Changeset 41baaf for src


Ignore:
Timestamp:
Jul 30, 2008, 1:11:30 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:
af6d8f
Parents:
683914
Message:

2 BUGFIXES: CreateAdjacencyList() and CyclicStructureAnalysis()

CreateAdjacencyList(): with benzophenone and indigo it was found that the correction of the bond degree was not working properly. Carbon bound to oxygen and other carbons would not raise the bond degree to oxygen preferentially over the carbon bonds, which lead to wrong bond degrees in the end. We refrained from using matrix schemes as these are not O(N) in a simple manner, but remained with the local scheme that now checks each also mismatching bond partner for its number of bonds and takes preferentially the one with the fewest bonds as the increase candidate.
CyclicStructureAnalysis(): with biphenylene and cholesterol it was found that the cycle detection did not work as expected. Cycles were found twice due to a back edge being shared by two cycles at the same time (and it's randomly dependend on the vertex ids which cycle is found first). Hence, we now do a backtracking of a cycle candidate, looking whether each of its vertices is not already set to be cyclic. If so, we removed the last added vertices from lists and stacks (i.e. the closing edges), so that the other BFS finger with the real candidate may still reach the looked-for backedge (otherwise the vertex would be marked gray and hence not visited).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/molecules.cpp

    r683914 r41baaf  
    14421442void molecule::CreateAdjacencyList(ofstream *out, double bonddistance, bool IsAngstroem)
    14431443{
    1444   atom *Walker = NULL, *OtherWalker = NULL;
    1445   int No, NoBonds;
     1444  atom *Walker = NULL, *OtherWalker = NULL, *Candidate = NULL;
     1445  int No, NoBonds, CandidateBondNo;
    14461446  int NumberCells, divisor[NDIM], n[NDIM], N[NDIM], index, Index, j;
    14471447  molecule **CellList;
     
    15561556    CreateListOfBondsPerAtom(out);
    15571557               
    1558     // correct Bond degree of each bond by checking of updated(!) sum of bond degree for an atom match its valence count
    1559     // bond degrres are correctled iteratively by one, so that 2-2 instead of 1-3 or 3-1 corrections are favoured: We want
    1560     // a rather symmetric distribution of higher bond degrees
     1558    // correct Bond degree of each bond by checking both bond partners for a mismatch between valence and current sum of bond degrees,
     1559    // iteratively increase the one first where the other bond partner has the fewest number of bonds (i.e. in general bonds oxygene
     1560    // preferred over carbon bonds). Beforehand, we had picked the first mismatching partner, which lead to oxygenes with single instead of
     1561    // double bonds as was expected.
    15611562                if (BondCount != 0) {
    15621563      NoCyclicBonds = 0;
     
    15671568        while (Walker->next != end) { // go through every atom
    15681569          Walker = Walker->next;
    1569           for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through each of its bond partners
    1570             OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
    1571                   // count valence of first partner (updated!), might have changed during last bond partner
    1572                   NoBonds = 0;
    1573             for(j=0;j<NumberOfBondsPerAtom[Walker->nr];j++)
    1574               NoBonds += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;
    1575                   *out << Verbose(3) << "Walker: " << (int)Walker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;
    1576                   if ((int)(Walker->type->NoValenceOrbitals) > NoBonds) { // we have a mismatch, check NoBonds of other atom
     1570          // count valence of first partner
     1571          NoBonds = 0;
     1572          for(j=0;j<NumberOfBondsPerAtom[Walker->nr];j++)
     1573            NoBonds += ListOfBondsPerAtom[Walker->nr][j]->BondDegree;
     1574          *out << Verbose(3) << "Walker " << *Walker << ": " << (int)Walker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;
     1575          if ((int)(Walker->type->NoValenceOrbitals) > NoBonds) { // we have a mismatch, check all bonding partners for mismatch
     1576            Candidate = NULL;
     1577            for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) { // go through each of its bond partners
     1578              OtherWalker = ListOfBondsPerAtom[Walker->nr][i]->GetOtherAtom(Walker);
    15771579                    // count valence of second partner
    15781580              NoBonds = 0;
    15791581              for(j=0;j<NumberOfBondsPerAtom[OtherWalker->nr];j++)
    15801582                NoBonds += ListOfBondsPerAtom[OtherWalker->nr][j]->BondDegree;
    1581               *out << Verbose(3) << "OtherWalker: " << (int)OtherWalker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;
    1582                     if ((int)(OtherWalker->type->NoValenceOrbitals) > NoBonds) // increase bond degree by one
    1583                 ListOfBondsPerAtom[Walker->nr][i]->BondDegree++;
     1583              *out << Verbose(3) << "OtherWalker " << *OtherWalker << ": " << (int)OtherWalker->type->NoValenceOrbitals << " > " << NoBonds << "?" << endl;
     1584                    if ((int)(OtherWalker->type->NoValenceOrbitals) > NoBonds) { // check if possible candidate
     1585                      if ((Candidate == NULL) || (NumberOfBondsPerAtom[Candidate->nr] > NumberOfBondsPerAtom[OtherWalker->nr])) { // pick the one with fewer number of bonds first
     1586                  Candidate = OtherWalker;
     1587                  CandidateBondNo = i;
     1588                        *out << Verbose(3) << "New candidate is " << *Candidate << "." << endl;
     1589                      }
     1590                    }
    15841591                  }
     1592            if (Candidate != NULL) {
     1593              ListOfBondsPerAtom[Walker->nr][CandidateBondNo]->BondDegree++;
     1594              *out << Verbose(2) << "Increased bond degree for bond " << *ListOfBondsPerAtom[Walker->nr][CandidateBondNo] << "." << endl;
     1595            }
    15851596          }
    15861597                    }
     
    18011812
    18021813/** Analyses the cycles found and returns minimum of all cycle lengths.
     1814 * We begin with a list of Back edges found during DepthFirstSearchAnalysis(). We go through this list - one end is the Root,
     1815 * the other our initial Walker - and do a Breadth First Search for the Root. We mark down each Predecessor and as soon as
     1816 * we have found the Root via BFS, we may climb back the closed cycle via the Predecessors. Thereby we mark atoms and bonds
     1817 * as cyclic and print out the cycles.
    18031818 * \param *out output stream for debugging
    18041819 * \param *BackEdgeStack stack with all back edges found during DFS scan
     
    18121827  enum Shading *ColorList = (enum Shading *) Malloc(sizeof(enum Shading)*AtomCount, "molecule::CyclicStructureAnalysis: *ColorList");
    18131828  class StackClass<atom *> *BFSStack = new StackClass<atom *> (AtomCount);   // will hold the current ring
    1814   class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount);   // contains all "touched" atoms
     1829  class StackClass<atom *> *TouchedStack = new StackClass<atom *> (AtomCount);   // contains all "touched" atoms (that need to be reset after BFS loop)
    18151830  atom *Walker = NULL, *OtherAtom = NULL, *Root = NULL;
    18161831  bond *Binder = NULL, *BackEdge = NULL;
     
    18431858    BFSStack->Push(Walker);
    18441859    TouchedStack->Push(Walker);
    1845     //*out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;
     1860    *out << Verbose(1) << "---------------------------------------------------------------------------------------------------------" << endl;
    18461861    OtherAtom = NULL;
    1847     while ((Walker != Root) && ((OtherAtom == NULL) || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]))) {  // look for Root
     1862    do {  // look for Root
    18481863      Walker = BFSStack->PopFirst();
    1849       //*out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;
     1864      *out << Verbose(2) << "Current Walker is " << *Walker << ", we look for SP to Root " << *Root << "." << endl;
    18501865      for(int i=0;i<NumberOfBondsPerAtom[Walker->nr];i++) {
    18511866        Binder = ListOfBondsPerAtom[Walker->nr][i];
    18521867        if (Binder != BackEdge) { // only walk along DFS spanning tree (otherwise we always find SP of one being backedge Binder)
    18531868          OtherAtom = Binder->GetOtherAtom(Walker);
    1854           //*out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
    1855           if (ColorList[OtherAtom->nr] == white) {
    1856             TouchedStack->Push(OtherAtom);
    1857             ColorList[OtherAtom->nr] = lightgray;
    1858             PredecessorList[OtherAtom->nr] = Walker;  // Walker is the predecessor
    1859             ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
    1860             //*out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " lightgray, its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl;
    1861             if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance
    1862               //*out << Verbose(3) << "Putting OtherAtom into queue." << endl;
    1863               BFSStack->Push(OtherAtom);
     1869#ifdef ADDHYDROGEN         
     1870          if (OtherAtom->type->Z != 1) {
     1871#endif
     1872            *out << Verbose(2) << "Current OtherAtom is: " << OtherAtom->Name << " for bond " << *Binder << "." << endl;
     1873            if (ColorList[OtherAtom->nr] == white) {
     1874              TouchedStack->Push(OtherAtom);
     1875              ColorList[OtherAtom->nr] = lightgray;
     1876              PredecessorList[OtherAtom->nr] = Walker;  // Walker is the predecessor
     1877              ShortestPathList[OtherAtom->nr] = ShortestPathList[Walker->nr]+1;
     1878              *out << Verbose(2) << "Coloring OtherAtom " << OtherAtom->Name << " lightgray, its predecessor is " << Walker->Name << " and its Shortest Path is " << ShortestPathList[OtherAtom->nr] << " egde(s) long." << endl;
     1879              //if (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr]) { // Check for maximum distance
     1880                *out << Verbose(3) << "Putting OtherAtom into queue." << endl;
     1881                BFSStack->Push(OtherAtom);
     1882              //}
     1883            } else {
     1884              *out << Verbose(3) << "Not Adding, has already been visited." << endl;
    18641885            }
     1886            if (OtherAtom == Root)
     1887              break;
     1888#ifdef ADDHYDROGEN         
    18651889          } else {
    1866             //*out << Verbose(3) << "Not Adding, has already been visited." << endl;
     1890            *out << Verbose(2) << "Skipping hydrogen atom " << *OtherAtom << "." << endl;
     1891            ColorList[OtherAtom->nr] = black;
    18671892          }
     1893#endif
    18681894        } else {
    1869           //*out << Verbose(3) << "Not Visiting, is a back edge." << endl;
     1895          *out << Verbose(2) << "Bond " << *Binder << " not Visiting, is the back edge." << endl;
    18701896        }
    18711897      }
    18721898      ColorList[Walker->nr] = black;
    1873       //*out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
    1874     }
     1899      *out << Verbose(1) << "Coloring Walker " << Walker->Name << " black." << endl;
     1900      if (OtherAtom == Root) { // if we have found the root, check whether this cycle wasn't already found beforehand
     1901        // step through predecessor list
     1902        while (OtherAtom != BackEdge->rightatom) {
     1903          if (!OtherAtom->GetTrueFather()->IsCyclic)  // if one bond in the loop is not marked as cyclic, we haven't found this cycle yet
     1904            break;
     1905          else
     1906            OtherAtom = PredecessorList[OtherAtom->nr];
     1907        }
     1908        if (OtherAtom == BackEdge->rightatom) { // if each atom in found cycle is cyclic, loop's been found before already
     1909          *out << Verbose(3) << "This cycle was already found before, skipping and removing seeker from search." << endl;\
     1910          do {
     1911            OtherAtom = TouchedStack->PopLast();
     1912            if (PredecessorList[OtherAtom->nr] == Walker) {
     1913              *out << Verbose(4) << "Removing " << *OtherAtom << " from lists and stacks." << endl;
     1914              PredecessorList[OtherAtom->nr] = NULL;
     1915              ShortestPathList[OtherAtom->nr] = -1;
     1916              ColorList[OtherAtom->nr] = white;
     1917              BFSStack->RemoveItem(OtherAtom);
     1918            }
     1919          } while ((!TouchedStack->IsEmpty()) && (PredecessorList[OtherAtom->nr] == NULL));
     1920          TouchedStack->Push(OtherAtom);  // last was wrongly popped
     1921          OtherAtom = BackEdge->rightatom; // set to not Root
     1922        } else
     1923          OtherAtom = Root;
     1924      }
     1925    } while ((OtherAtom != Root) && (OtherAtom != NULL)); // || (ShortestPathList[OtherAtom->nr] < MinimumRingSize[Walker->GetTrueFather()->nr])));
    18751926   
    1876     if (Walker == Root) {
     1927    if (OtherAtom == Root) {
    18771928      // now climb back the predecessor list and thus find the cycle members
    18781929      NumCycles++;
     
    18801931      Root->GetTrueFather()->IsCyclic = true;
    18811932      *out << Verbose(1) << "Found ring contains: ";
     1933      Walker = Root;
    18821934      while (Walker != BackEdge->rightatom) {
    18831935        *out << Walker->Name << " <-> ";
Note: See TracChangeset for help on using the changeset viewer.