- Timestamp:
- Feb 13, 2015, 9:17:02 AM (10 years ago)
- 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)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Fragmentation/Exporters/SphericalPointDistribution.cpp
rf54930 r0241c5 38 38 39 39 #include "CodePatterns/Assert.hpp" 40 #include "CodePatterns/IteratorAdaptors.hpp" 41 #include "CodePatterns/toString.hpp" 40 #include "CodePatterns/Log.hpp" 42 41 43 42 #include <algorithm> 44 #include <cmath>45 #include <limits>46 #include <list>47 43 #include <vector> 48 #include <map>49 44 50 45 #include "LinearAlgebra/Line.hpp" … … 52 47 #include "LinearAlgebra/Vector.hpp" 53 48 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 ) 49 void SphericalPointDistribution::initSelf(const int _NumberOfPoints) 63 50 { 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)+"."); 74 98 } 75 return result;99 LOG(3, "DEBUG: Ideal polygon is " << points); 76 100 } 77 101 78 // class generator: taken from www.cplusplus.com example std::generate79 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 matching88 * and check whether these distances each match between \a _old and89 * \a _new.90 *91 * \param _old first set of points (fewer or equal to \a _new)92 * \param _new second set of points93 * \param _Matching matching between the two sets94 * \return pair with L1 and squared L2 error95 */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 another105 106 // calculate all pair-wise distances107 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 error120 if (errors.first < gap)121 errors.first = gap;122 // L2 error123 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 &_matchingindices133 )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 values143 if (*valueiter == i)144 ++valueiter;145 else146 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 rotate155 * to the correct position. First, we rotate its center via \a angles,156 * then we rotate the "triangle" around itself/\a _RotationAxis by157 * \a _RotationAngle.158 *159 * \param _polygon polygon whose points to rotate160 * \param _angles vector with rotation angles for x,y,z axis161 * \param _RotationAxis162 * \param _RotationAngle163 */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 angles177 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 recursion197 * \param _matching current matching being build up198 * \param _indices contains still available indices199 * \param _matchingsize200 */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 acceptable208 const double L1THRESHOLD = 1e-2;209 if (!_MCS.foundflag) {210 if (_matching.size() < _matchingsize) {211 // go through all indices212 for (IndexList_t::iterator iter = _indices.begin();213 iter != _indices.end();) {214 // add index to matching215 _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 _matchingsize219 recurseMatchings(_MCS, _matching, _indices, _matchingsize-1);220 // re-add chosen index and reset index to new position221 _indices.insert(backupiter, _matching.back());222 iter = backupiter;223 // remove index from _matching to make space for the next one224 _matching.pop_back();225 }226 // gone through all indices then exit recursion227 _MCS.foundflag = true;228 } else {229 // calculate errors230 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_t245 SphericalPointDistribution::matchSphericalPointDistributions(246 const SphericalPointDistribution::Polygon_t &_polygon,247 const SphericalPointDistribution::Polygon_t &_newpolygon248 )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 combinatorially262 {263 // translate polygon into vector to enable index addressing264 IndexList_t indices(_newpolygon.size());265 std::generate(indices.begin(), indices.end(), UniqueNumber);266 IndexList_t matching;267 268 // walk through all matchings269 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 with276 // respect to bestmatching277 std::vector<double> angles(3);278 Vector newCenter;279 {280 // calculate center of triangle/line/point consisting of first points of matching281 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 axis294 direction[i] = 1.;295 const Line axis (zeroVec, direction);296 // calculate rotation angle for this axis297 const double alpha = direction.Angle(oldCenter) - direction.Angle(newCenter);298 // perform rotation299 axis.rotateVector(newCenter, alpha);300 // store angle301 angles[i] = alpha;302 // reset direction component for next iteration303 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 _newpolygon312 SphericalPointDistribution::Polygon_t rotated_newpolygon =313 rotatePolygon(_newpolygon, angles, RotationAxis, RotationAngle);314 315 // remove all points in matching and return remaining ones316 return removeMatchingPoints(rotated_newpolygon, MCS.bestmatching);317 } else318 return _newpolygon;319 }320 321 322
Note:
See TracChangeset
for help on using the changeset viewer.