Ignore:
Timestamp:
Feb 13, 2015, 9:17:02 AM (10 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:
2fcef3
Parents:
f54930
git-author:
Frederik Heber <heber@…> (06/04/14 11:23:31)
git-committer:
Frederik Heber <heber@…> (02/13/15 09:17:02)
Message:

Trimmed down SphericalPointDistribution to what is needed at the moment.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Fragmentation/Exporters/SphericalPointDistribution.cpp

    rf54930 r0241c5  
    3838
    3939#include "CodePatterns/Assert.hpp"
    40 #include "CodePatterns/IteratorAdaptors.hpp"
    41 #include "CodePatterns/toString.hpp"
     40#include "CodePatterns/Log.hpp"
    4241
    4342#include <algorithm>
    44 #include <cmath>
    45 #include <limits>
    46 #include <list>
    4743#include <vector>
    48 #include <map>
    4944
    5045#include "LinearAlgebra/Line.hpp"
     
    5247#include "LinearAlgebra/Vector.hpp"
    5348
    54 typedef std::list<unsigned int> IndexList_t;
    55 typedef std::vector<unsigned int> IndexArray_t;
    56 typedef std::vector<Vector> VectorArray_t;
    57 typedef std::vector<double> DistanceArray_t;
    58 
    59 DistanceArray_t calculatePairwiseDistances(
    60     const std::vector<Vector> &_points,
    61     const IndexList_t &_indices
    62     )
     49void SphericalPointDistribution::initSelf(const int _NumberOfPoints)
    6350{
    64   DistanceArray_t result;
    65   for (IndexList_t::const_iterator firstiter = _indices.begin();
    66       firstiter != _indices.end(); ++firstiter) {
    67     for (IndexList_t::const_iterator seconditer = firstiter;
    68         seconditer != _indices.end(); ++seconditer) {
    69       if (firstiter == seconditer)
    70         continue;
    71       const double distance = (_points[*firstiter] - _points[*seconditer]).NormSquared();
    72       result.push_back(distance);
    73     }
     51  switch (_NumberOfPoints)
     52  {
     53    case 0:
     54      points = get<0>();
     55      break;
     56    case 1:
     57      points = get<1>();
     58      break;
     59    case 2:
     60      points = get<2>();
     61      break;
     62    case 3:
     63      points = get<3>();
     64      break;
     65    case 4:
     66      points = get<4>();
     67      break;
     68    case 5:
     69      points = get<5>();
     70      break;
     71    case 6:
     72      points = get<6>();
     73      break;
     74    case 7:
     75      points = get<7>();
     76      break;
     77    case 8:
     78      points = get<8>();
     79      break;
     80    case 9:
     81      points = get<9>();
     82      break;
     83    case 10:
     84      points = get<10>();
     85      break;
     86    case 11:
     87      points = get<11>();
     88      break;
     89    case 12:
     90      points = get<12>();
     91      break;
     92    case 14:
     93      points = get<14>();
     94      break;
     95    default:
     96      ASSERT(0, "SphericalPointDistribution::initSelf() - cannot deal with the case "
     97          +toString(_NumberOfPoints)+".");
    7498  }
    75   return result;
     99  LOG(3, "DEBUG: Ideal polygon is " << points);
    76100}
    77101
    78 // class generator: taken from www.cplusplus.com example std::generate
    79 struct c_unique {
    80   int current;
    81   c_unique() {current=0;}
    82   int operator()() {return ++current;}
    83 } UniqueNumber;
    84 
    85 /** Returns squared L2 error of the given \a _Matching.
    86  *
    87  * We compare the pair-wise distances of each associated matching
    88  * and check whether these distances each match between \a _old and
    89  * \a _new.
    90  *
    91  * \param _old first set of points (fewer or equal to \a _new)
    92  * \param _new second set of points
    93  * \param _Matching matching between the two sets
    94  * \return pair with L1 and squared L2 error
    95  */
    96 std::pair<double, double> calculateErrorOfMatching(
    97     const std::vector<Vector> &_old,
    98     const std::vector<Vector> &_new,
    99     const IndexList_t &_Matching)
    100 {
    101   std::pair<double, double> errors( std::make_pair( 0., 0. ) );
    102 
    103   if (_Matching.size() > 1) {
    104     // convert matching into two vectors to calculate distance among another
    105 
    106     // calculate all pair-wise distances
    107     IndexList_t keys(_Matching.size());
    108     std::generate (keys.begin(), keys.end(), UniqueNumber);
    109     const DistanceArray_t firstdistances = calculatePairwiseDistances(_old, keys);
    110     const DistanceArray_t seconddistances = calculatePairwiseDistances(_new, _Matching);
    111 
    112     ASSERT( firstdistances.size() == seconddistances.size(),
    113         "calculateL2ErrorOfMatching() - mismatch in pair-wise distance array sizes.");
    114     DistanceArray_t::const_iterator firstiter = firstdistances.begin();
    115     DistanceArray_t::const_iterator seconditer = seconddistances.begin();
    116     for (;(firstiter != firstdistances.end()) && (seconditer != seconddistances.end());
    117         ++firstiter, ++seconditer) {
    118       const double gap = *firstiter - *seconditer;
    119       // L1 error
    120       if (errors.first < gap)
    121         errors.first = gap;
    122       // L2 error
    123       errors.second += gap*gap;
    124     }
    125   }
    126 
    127   return errors;
    128 }
    129 
    130 SphericalPointDistribution::Polygon_t removeMatchingPoints(
    131     const SphericalPointDistribution::Polygon_t &_points,
    132     const IndexList_t &_matchingindices
    133     )
    134 {
    135   SphericalPointDistribution::Polygon_t remainingpoints;
    136   IndexArray_t indices(_matchingindices.begin(), _matchingindices.end());
    137   std::sort(indices.begin(), indices.end());
    138   IndexArray_t::const_iterator valueiter = indices.begin();
    139   SphericalPointDistribution::Polygon_t::const_iterator pointiter =
    140       _points.begin();
    141   for (unsigned int i=0; i< _points.size(); ++i, ++pointiter) {
    142     // skip all those in values
    143     if (*valueiter == i)
    144       ++valueiter;
    145     else
    146       remainingpoints.push_back(*pointiter);
    147   }
    148 
    149   return remainingpoints;
    150 }
    151 
    152 /** Rotates a given polygon around x, y, and z axis by the given angles.
    153  *
    154  * Essentially, we concentrate on the three points of the polygon to rotate
    155  * to the correct position. First, we rotate its center via \a angles,
    156  * then we rotate the "triangle" around itself/\a _RotationAxis by
    157  * \a _RotationAngle.
    158  *
    159  * \param _polygon polygon whose points to rotate
    160  * \param _angles vector with rotation angles for x,y,z axis
    161  * \param _RotationAxis
    162  * \param _RotationAngle
    163  */
    164 SphericalPointDistribution::Polygon_t rotatePolygon(
    165     const SphericalPointDistribution::Polygon_t &_polygon,
    166     const std::vector<double> &_angles,
    167     const Line &_RotationAxis,
    168     const double _RotationAngle)
    169 {
    170   SphericalPointDistribution::Polygon_t rotated_polygon = _polygon;
    171   RealSpaceMatrix rotation;
    172   ASSERT( _angles.size() == 3,
    173       "rotatePolygon() - not exactly "+toString(3)+" angles given.");
    174   rotation.setRotation(_angles[0] * M_PI/180., _angles[1] * M_PI/180., _angles[2] * M_PI/180.);
    175 
    176   // apply rotation angles
    177   for (SphericalPointDistribution::Polygon_t::iterator iter = rotated_polygon.begin();
    178       iter != rotated_polygon.end(); ++iter) {
    179     *iter = rotation * (*iter);
    180     _RotationAxis.rotateVector(*iter, _RotationAngle);
    181   }
    182 
    183   return rotated_polygon;
    184 }
    185 
    186 struct MatchingControlStructure {
    187   bool foundflag;
    188   double bestL2;
    189   IndexList_t bestmatching;
    190   VectorArray_t oldpoints;
    191   VectorArray_t newpoints;
    192 };
    193 
    194 /** Recursive function to go through all possible matchings.
    195  *
    196  * \param _MCS structure holding global information to the recursion
    197  * \param _matching current matching being build up
    198  * \param _indices contains still available indices
    199  * \param _matchingsize
    200  */
    201 void recurseMatchings(
    202     MatchingControlStructure &_MCS,
    203     IndexList_t &_matching,
    204     IndexList_t _indices,
    205     unsigned int _matchingsize)
    206 {
    207   //!> threshold for L1 error below which matching is immediately acceptable
    208   const double L1THRESHOLD = 1e-2;
    209   if (!_MCS.foundflag) {
    210     if (_matching.size() < _matchingsize) {
    211       // go through all indices
    212       for (IndexList_t::iterator iter = _indices.begin();
    213           iter != _indices.end();) {
    214         // add index to matching
    215         _matching.push_back(*iter);
    216         // remove index but keep iterator to position (is the next to erase element)
    217         IndexList_t::iterator backupiter = _indices.erase(iter);
    218         // recurse with decreased _matchingsize
    219         recurseMatchings(_MCS, _matching, _indices, _matchingsize-1);
    220         // re-add chosen index and reset index to new position
    221         _indices.insert(backupiter, _matching.back());
    222         iter = backupiter;
    223         // remove index from _matching to make space for the next one
    224         _matching.pop_back();
    225       }
    226       // gone through all indices then exit recursion
    227       _MCS.foundflag = true;
    228     } else {
    229       // calculate errors
    230       std::pair<double, double> errors = calculateErrorOfMatching(
    231           _MCS.oldpoints, _MCS.newpoints, _matching);
    232       if (errors.first < L1THRESHOLD) {
    233         _MCS.bestmatching = _matching;
    234         _MCS.foundflag = true;
    235       }
    236       if (_MCS.bestL2 > errors.second) {
    237         _MCS.bestmatching = _matching;
    238         _MCS.bestL2 = errors.second;
    239       }
    240     }
    241   }
    242 }
    243 
    244 SphericalPointDistribution::Polygon_t
    245 SphericalPointDistribution::matchSphericalPointDistributions(
    246     const SphericalPointDistribution::Polygon_t &_polygon,
    247     const SphericalPointDistribution::Polygon_t &_newpolygon
    248     )
    249 {
    250   SphericalPointDistribution::Polygon_t remainingpoints;
    251   VectorArray_t remainingold(_polygon.begin(), _polygon.end());
    252   VectorArray_t remainingnew(_newpolygon.begin(), _newpolygon.end());
    253 
    254   if (_polygon.size() > 0) {
    255     MatchingControlStructure MCS;
    256     MCS.foundflag = false;
    257     MCS.bestL2 = std::numeric_limits<double>::max();
    258     MCS.oldpoints.insert(MCS.oldpoints.begin(), _polygon.begin(),_polygon.end() );
    259     MCS.newpoints.insert(MCS.newpoints.begin(), _newpolygon.begin(),_newpolygon.end() );
    260 
    261     // search for bestmatching combinatorially
    262     {
    263       // translate polygon into vector to enable index addressing
    264       IndexList_t indices(_newpolygon.size());
    265       std::generate(indices.begin(), indices.end(), UniqueNumber);
    266       IndexList_t matching;
    267 
    268       // walk through all matchings
    269       const unsigned int matchingsize = _polygon.size();
    270       ASSERT( matchingsize <= indices.size(),
    271           "SphericalPointDistribution::matchSphericalPointDistributions() - not enough new points to choose for matching to old ones.");
    272       recurseMatchings(MCS, matching, indices, matchingsize);
    273     }
    274 
    275     // determine rotation angles to align the two point distributions with
    276     // respect to bestmatching
    277     std::vector<double> angles(3);
    278     Vector newCenter;
    279     {
    280       // calculate center of triangle/line/point consisting of first points of matching
    281       Vector oldCenter;
    282       IndexList_t::const_iterator iter = MCS.bestmatching.begin();
    283       unsigned int i = 0;
    284       for (; (i<3) && (i<MCS.bestmatching.size()); ++i, ++iter) {
    285         oldCenter += remainingold[i];
    286         newCenter += remainingnew[*iter];
    287       }
    288       oldCenter *= 1./(double)i;
    289       newCenter *= 1./(double)i;
    290 
    291       Vector direction(0.,0.,0.);
    292       for(size_t i=0;i<NDIM;++i) {
    293         // create new rotation axis
    294         direction[i] = 1.;
    295         const Line axis (zeroVec, direction);
    296         // calculate rotation angle for this axis
    297         const double alpha = direction.Angle(oldCenter) - direction.Angle(newCenter);
    298         // perform rotation
    299         axis.rotateVector(newCenter, alpha);
    300         // store angle
    301         angles[i] = alpha;
    302         // reset direction component for next iteration
    303         direction[i] = 0.;
    304       }
    305     }
    306     const Line RotationAxis(zeroVec, newCenter);
    307     const double RotationAngle =
    308         newCenter.Angle(remainingold[0])
    309         - newCenter.Angle(remainingnew[*MCS.bestmatching.begin()]);
    310 
    311     // rotate _newpolygon
    312     SphericalPointDistribution::Polygon_t rotated_newpolygon =
    313         rotatePolygon(_newpolygon, angles, RotationAxis, RotationAngle);
    314 
    315     // remove all points in matching and return remaining ones
    316     return removeMatchingPoints(rotated_newpolygon, MCS.bestmatching);
    317   } else
    318     return _newpolygon;
    319 }
    320 
    321 
    322 
Note: See TracChangeset for help on using the changeset viewer.