Changeset 08ef35 for src


Ignore:
Timestamp:
Aug 10, 2009, 4:11:47 PM (15 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:
570125
Parents:
5c7bf8
Message:

New function ConvexizeNonconvexEnvelope() to calculate the volume of a non-convex envelope.

The central idea is that the volume of a convex envelope is easy to determine as a sum of pyramids with respect to a center inside the envelope. Hence, if we can "reduce" the non-convex envelope to a convex one in such a way that we know the added volume, we may determine the volume of a non-convex envelope.
The nice side effect is that we may use our Find_non_convex_border() algorithm to calculate also the convex envelope.

  • We go through all BoundaryPoints and check whether one of its Baselines does not fulfill the ConvexCriterion. If so, we remove it, as it can not be a boundary point on the convex envelope, and re-construct the attached triangles. The added volume is a general tetraeder, whose formula is known.
  • FIX: Find_convex_border() - We check whether AddPoint is successful or not.
  • builder.cpp: case 'o' - changed to use ConvexizeNonconvexEnvelope() instead of Find_convex_border()
  • Tesselation:AddPoint() - now takes second argument which is the index for BPS and always set BPS to either the newly created or the already present point. Return argument discerns between new and already present point.
  • Tesselation::BPS, BLS, BTS are now public not private. We have to access them from ConvexizeNonconvexEnvelope()
Location:
src
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • src/boundary.cpp

    r5c7bf8 r08ef35  
    476476  for (int axis = 0; axis < NDIM; axis++)
    477477    for (Boundaries::iterator runner = BoundaryPoints[axis].begin(); runner != BoundaryPoints[axis].end(); runner++)
    478         mol->TesselStruct->AddPoint(runner->second.second);
     478        if (!mol->TesselStruct->AddPoint(runner->second.second, 0))
     479          *out << Verbose(3) << "WARNING: Point " << *(runner->second.second) << " is already present!" << endl;
    479480
    480481  *out << Verbose(2) << "I found " << mol->TesselStruct->PointsOnBoundaryCount << " points on the convex boundary." << endl;
     
    560561};
    561562
     563/** Creates a convex envelope from a given non-convex one.
     564 * -# We go through all PointsOnBoundary.
     565 * -# We look at each of its lines and CheckConvexityCriterion().
     566 * -# If any returns concave, this Point cannot be on the final convex envelope.
     567 * -# Hence, we remove it and re-create all its triangles from its getCircleOfConnectedPoints()
     568 * -# We calculate the additional volume
     569 * -# We go over the points until none yields a concave spot anymore.
     570 *
     571 * Note: This routine - for free - calculates the difference in volume between convex and
     572 * non-convex envelope, as the former is easy to calculate - VolumeOfConvexEnvelope() - it
     573 * can be used to compute volumes of arbitrary shapes.
     574 * \param *out output stream for debugging
     575 * \param *TesselStruct non-convex envelope, is changed in return!
     576 * \param *configuration contains IsAngstroem()
     577 * \return volume difference between the non- and the created convex envelope
     578 */
     579double ConvexizeNonconvexEnvelope(ofstream *out, class Tesselation *TesselStruct)
     580{
     581  double volume = 0;
     582  class BoundaryPointSet *point = NULL;
     583  class BoundaryLineSet *line = NULL;
     584  class BoundaryTriangleSet *triangle = NULL;
     585  Vector OldPoint, TetraederVector[3];
     586  *out << Verbose(0) << "Begin of ConvexizeNonconvexEnvelope" << endl;
     587
     588  if (TesselStruct == NULL) {
     589    *out << Verbose(1) << "ERROR: TesselStruct is empty!" << endl;
     590    return volume;
     591  }
     592
     593  bool AllConvex = true;
     594  bool Convexity = false;
     595  do {
     596    AllConvex = true;
     597    for (PointMap::iterator PointRunner = TesselStruct->PointsOnBoundary.begin(); PointRunner != TesselStruct->PointsOnBoundary.end(); PointRunner++) {
     598      point = PointRunner->second;
     599      *out << Verbose(1) << "INFO: Current point is " << *point << "." << endl;
     600      Convexity = true;
     601      for (LineMap::iterator LineRunner = point->lines.begin(); LineRunner != point->lines.end(); LineRunner++) {
     602        line = LineRunner->second;
     603        *out << Verbose(2) << "INFO: Current line is " << *line << "." << endl;
     604        if (line->CheckConvexityCriterion(out)) {
     605          // convex
     606        } else { // concave
     607          Convexity = false; // we have to go again through all ...
     608          break;  // no need to check the others too
     609        }
     610      }
     611      AllConvex = AllConvex && Convexity;
     612      if (!Convexity) {
     613        *out << Verbose(1) << "... point cannot be on convex envelope." << endl;
     614        OldPoint.CopyVector(point->node->node);
     615        // get list of connected points
     616        BoundaryPointSet *Otherpoint = line->GetOtherEndpoint(point);
     617        list<TesselPoint*> *CircleofPoints = TesselStruct->getCircleOfConnectedPoints(out, point->node, Otherpoint->node->node);
     618        // remove all triangles
     619        int *numbers = NULL;
     620        int count = 0;
     621        int i=0;
     622        for (LineMap::iterator LineRunner = point->lines.begin(); LineRunner != point->lines.end(); LineRunner++)
     623          count+=LineRunner->second->triangles.size();
     624        numbers = new int[count];
     625        for (LineMap::iterator LineRunner = point->lines.begin(); LineRunner != point->lines.end(); LineRunner++) {
     626          line = LineRunner->second;
     627          for (TriangleMap::iterator TriangleRunner = line->triangles.begin(); TriangleRunner != line->triangles.end(); TriangleRunner++) {
     628            triangle = TriangleRunner->second;
     629            *out << Verbose(2) << "Erasing triangle " << *triangle << "." << endl;
     630            numbers[i] = triangle->Nr;
     631            TesselStruct->TrianglesOnBoundary.erase(triangle->Nr);
     632            delete(triangle);
     633            i++;
     634          }
     635        }
     636        *out << Verbose(1) << i << " triangles were removed." << endl;
     637
     638        // re-create all triangles by going through connected points list
     639        list<TesselPoint*>::iterator OtherCircleRunner = CircleofPoints->end();
     640        OtherCircleRunner--;
     641        i=0;
     642        for (list<TesselPoint*>::iterator CircleRunner = CircleofPoints->begin(); CircleRunner != CircleofPoints->end(); CircleRunner++) {
     643          *out << Verbose(2) << "Adding new triangle points."<< endl;
     644          TesselStruct->AddPoint(point->node, 0);
     645          TesselStruct->AddPoint(*CircleRunner, 1);
     646          TesselStruct->AddPoint(*OtherCircleRunner, 2);
     647          *out << Verbose(2) << "Adding new triangle lines."<< endl;
     648          TesselStruct->AddTriangleLine(TesselStruct->BPS[0], TesselStruct->BPS[1], 0);
     649          TesselStruct->AddTriangleLine(TesselStruct->BPS[0], TesselStruct->BPS[2], 1);
     650          TesselStruct->AddTriangleLine(TesselStruct->BPS[1], TesselStruct->BPS[2], 2);
     651          TesselStruct->BTS = new class BoundaryTriangleSet(TesselStruct->BLS, numbers[i]);
     652          TesselStruct->TrianglesOnBoundary.insert(TrianglePair(numbers[i], triangle));
     653          *out << Verbose(2) << "Created triangle " << *TesselStruct->BTS << "." << endl;
     654          // calculate volume summand as a general tetraeder
     655          for (int j=0;j<3;j++) {
     656            TetraederVector[j].CopyVector(TesselStruct->BPS[j]->node->node);
     657            TetraederVector[j].SubtractVector(&OldPoint);
     658          }
     659          OldPoint.CopyVector(&TetraederVector[0]);
     660          OldPoint.VectorProduct(&TetraederVector[1]);
     661          volume += 1./6. * fabs(OldPoint.ScalarProduct(&TetraederVector[2]));
     662          // advance other shank
     663          OtherCircleRunner++;
     664          if (OtherCircleRunner == CircleofPoints->end())
     665            OtherCircleRunner = CircleofPoints->begin();
     666          // advance number
     667          i++;
     668          if (i > count)
     669            *out << Verbose(2) << "WARNING: Maximum of numbers reached!" << endl;
     670        }
     671        *out << Verbose(1) << i << " triangles were created." << endl;
     672       
     673        delete[](numbers);
     674      }
     675    }
     676  } while (!AllConvex);
     677  *out << Verbose(0) << "End of ConvexizeNonconvexEnvelope" << endl;
     678
     679  // end
     680  return volume;
     681};
    562682
    563683/** Determines the volume of a cluster.
  • src/boundary.hpp

    r5c7bf8 r08ef35  
    3939void Find_convex_border(ofstream *out, molecule* mol, class LinkedCell *LCList, const char *filename);
    4040void Find_non_convex_border(ofstream *out, molecule* mol, class LinkedCell *LC, const char *tempbasename, const double RADIUS);
     41double ConvexizeNonconvexEnvelope(ofstream *out, class Tesselation *TesselStruct);
    4142void Find_next_suitable_point(class BoundaryTriangleSet *BaseTriangle, class BoundaryLineSet *BaseLine, atom*& OptCandidate, Vector *OptCandidateCenter, double *ShortestAngle, const double RADIUS, LinkedCell *LC);
    4243Boundaries *GetBoundaryPoints(ofstream *out, molecule *mol);
  • src/builder.cpp

    r5c7bf8 r08ef35  
    18711871                cout << Verbose(1) << "Storing tecplot data in " << argv[argptr] << "." << endl;
    18721872                LinkedCell LCList(mol, 10.);
    1873                 class Tesselation *TesselStruct = NULL;
    1874                 Find_convex_border((ofstream *)&cout, mol, &LCList, argv[argptr]);
    1875                 double clustervolume = VolumeOfConvexEnvelope((ofstream *)&cout, TesselStruct, &configuration);
    1876                 cout << Verbose(0) << "The tesselated surface area is " << clustervolume << "." << endl;
    1877                 delete(TesselStruct);
     1873                //Find_convex_border((ofstream *)&cout, mol, &LCList, argv[argptr]);
     1874                Find_non_convex_border((ofstream *)&cout, mol, &LCList, argv[argptr], 10.);
     1875
     1876                double volumedifference = ConvexizeNonconvexEnvelope((ofstream *)&cout, mol->TesselStruct);
     1877                double clustervolume = VolumeOfConvexEnvelope((ofstream *)&cout, mol->TesselStruct, &configuration);
     1878                cout << Verbose(0) << "The tesselated surface area is " << clustervolume << " " << (configuration.GetIsAngstroem() ? "angstrom" : "atomiclength") << "^3." << endl;
     1879                cout << Verbose(0) << "The non-convex tesselated surface area is " << clustervolume-volumedifference << " " << (configuration.GetIsAngstroem() ? "angstrom" : "atomiclength") << "^3." << endl;
    18781880                argptr+=1;
    18791881              }
  • src/tesselation.cpp

    r5c7bf8 r08ef35  
    208208 * \return NULL - if endpoint not contained in BoundaryLineSet, or pointer to BoundaryPointSet otherwise
    209209 */
    210 inline class BoundaryPointSet *BoundaryLineSet::GetOtherEndpoint(class BoundaryPointSet *point)
     210class BoundaryPointSet *BoundaryLineSet::GetOtherEndpoint(class BoundaryPointSet *point)
    211211{
    212212  if (endpoints[0] == point)
     
    10441044        // add Walker to boundary points
    10451045        *out << Verbose(2) << "Adding " << *Walker << " to BoundaryPoints." << endl;
    1046         AddPoint(Walker);
    1047         if (BPS[0] != NULL)
     1046        if (AddPoint(Walker,0))
    10481047          NewPoint = BPS[0];
    10491048        else
     
    11001099/** Adds an point to the tesselation::PointsOnBoundary list.
    11011100 * \param *Walker point to add
    1102  */
    1103 void
    1104 Tesselation::AddPoint(TesselPoint *Walker)
     1101 * \param n TesselStruct::BPS index to put pointer into
     1102 * \return true - new point was added, false - point already present
     1103 */
     1104bool
     1105Tesselation::AddPoint(TesselPoint *Walker, int n)
    11051106{
    11061107  PointTestPair InsertUnique;
    1107   BPS[0] = new class BoundaryPointSet(Walker);
    1108   InsertUnique = PointsOnBoundary.insert(PointPair(Walker->nr, BPS[0]));
    1109   if (InsertUnique.second) // if new point was not present before, increase counter
     1108  BPS[n] = new class BoundaryPointSet(Walker);
     1109  InsertUnique = PointsOnBoundary.insert(PointPair(Walker->nr, BPS[n]));
     1110  if (InsertUnique.second) { // if new point was not present before, increase counter
    11101111    PointsOnBoundaryCount++;
    1111   else {
    1112     delete(BPS[0]);
    1113     BPS[0] = NULL;
     1112    return true;
     1113  } else {
     1114    delete(BPS[n]);
     1115    BPS[n] = InsertUnique.first->second;
     1116    return false;
    11141117  }
    11151118}
  • src/tesselation.hpp

    r5c7bf8 r08ef35  
    190190    virtual ~Tesselation();
    191191
    192     void AddPoint(TesselPoint *Walker);
     192    bool AddPoint(TesselPoint *Walker, int n);
    193193    void AddTrianglePoint(TesselPoint* Candidate, int n);
    194194    void AddTriangleLine(class BoundaryPointSet *a, class BoundaryPointSet *b, int n);
     
    236236    virtual bool IsEnd();
    237237
    238   private:
    239     class BoundaryPointSet *TPS[3]; //this is a Storage for pointers to triangle points, this and BPS[2] needed due to AddLine restrictions
    240238    class BoundaryPointSet *BPS[2];
    241239    class BoundaryLineSet *BLS[3];
    242240    class BoundaryTriangleSet *BTS;
     241
     242  private:
     243    class BoundaryPointSet *TPS[3]; //this is a Storage for pointers to triangle points, this and BPS[2] needed due to AddLine restrictions
    243244
    244245    PointMap::iterator InternalPointer;
Note: See TracChangeset for help on using the changeset viewer.