Changeset d52ea1b


Ignore:
Timestamp:
Jun 7, 2008, 1:21:53 PM (17 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:
17ce5c
Parents:
65684f
Message:

Working version of PAS transformation (tested on C-S-H cluster) and code scaffold of VolumeOfConvexEnvelope that's untested so far

PAS simply calculates inertia tensor, diagonalizes it via GSL and transforms molecule into eigenvector system such that z axis is eigenvector of biggest eigenvalue.

Location:
src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/builder.cpp

    r65684f rd52ea1b  
    484484 * \param *mol the molecule with all the atoms
    485485 */
    486 static void MeasureAtoms(periodentafel *periode, molecule *mol)
     486static void MeasureAtoms(periodentafel *periode, molecule *mol, config *configuration)
    487487{
    488488  atom *first, *second, *third;
     
    496496  cout << Verbose(0) << " b - calculate bond length between two atoms" << endl;
    497497  cout << Verbose(0) << " c - calculate bond angle" << endl;
     498  cout << Verbose(0) << " d - calculate principal axis of the system" << endl;
     499  cout << Verbose(0) << " e - calculate volume of the convex envelope" << endl;
    498500  cout << Verbose(0) << "all else - go back" << endl;
    499501  cout << Verbose(0) << "===============================================" << endl;
     
    553555      cout << Verbose(0) << (acos(x.ScalarProduct((const vector *)&y)/(y.Norm()*x.Norm()))/M_PI*180.) << " degrees" << endl;         
    554556      break;
     557    case 'd':
     558        cout << Verbose(0) << "Evaluating prinicipal axis." << endl;
     559        cout << Verbose(0) << "Shall we rotate? [0/1]: ";
     560        cin >> Z;
     561        if ((Z >=0) && (Z <=1))
     562          mol->PrincipalAxisSystem((ofstream *)&cout, (bool)Z);
     563        else
     564          mol->PrincipalAxisSystem((ofstream *)&cout, false);
     565        break;
     566    case 'e':
     567        cout << Verbose(0) << "Evaluating volume of the convex envelope.";
     568        mol->VolumeOfConvexEnvelope((ofstream *)&cout, configuration->GetIsAngstroem());
     569        break;
    555570  }
    556571};
     
    745760            cout << "\t-f <dist> <order>\tFragments the molecule in BOSSANOVA manner and stores config files in same dir as config." << endl;
    746761            cout << "\t-h/-H/-?\tGive this help screen." << endl;
     762            cout << "\t-m\tAlign in PAS with greatest EV along z axis." << endl;
    747763            cout << "\t-p <file>\tParse given xyz file and create raw config file from it." << endl;
    748764            cout << "\t-r\t\tConvert file from an old pcp syntax." << endl;
     
    945961              }
    946962              break;
     963            case 'm':
     964              ExitFlag = 1;
     965              cout << Verbose(0) << "Evaluating prinicipal axis." << endl;
     966              mol->PrincipalAxisSystem((ofstream *)&cout, true);
     967              break;
    947968            default:   // no match? Step on
    948969              argptr++;
     
    11511172
    11521173      case 'l': // measure distances or angles
    1153         MeasureAtoms(periode, mol);
     1174        MeasureAtoms(periode, mol, &configuration);
    11541175        break;
    11551176
     
    11641185        mol->CreateAdjacencyList((ofstream *)&cout, tmp1, configuration.GetIsAngstroem());
    11651186        //mol->CreateListOfBondsPerAtom((ofstream *)&cout);
    1166         Subgraphs = mol->DepthFirstSearchAnalysis((ofstream *)&cout, false, MinimumRingSize);
     1187        Subgraphs = mol->DepthFirstSearchAnalysis((ofstream *)&cout, MinimumRingSize);
    11671188        while (Subgraphs->next != NULL) {
    11681189          Subgraphs = Subgraphs->next;
  • src/molecules.cpp

    r65684f rd52ea1b  
    179179  bond *FirstBond = NULL, *SecondBond = NULL; // Other bonds in double bond case to determine "other" plane
    180180  atom *FirstOtherAtom = NULL, *SecondOtherAtom = NULL, *ThirdOtherAtom = NULL; // pointer to hydrogen atoms to be added
    181   int i;  // loop variable
    182181  double b,l,d,f,g, alpha, factors[NDIM];    // hold temporary values in triple bond case for coordination determination
    183182  vector OrthoVector1, OrthoVector2;  // temporary vectors in coordination construction
     
    253252    case 2:
    254253      // determine two other bonds (warning if there are more than two other) plus valence sanity check
    255       for (i=0;i<NumBond;i++) {
     254      for (int i=0;i<NumBond;i++) {
    256255        if (BondList[i] != TopBond) {
    257256          if (FirstBond == NULL) {
     
    312311      FirstOtherAtom->x.Zero();
    313312      SecondOtherAtom->x.Zero();
    314       for(i=NDIM;i--;) { // rotate by half the bond angle in both directions (InBondVector is bondangle = 0 direction)
     313      for(int i=NDIM;i--;) { // rotate by half the bond angle in both directions (InBondVector is bondangle = 0 direction)
    315314        FirstOtherAtom->x.x[i] = InBondVector.x[i] * cos(bondangle) + OrthoVector1.x[i] * (sin(bondangle));
    316315        SecondOtherAtom->x.x[i] = InBondVector.x[i] * cos(bondangle) + OrthoVector1.x[i] * (-sin(bondangle));
     
    319318      SecondOtherAtom->x.Scale(&BondRescale);
    320319      //*out << Verbose(3) << "ReScaleCheck: " << FirstOtherAtom->x.Norm() << " and " << SecondOtherAtom->x.Norm() << "." << endl;
    321       for(i=NDIM;i--;) { // and make relative to origin atom
     320      for(int i=NDIM;i--;) { // and make relative to origin atom
    322321        FirstOtherAtom->x.x[i] += TopOrigin->x.x[i];
    323322        SecondOtherAtom->x.x[i] += TopOrigin->x.x[i];
     
    439438  int NumberOfAtoms = 0; // atom number in xyz read
    440439  int i, j; // loop variables
    441   atom *first = NULL;  // pointer to added atom
     440  atom *Walker = NULL;  // pointer to added atom
    442441  char shorthand[3];  // shorthand for atom name
    443442  ifstream xyzfile;   // xyz file
     
    457456
    458457  for(i=0;i<NumberOfAtoms;i++){
    459     first = new atom;
     458    Walker = new atom;
    460459    getline(xyzfile,line,'\n');
    461460    istringstream *item = new istringstream(line);
     
    466465    *item >> x[1];
    467466    *item >> x[2];
    468     first->type = elemente->FindElement(shorthand);
    469     if (first->type == NULL) {
     467    Walker->type = elemente->FindElement(shorthand);
     468    if (Walker->type == NULL) {
    470469      cerr << "Could not parse the element at line: '" << line << "', setting to H.";
    471       first->type = elemente->FindElement(1);
     470      Walker->type = elemente->FindElement(1);
    472471    }
    473472    for(j=NDIM;j--;)
    474       first->x.x[j] = x[j];
    475      AddAtom(first);  // add to molecule
     473      Walker->x.x[j] = x[j];
     474     AddAtom(Walker);  // add to molecule
    476475    delete(item);
    477476  }
     
    710709};
    711710
    712 /** Centers the center of gravity of the atoms at (0,0,0).
     711/** Returns vector pointing to center of gravity.
    713712 * \param *out output stream for debugging
    714  * \param *center return vector for translation vector
    715  */
    716 void molecule::CenterGravity(ofstream *out, vector *center)
    717 {
     713 * \return pointer to center of gravity vector
     714 */
     715vector * molecule::DetermineCenterOfGravity(ofstream *out)
     716{
     717        atom *ptr = start->next;  // start at first in list
     718        vector *a = new vector();
     719        vector tmp;
    718720  double Num = 0;
    719   atom *ptr = start->next;  // start at first in list
    720   vector tmp;
    721  
    722   for(int i=NDIM;i--;) // zero center vector
    723     center->x[i] = 0.;
    724    
     721       
     722        a->Zero();
     723
    725724  if (ptr != end) {   //list not empty?
    726725    while (ptr->next != end) {  // continue with second if present
     
    729728      tmp.CopyVector(&ptr->x);
    730729      tmp.Scale(ptr->type->mass);  // scale by mass
    731       center->AddVector(&tmp);       
    732     }
    733     center->Scale(-1./Num); // divide through total mass (and sign for direction)
     730      a->AddVector(&tmp);       
     731    }
     732    a->Scale(-1./Num); // divide through total mass (and sign for direction)
     733  }
     734  *out << Verbose(1) << "Resulting center of gravity: ";
     735  a->Output(out);
     736  *out << endl;
     737  return a;
     738};
     739
     740/** Centers the center of gravity of the atoms at (0,0,0).
     741 * \param *out output stream for debugging
     742 * \param *center return vector for translation vector
     743 */
     744void molecule::CenterGravity(ofstream *out, vector *center)
     745{
     746  if (center == NULL) {
     747    DetermineCenter(*center);
     748    Translate(center);
     749    delete(center);
     750  } else {
    734751    Translate(center);
    735752  }
     
    775792};
    776793
    777 /** Determines center of gravity (yet not considering atom masses).
    778  * \param CenterOfGravity reference to return vector
    779  */
    780 void molecule::DetermineCenterOfGravity(vector &CenterOfGravity)
     794/** Determines center of molecule (yet not considering atom masses).
     795 * \param Center reference to return vector
     796 */
     797void molecule::DetermineCenter(vector &Center)
    781798{
    782799  atom *Walker = start;
     
    788805 
    789806  do {
    790     CenterOfGravity.Zero();
     807    Center.Zero();
    791808    flag = true;
    792809    while (Walker->next != end) {
     
    815832        TestVector.AddVector(&TranslationVector);
    816833        TestVector.MatrixMultiplication(matrix);
    817         CenterOfGravity.AddVector(&TestVector);
     834        Center.AddVector(&TestVector);
    818835        cout << Verbose(1) << "Vector is: ";
    819836        TestVector.Output((ofstream *)&cout);
     
    828845            TestVector.AddVector(&TranslationVector);
    829846            TestVector.MatrixMultiplication(matrix);
    830             CenterOfGravity.AddVector(&TestVector);
     847            Center.AddVector(&TestVector);
    831848            cout << Verbose(1) << "Hydrogen Vector is: ";
    832849            TestVector.Output((ofstream *)&cout);
     
    838855    }
    839856  } while (!flag);
    840   Free((void **)&matrix, "molecule::DetermineCenterOfGravity: *matrix");
    841   CenterOfGravity.Scale(1./(double)AtomCount);
     857  Free((void **)&matrix, "molecule::DetermineCenter: *matrix");
     858  Center.Scale(1./(double)AtomCount);
     859};
     860
     861/** Transforms/Rotates the given molecule into its principal axis system.
     862 * \param *out output stream for debugging
     863 * \param DoRotate whether to rotate (true) or only to determine the PAS.
     864 */
     865void molecule::PrincipalAxisSystem(ofstream *out, bool DoRotate)
     866{
     867        atom *ptr = start;  // start at first in list
     868        double InertiaTensor[NDIM*NDIM];
     869        vector *CenterOfGravity = DetermineCenterOfGravity(out);
     870
     871        CenterGravity(out, CenterOfGravity);
     872       
     873        // reset inertia tensor
     874        for(int i=0;i<NDIM*NDIM;i++)
     875                InertiaTensor[i] = 0.;
     876       
     877        // sum up inertia tensor
     878        while (ptr->next != end) {
     879                ptr = ptr->next;
     880                vector x;
     881                x.CopyVector(&ptr->x);
     882                //x.SubtractVector(CenterOfGravity);
     883                InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]);
     884                InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]);
     885                InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]);
     886                InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]);
     887                InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]);
     888                InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]);
     889                InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]);
     890                InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]);
     891                InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]);
     892        }
     893        // print InertiaTensor for debugging
     894        *out << "The inertia tensor is:" << endl;
     895        for(int i=0;i<NDIM;i++) {
     896          for(int j=0;j<NDIM;j++)
     897            *out << InertiaTensor[i*NDIM+j] << " ";
     898          *out << endl;
     899        }
     900        *out << endl;
     901       
     902        // diagonalize to determine principal axis system
     903        gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(NDIM);
     904        gsl_matrix_view m = gsl_matrix_view_array(InertiaTensor, NDIM, NDIM);
     905        gsl_vector *eval = gsl_vector_alloc(NDIM);
     906        gsl_matrix *evec = gsl_matrix_alloc(NDIM, NDIM);
     907        gsl_eigen_symmv(&m.matrix, eval, evec, T);
     908        gsl_eigen_symmv_free(T);
     909        gsl_eigen_symmv_sort(eval, evec, GSL_EIGEN_SORT_ABS_DESC);
     910       
     911        for(int i=0;i<NDIM;i++) {
     912                *out << Verbose(1) << "eigenvalue = " << gsl_vector_get(eval, i);
     913                *out << ", eigenvector = (" << evec->data[i * evec->tda + 0] << "," << evec->data[i * evec->tda + 1] << "," << evec->data[i * evec->tda + 2] << ")" << endl;
     914        }
     915       
     916        // check whether we rotate or not
     917        if (DoRotate) {
     918          *out << Verbose(1) << "Transforming molecule into PAS ... ";
     919          // the eigenvectors specify the transformation matrix
     920          ptr = start;
     921          while (ptr->next != end) {
     922            ptr = ptr->next;
     923            ptr->x.MatrixMultiplication(evec->data);
     924          }
     925          *out << "done." << endl;
     926
     927          // summing anew for debugging (resulting matrix has to be diagonal!)
     928          // reset inertia tensor
     929    for(int i=0;i<NDIM*NDIM;i++)
     930      InertiaTensor[i] = 0.;
     931   
     932    // sum up inertia tensor
     933    ptr = start;
     934    while (ptr->next != end) {
     935      ptr = ptr->next;
     936      vector x;
     937      x.CopyVector(&ptr->x);
     938      //x.SubtractVector(CenterOfGravity);
     939      InertiaTensor[0] += ptr->type->mass*(x.x[1]*x.x[1] + x.x[2]*x.x[2]);
     940      InertiaTensor[1] += ptr->type->mass*(-x.x[0]*x.x[1]);
     941      InertiaTensor[2] += ptr->type->mass*(-x.x[0]*x.x[2]);
     942      InertiaTensor[3] += ptr->type->mass*(-x.x[1]*x.x[0]);
     943      InertiaTensor[4] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[2]*x.x[2]);
     944      InertiaTensor[5] += ptr->type->mass*(-x.x[1]*x.x[2]);
     945      InertiaTensor[6] += ptr->type->mass*(-x.x[2]*x.x[0]);
     946      InertiaTensor[7] += ptr->type->mass*(-x.x[2]*x.x[1]);
     947      InertiaTensor[8] += ptr->type->mass*(x.x[0]*x.x[0] + x.x[1]*x.x[1]);
     948    }
     949    // print InertiaTensor for debugging
     950    *out << "The inertia tensor is:" << endl;
     951    for(int i=0;i<NDIM;i++) {
     952      for(int j=0;j<NDIM;j++)
     953        *out << InertiaTensor[i*NDIM+j] << " ";
     954      *out << endl;
     955    }
     956    *out << endl;
     957        }
     958       
     959        // free everything
     960        delete(CenterOfGravity);
     961        gsl_vector_free(eval);
     962        gsl_matrix_free(evec);
    842963};
    843964
     
    12341355  if ((Binder->next != last) && (Binder->next->Type == Undetermined)) {
    12351356    *out << Verbose(0) << "No Depth-First-Search analysis performed so far, calling ..." << endl;
    1236     Subgraphs = DepthFirstSearchAnalysis(out, false, MinimumRingSize);
     1357    Subgraphs = DepthFirstSearchAnalysis(out, MinimumRingSize);
    12371358    while (Subgraphs->next != NULL) {
    12381359      Subgraphs = Subgraphs->next;
     
    12481369  }
    12491370  return No;
     1371};
     1372
     1373/** Determines the volume of a cluster.
     1374 * Determines first the convex envelope, then tesselates it and calculates its volume.
     1375 * \param *out output stream for debugging
     1376 * \param IsAngstroem for the units on output
     1377 */
     1378double molecule::VolumeOfConvexEnvelope(ofstream *out, bool IsAngstroem)
     1379{
     1380        atom *Walker = NULL;
     1381       
     1382        // 1. calculate center of gravity
     1383        vector *CenterOfGravity = DetermineCenterOfGravity(out);
     1384       
     1385        // 2. calculate distance of each atom and sort into hash table
     1386//      map<double, int> DistanceSet;
     1387//     
     1388//      Walker = start;
     1389//      while (Walker->next != end) {
     1390//              Walker = Walker->next;
     1391//              DistanceSet.insert( pair<double, int>(ptr->x.distance(CenterOfGravity), ptr->nr) );
     1392//      }
     1393       
     1394        // 3. Find all points on the boundary
     1395        Boundaries BoundaryPoints[NDIM];        // first is alpha, second is (r, nr)
     1396        BoundariesTestPair BoundaryTestPair;
     1397        vector AxisVector;
     1398        // 3a. Go through every axis
     1399        for (int axis=0; axis<NDIM; axis++)  {
     1400                AxisVector.Zero();
     1401                AxisVector.x[axis] = 1.;
     1402                // 3b. construct set of all points, transformed into cylindrical system and with left and right neighbours
     1403                Walker = start;
     1404                while (Walker->next != end) {
     1405                        Walker = Walker->next;
     1406                        vector ProjectedVector;
     1407                        ProjectedVector.CopyVector(&Walker->x);
     1408                        ProjectedVector.Scale(-1.*Walker->x.Projection(&AxisVector));
     1409                        ProjectedVector.AddVector(&Walker->x);  // subtract projection from vector
     1410                        BoundaryTestPair = BoundaryPoints[axis].insert( BoundariesPair (ProjectedVector.Angle(&AxisVector), DistanceNrPair (ProjectedVector.Norm(), Walker) ) );
     1411                        if (BoundaryTestPair.second) { // successfully inserted
     1412                        } else { // same point exists, check first r, then distance of original vectors to centers of gravity
     1413                                *out << Verbose(2) << "Encountered two vectors whose projection onto axis " << axis << " is equal: " << endl;
     1414                                *out << Verbose(2) << "Present vector: ";
     1415                                BoundaryTestPair.first->second.second->x.Output(out);
     1416                                *out << endl;
     1417                                *out << Verbose(2) << "New vector: ";
     1418                                Walker->x.Output(out);
     1419                                *out << endl;
     1420                                double tmp = ProjectedVector.Norm();
     1421                                if (tmp > BoundaryTestPair.first->second.first) {
     1422                                        BoundaryTestPair.first->second.first = tmp;
     1423                                        BoundaryTestPair.first->second.second = Walker;
     1424                                        *out << Verbose(2) << "Keeping new vector." << endl;
     1425                                } else if (tmp == BoundaryTestPair.first->second.first) {
     1426                                        if (BoundaryTestPair.first->second.second->x.Distance(CenterOfGravity) < Walker->x.Distance(CenterOfGravity)) {
     1427                                                BoundaryTestPair.first->second.second = Walker;
     1428                                                *out << Verbose(2) << "Keeping new vector." << endl;
     1429                                        } else {
     1430                                                *out << Verbose(2) << "Keeping present vector." << endl;
     1431                                        }
     1432                                } else {
     1433                                                *out << Verbose(2) << "Keeping present vector." << endl;
     1434                                }
     1435                        }
     1436                }
     1437                // 3c. throw out points whose distance is less than the mean of left and right neighbours
     1438                bool flag = false;
     1439                do { // do as long as we still throw one out per round
     1440                        flag = false;
     1441                        Boundaries::iterator left = BoundaryPoints[axis].end();
     1442                        Boundaries::iterator right = BoundaryPoints[axis].end();
     1443                        for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
     1444                                // set neighbours correctly
     1445                                if (runner == BoundaryPoints[axis].begin()) {
     1446                                        left = BoundaryPoints[axis].end();
     1447                                }       else {
     1448                                        left = runner;
     1449                                }
     1450        left--;
     1451        right = runner;
     1452        right++;
     1453                                if (right == BoundaryPoints[axis].end()) {
     1454                                        right = BoundaryPoints[axis].begin();
     1455                                }
     1456                                // check distance
     1457                                if (runner->second.first < (left->second.first + right->second.first)/2. ) {
     1458                                        // throw out point
     1459                                        BoundaryPoints[axis].erase(runner);
     1460                                        flag = true;
     1461                                }
     1462                        }
     1463                } while (flag);
     1464        }       
     1465        // 3d. put into boundary set only those points appearing in each of the NDIM sets
     1466        int *AtomList = new int[AtomCount];
     1467        for (int j=0; j<AtomCount; j++) // reset list
     1468                AtomList[j] = 0;
     1469        for (int axis=0; axis<NDIM; axis++)  {  // increase whether it's present
     1470                for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
     1471                        AtomList[runner->second.second->nr]++;
     1472                }
     1473        }
     1474        int BoundaryPointCount = 0;
     1475        Walker = start;
     1476        while (Walker->next != end) {
     1477                Walker = Walker->next;
     1478                if (AtomList[Walker->nr] < NDIM) {      // enter all neighbouring points
     1479                        BoundaryPointCount++;
     1480                }
     1481        }
     1482       
     1483        // 3e. Points no more in the total list, have to be thrown out of each axis lists too!
     1484        for (int axis=0; axis<NDIM; axis++)  {
     1485                for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
     1486                        if (AtomList[runner->second.second->nr] < NDIM)
     1487                                BoundaryPoints[axis].erase(runner);
     1488                }
     1489        }
     1490
     1491        *out << Verbose(2) << "I found " << BoundaryPointCount << " points on the convex boundary." << endl;
     1492        // now we have the whole set of edge points in the BoundaryList
     1493       
     1494        // 4. Create each possible line, number them and put them into a list (3 * AtomCount possible)
     1495        struct lines {
     1496                atom *x[2];
     1497                int nr;
     1498        } LinesList[3 * AtomCount];
     1499       
     1500        // initialise reference storage (needed lateron)
     1501        int **AtomLines = new int *[AtomCount];
     1502        Walker = start;
     1503        while (Walker->next != end) {   // go through all points
     1504                Walker = Walker->next;
     1505                if (AtomList[Walker->nr] == NDIM) {     // if this is a boundary point
     1506                        AtomLines[Walker->nr] = new int[NDIM];
     1507                        for(int axis=0;axis<NDIM;axis++) {
     1508                                AtomLines[Walker->nr][2*axis+0] = -1;
     1509                                AtomLines[Walker->nr][2*axis+1] = -1;
     1510                        }
     1511                }
     1512        }
     1513       
     1514        // then create each line
     1515  int LineCount = 0;
     1516        for(int axis=0;axis<NDIM;axis++) {      // go through every axis
     1517          for(Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++) {
     1518            // get left and right neighbours
     1519            Boundaries::iterator NN[2] = runner;
     1520            if (NN[0] == BoundaryPoints[axis].begin())
     1521              NN[0] = BoundaryPoints[axis].end();
     1522            NN[0]--;
     1523            NN[1] = runner;
     1524      NN[1]++;
     1525      if (NN[1] == BoundaryPoints[axis].end())
     1526        NN[1] = BoundaryPoints[axis].begin();
     1527      // check those neighbours for their atomic index
     1528      for (int k=0;k<2;k++) {
     1529                        if (runner->second.second->nr > NN[k]->second.second->nr) { // check left neighbour on this projected axis
     1530                                LinesList[LineCount].x[0] = runner->second.second;
     1531                                LinesList[LineCount].x[1] = NN[k]->second.second;
     1532                                if (AtomLines[LinesList[LineCount].x[0]->nr][axis] == -1) {
     1533                                        AtomLines[LinesList[LineCount].x[0]->nr][axis] = LineCount;
     1534                                } else if (AtomLines[LinesList[LineCount].x[1]->nr][axis] == -1) {
     1535                                        AtomLines[LinesList[LineCount].x[1]->nr][axis] = LineCount;
     1536                                } else {
     1537                                        *out << Verbose(2) << "Could not store line number " << LineCount << "." << endl;
     1538                                }
     1539                                LineCount++;
     1540                        }
     1541      }
     1542                }
     1543        }
     1544        *out << Verbose(2) << "I created " << LineCount << " edges." << endl;
     1545       
     1546        // 5. Create every possible triangle from the lines (numbering of each line must be i < j < k)
     1547        struct triangles {
     1548                atom *x1;
     1549                atom *x2;
     1550                atom *x3;
     1551                int nr;
     1552        } TriangleList[2 * 3 * AtomCount];      // each line can be part in at most 2 triangles
     1553        int TriangleCount = 0;
     1554        for (int i=0; i<LineCount; i++) {       // go through every line
     1555                LinetoAtomMap LinetoAtom;
     1556                // we have two points, check the lines at either end, whether they share a common endpoint
     1557                for (int endpoint=0;endpoint<2;endpoint++) {
     1558                        Walker = LinesList[LineCount].x[endpoint];             
     1559                        for (int axis=0;axis<NDIM;axis++) {
     1560                                LinetoAtomTestPair LinetoAtomTest;
     1561                                LinetoAtomPair InsertionPair = LinetoAtomPair(-1, NULL);
     1562                                struct lines *TempLine = &LinesList[ AtomLines[Walker->nr][axis] ];
     1563                                if (AtomLines[Walker->nr][axis] != LineCount) {
     1564                                        if (TempLine->x[0] != Walker) {
     1565                                                InsertionPair = LinetoAtomPair(TempLine->x[0]->nr, TempLine->x[0]);
     1566                                        } else if (TempLine->x[1] != Walker) {
     1567                                                InsertionPair = LinetoAtomPair(TempLine->x[1]->nr, TempLine->x[0]);
     1568                                        } else {
     1569                                                *out << Verbose(2) << "Atom " << *Walker << "is both the end of line " << AtomLines[Walker->nr][axis] << "." << endl;
     1570                                        }
     1571                                        if (InsertionPair.first != -1)          // insert if present
     1572                                                LinetoAtomTest = LinetoAtom.insert( InsertionPair );
     1573                                        if (!LinetoAtomTest.second) {
     1574                                                // atom is already present in list, hence we have found a possible triangle
     1575                                                if ((Walker->nr < LinetoAtomTest.first->first) && (LinetoAtomTest.first->first < InsertionPair.first)) {        // check if numbering is in correct order for uniqueness, if so add
     1576                                                        TriangleList[TriangleCount].x1 = Walker;
     1577                                                        TriangleList[TriangleCount].x2 = LinetoAtomTest.first->second;
     1578                                                        TriangleList[TriangleCount].x3 = InsertionPair.second;
     1579                                                        TriangleCount++;
     1580                                                }
     1581                                        }       //else {   // check if insertion was successful
     1582          // successfully inserted, hence nothing found yet
     1583        //}
     1584                                }
     1585                        }
     1586                }
     1587        }
     1588        *out << Verbose(2) << "I created " << TriangleCount << " triangles." << endl;
     1589
     1590        // 6. Every triangle forms a pyramid with the center of gravity as its peak, sum up the volumes
     1591        double volume = 0.;
     1592        double PyramidVolume = 0.;
     1593        double G,h;
     1594        vector x,y;
     1595        double a,b,c;
     1596        for (int i=0; i<TriangleCount; i++) { // go through every triangle, calculate volume of its pyramid with CoG as peak
     1597                x.CopyVector(&TriangleList[TriangleCount].x1->x);
     1598                x.SubtractVector(&TriangleList[TriangleCount].x2->x);
     1599                y.CopyVector(&TriangleList[TriangleCount].x1->x);
     1600                y.SubtractVector(&TriangleList[TriangleCount].x3->x);
     1601                a = sqrt(TriangleList[TriangleCount].x1->x.Distance(&TriangleList[TriangleCount].x2->x));
     1602                b = sqrt(TriangleList[TriangleCount].x1->x.Distance(&TriangleList[TriangleCount].x3->x));
     1603                c = sqrt(TriangleList[TriangleCount].x3->x.Distance(&TriangleList[TriangleCount].x2->x));
     1604                G =  c * (sin(x.Angle(&y))*a); // area of tesselated triangle
     1605                x.MakeNormalVector(&TriangleList[TriangleCount].x1->x, &TriangleList[TriangleCount].x2->x, &TriangleList[TriangleCount].x3->x);
     1606                y.CopyVector(&x);
     1607                x.Scale(CenterOfGravity->Projection(&x));
     1608                h = x.Norm(); // distance of CoG to triangle
     1609                PyramidVolume = (1./3.) * G * h;                // this formula holds for _all_ pyramids (independent of n-edge base or (not) centered peak)
     1610                volume += PyramidVolume;
     1611        }
     1612        *out << Verbose(1) << "The summed volume is " << volume << " " << (IsAngstroem ? "A^3" : "a_0^3") << "." << endl;
     1613
     1614        // free reference lists
     1615        delete[](AtomList);
     1616  for(int i=0;i<AtomCount;i++)
     1617    delete[](AtomLines[i]);
     1618  delete[](AtomLines);
     1619
     1620        return volume;
    12501621};
    12511622
     
    14901861 * We use the algorithm from [Even, Graph Algorithms, p.62].
    14911862 * \param *out output stream for debugging
    1492  * \param ReturnStack true - return pointer to atom stack of separable components, false - return NULL
    14931863 * \param *&MinimumRingSize contains smallest ring size in molecular structure on return or -1 if no rings were found
    14941864 * \return list of each disconnected subgraph as an individual molecule class structure
    14951865 */
    1496 MoleculeLeafClass * molecule::DepthFirstSearchAnalysis(ofstream *out, bool ReturnStack, int *&MinimumRingSize)
     1866MoleculeLeafClass * molecule::DepthFirstSearchAnalysis(ofstream *out, int *&MinimumRingSize)
    14971867{
    14981868  class StackClass<atom *> *AtomStack;
     
    20062376 * \param *path path to file
    20072377 * \param *FragmentList empty, filled on return
    2008  * \param IsAngstroem whether we have Ansgtroem or bohrradius
    20092378 * \return true - parsing successfully, false - failure on parsing (FragmentList will be NULL)
    20102379 */
    2011 bool molecule::ParseKeySetFile(ofstream *out, char *path, Graph *&FragmentList, bool IsAngstroem)
     2380bool molecule::ParseKeySetFile(ofstream *out, char *path, Graph *&FragmentList)
    20122381{
    20132382  bool status = true;
     
    21862555{
    21872556  ifstream File;
    2188   stringstream line;
     2557  stringstream filename;
    21892558  bool status = true;
    21902559  char *buffer = (char *) Malloc(sizeof(char)*MAXSTRINGSIZE, "molecule::CheckAdjacencyFileAgainstMolecule: *buffer");
    21912560 
    2192   line << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;
    2193   File.open(line.str().c_str(), ios::out);
     2561  filename << path << "/" << FRAGMENTPREFIX << ADJACENCYFILE;
     2562  File.open(filename.str().c_str(), ios::out);
    21942563  *out << Verbose(1) << "Looking at bond structure stored in adjacency file and comparing to present one ... ";
    21952564  if (File != NULL) {
     
    24932862
    24942863  // ===== 2. perform a DFS analysis to gather info on cyclic structure and a list of disconnected subgraphs =====
    2495   Subgraphs = DepthFirstSearchAnalysis(out, false, MinimumRingSize);
     2864  Subgraphs = DepthFirstSearchAnalysis(out, MinimumRingSize);
    24962865  // fill the bond structure of the individually stored subgraphs
    24972866  Subgraphs->next->FillBondStructureFromReference(out, this, (FragmentCounter = 0), ListOfLocalAtoms, false);  // we want to keep the created ListOfLocalAtoms
    24982867
    24992868  // ===== 3. if structure still valid, parse key set file and others =====
    2500   FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList, configuration->GetIsAngstroem());
     2869  FragmentationToDo = FragmentationToDo && ParseKeySetFile(out, configuration->configpath, ParsedFragmentList);
    25012870
    25022871  // ===== 4. check globally whether there's something to do actually (first adaptivity check)
     
    34213790  KeyStack AtomStack;
    34223791  atom **PredecessorList = (atom **) Malloc(sizeof(atom *)*AtomCount, "molecule::PowerSetGenerator: **PredecessorList");
    3423   KeySet::iterator runner;
    34243792  int RootKeyNr = FragmentSearch.Root->nr;
    34253793  int Counter = FragmentSearch.FragmentCounter;
     
    38164184{
    38174185  Graph ***FragmentLowerOrdersList = NULL;
    3818   int Order, NumLevels, NumMolecules, TotalNumMolecules = 0, *NumMoleculesOfOrder = NULL;
    3819   int counter = 0;
     4186  int NumLevels, NumMolecules, TotalNumMolecules = 0, *NumMoleculesOfOrder = NULL;
     4187  int counter = 0, Order;
    38204188  int UpgradeCount = RootStack.size();
    38214189  KeyStack FragmentRootStack;
     
    38314199
    38324200  // initialise the fragments structure
    3833   FragmentSearch.BondsPerSPList = (bond **) Malloc(sizeof(bond *)*Order*2, "molecule::PowerSetGenerator: ***BondsPerSPList");
    3834   FragmentSearch.BondsPerSPCount = (int *) Malloc(sizeof(int)*Order, "molecule::PowerSetGenerator: *BondsPerSPCount");
    38354201  FragmentSearch.ShortestPathList = (int *) Malloc(sizeof(int)*AtomCount, "molecule::PowerSetGenerator: *ShortestPathList");
    38364202  FragmentSearch.Labels = (int *) Malloc(sizeof(int)*AtomCount, "molecule::PowerSetGenerator: *Labels");
     
    40594425  if (result) {
    40604426    *out << Verbose(5) << "Calculating Centers of Gravity" << endl;
    4061     DetermineCenterOfGravity(CenterOfGravity);
    4062     OtherMolecule->DetermineCenterOfGravity(OtherCenterOfGravity);
     4427    DetermineCenter(CenterOfGravity);
     4428    OtherMolecule->DetermineCenter(OtherCenterOfGravity);
    40634429    *out << Verbose(5) << "Center of Gravity: ";
    40644430    CenterOfGravity.Output(out);
  • src/molecules.hpp

    r65684f rd52ea1b  
    1313#include <gsl/gsl_vector.h>
    1414#include <gsl/gsl_matrix.h>
     15#include <gsl/gsl_eigen.h>
    1516#include <gsl/gsl_heapsort.h>
    1617
     
    4344#define KeySetTestPair pair<KeySet::iterator, bool>
    4445#define GraphTestPair pair<Graph::iterator, bool>
     46
     47#define DistanceNrPair pair< double, atom* >
     48#define Boundaries map <double, DistanceNrPair >
     49#define BoundariesPair pair<double, DistanceNrPair >
     50#define BoundariesTestPair pair<Boundaries::iterator, bool>
     51#define LinetoAtomMap map < int, atom * >
     52#define LinetoAtomPair pair < int, atom * >
     53#define LinetoAtomTestPair pair < LinetoAtomMap::iterator, bool>
    4554
    4655struct KeyCompare
     
    265274  void CenterEdge(ofstream *out, vector *max);
    266275  void CenterOrigin(ofstream *out, vector *max);
    267   void CenterGravity(ofstream *out, vector *max); 
     276  void CenterGravity(ofstream *out, vector *max);
    268277  void Translate(const vector *x);
    269278  void Mirror(const vector *x);
    270279  void Align(vector *n);
    271280  void Scale(double **factor);
    272   void DetermineCenterOfGravity(vector &CenterOfGravity);
     281  void DetermineCenter(vector &center);
     282  vector * DetermineCenterOfGravity(ofstream *out);
    273283  void SetBoxDimension(vector *dim);
    274284  double * ReturnFullMatrixforSymmetric(double *cell_size);
    275285  void ScanForPeriodicCorrection(ofstream *out);
    276 
     286        void PrincipalAxisSystem(ofstream *out, bool DoRotate);
     287        double VolumeOfConvexEnvelope(ofstream *out, bool IsAngstroem);
     288       
    277289  bool CheckBounds(const vector *x) const;
    278290  void GetAlignVector(struct lsq_params * par) const;
     
    283295 
    284296  // Graph analysis
    285   MoleculeLeafClass * DepthFirstSearchAnalysis(ofstream *out, bool ReturnStack, int *&MinimumRingSize);
     297  MoleculeLeafClass * DepthFirstSearchAnalysis(ofstream *out, int *&MinimumRingSize);
    286298  void CyclicStructureAnalysis(ofstream *out, class StackClass<bond *> *BackEdgeStack, int *&MinimumRingSize);
    287299  bond * FindNextUnused(atom *vertex);
     
    303315  bool ParseOrderAtSiteFromFile(ofstream *out, char *path);
    304316  bool StoreOrderAtSiteFile(ofstream *out, char *path);
    305   bool ParseKeySetFile(ofstream *out, char *filename, Graph *&FragmentList, bool IsAngstroem);
     317  bool ParseKeySetFile(ofstream *out, char *filename, Graph *&FragmentList);
    306318  bool StoreKeySetFile(ofstream *out, Graph &KeySetList, char *path);
    307319  bool StoreForcesFile(ofstream *out, MoleculeListClass *BondFragments, char *path, int *SortIndex);
Note: See TracChangeset for help on using the changeset viewer.