- Timestamp:
- Sep 10, 2016, 4:01:20 PM (8 years ago)
- Branches:
- Action_Thermostats, Add_AtomRandomPerturbation, Add_FitFragmentPartialChargesAction, Add_RotateAroundBondAction, Add_SelectAtomByNameAction, Adding_Graph_to_ChangeBondActions, Adding_MD_integration_tests, Adding_StructOpt_integration_tests, Automaking_mpqc_open, AutomationFragmentation_failures, Candidate_v1.5.4, Candidate_v1.6.0, Candidate_v1.6.1, ChangeBugEmailaddress, ChangingTestPorts, ChemicalSpaceEvaluator, 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_ChargeSampling_PBC, Fix_ChronosMutex, Fix_FitPartialCharges, Fix_FitPotential_needs_atomicnumbers, Fix_ForceAnnealing, Fix_IndependentFragmentGrids, Fix_ParseParticles, Fix_ParseParticles_split_forward_backward_Actions, Fix_StatusMsg, Fix_StepWorldTime_single_argument, Fix_Verbose_Codepatterns, Fixes, ForceAnnealing_goodresults, ForceAnnealing_oldresults, ForceAnnealing_tocheck, ForceAnnealing_with_BondGraph, ForceAnnealing_with_BondGraph_continued, ForceAnnealing_with_BondGraph_continued_betteresults, ForceAnnealing_with_BondGraph_contraction-expansion, GeometryObjects, Gui_displays_atomic_force_velocity, IndependentFragmentGrids, IndependentFragmentGrids_IndividualZeroInstances, IndependentFragmentGrids_IntegrationTest, IndependentFragmentGrids_Sole_NN_Calculation, JobMarket_RobustOnKillsSegFaults, JobMarket_StableWorkerPool, JobMarket_unresolvable_hostname_fix, ODR_violation_mpqc_open, PartialCharges_OrthogonalSummation, PythonUI_with_named_parameters, QtGui_reactivate_TimeChanged_changes, Recreated_GuiChecks, RotateToPrincipalAxisSystem_UndoRedo, SaturateAtoms_findBestMatching, SaturateAtoms_singleDegree, StoppableMakroAction, Subpackage_CodePatterns, Subpackage_JobMarket, Subpackage_LinearAlgebra, Subpackage_levmar, Subpackage_mpqc_open, Subpackage_vmg, ThirdParty_MPQC_rebuilt_buildsystem, TrajectoryDependenant_MaxOrder, TremoloParser_IncreasedPrecision, TremoloParser_MultipleTimesteps, Ubuntu_1604_changes, stable
- Children:
- 0c42f2, cdac1d
- Parents:
- d32f60
- git-author:
- Frederik Heber <heber@…> (05/10/16 18:33:50)
- git-committer:
- Frederik Heber <heber@…> (09/10/16 16:01:20)
- Location:
- src
- Files:
-
- 2 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Actions/AtomAction/SaturateAction.cpp
rd32f60 r64cafb2 77 77 "ChangeElementAction::performCall() - mol is still NULL." ); 78 78 79 // add the hydrogens80 const Vector AtomsPosition = _atom->getPosition();81 double typical_distance = _atom->getType()->getHBondDistance(0);82 if (typical_distance == -1.)83 typical_distance = 1.;84 SphericalPointDistribution PointSphere(typical_distance);85 PointSphere.initSelf(_atom->getType()->getNoValenceOrbitals());86 for (SphericalPointDistribution::Polygon_t::const_iterator iter = PointSphere.points.begin();87 iter != PointSphere.points.end(); ++iter) {88 // for every Vector add a point relative to atom's position89 atom * hydrogenAtom = World::getInstance().createAtom();90 hydrogenAtom->setType(hydrogen);91 hydrogenAtom->setPosition(AtomsPosition + *iter);92 mol->AddAtom(hydrogenAtom);93 // add bond94 _atom->addBond(WorldTime::getTime(), hydrogenAtom);95 // mark down for undo state96 addedHydrogens.push_back(AtomicInfo(*(hydrogenAtom)));97 }79 // // add the hydrogens 80 // const Vector AtomsPosition = _atom->getPosition(); 81 // double typical_distance = _atom->getType()->getHBondDistance(0); 82 // if (typical_distance == -1.) 83 // typical_distance = 1.; 84 // SphericalPointDistribution PointSphere(typical_distance); 85 // PointSphere.initSelf(_atom->getType()->getNoValenceOrbitals()); 86 // for (SphericalPointDistribution::Polygon_t::const_iterator iter = PointSphere.points.begin(); 87 // iter != PointSphere.points.end(); ++iter) { 88 // // for every Vector add a point relative to atom's position 89 // atom * hydrogenAtom = World::getInstance().createAtom(); 90 // hydrogenAtom->setType(hydrogen); 91 // hydrogenAtom->setPosition(AtomsPosition + *iter); 92 // mol->AddAtom(hydrogenAtom); 93 // // add bond 94 // _atom->addBond(WorldTime::getTime(), hydrogenAtom); 95 // // mark down for undo state 96 // addedHydrogens.push_back(AtomicInfo(*(hydrogenAtom))); 97 // } 98 98 } 99 99 -
src/Fragmentation/Exporters/SphericalPointDistribution.cpp
rd32f60 r64cafb2 38 38 39 39 #include "CodePatterns/Assert.hpp" 40 #include "CodePatterns/Log.hpp" 40 #include "CodePatterns/IteratorAdaptors.hpp" 41 #include "CodePatterns/toString.hpp" 41 42 42 43 #include <algorithm> 44 #include <cmath> 45 #include <limits> 46 #include <list> 43 47 #include <vector> 48 #include <map> 44 49 45 50 #include "LinearAlgebra/Line.hpp" … … 47 52 #include "LinearAlgebra/Vector.hpp" 48 53 49 void SphericalPointDistribution::initSelf(const int _NumberOfPoints) 50 { 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)+"."); 98 } 99 LOG(3, "DEBUG: Ideal polygon is " << points); 100 } 101 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 ) 63 { 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 } 74 } 75 return result; 76 } 77 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 -
src/Fragmentation/Exporters/SphericalPointDistribution.hpp
rd32f60 r64cafb2 57 57 } 58 58 59 /** Initializes the polygon with the given \a _NumberOfPoints. 59 60 /** Matches a given spherical distribution with another containing more 61 * points. 60 62 * 61 * \param _NumberOfPoints number of points 63 * This is a helper to determine points where to best insert saturation 64 * hydrogens. 65 * 66 * \param _polygon current occupied positions 67 * \param _newpolygon ideal distribution to match best with current occupied 68 * positions 69 * \return remaining vacant positions relative to \a _polygon 62 70 */ 63 void initSelf(const int _NumberOfPoints); 71 static Polygon_t matchSphericalPointDistributions( 72 const Polygon_t &_polygon, 73 const Polygon_t &_newpolygon 74 ); 75 64 76 65 77 //!> default radius of the spherical distribution … … 67 79 //!> precalculated value for root of 3 68 80 const double SQRT_3; 69 //!> points in this polygon70 Polygon_t points;71 81 }; 72 82 -
src/Fragmentation/Exporters/unittests/Makefile.am
rd32f60 r64cafb2 5 5 ../Fragmentation/Exporters/unittests/HydrogenPoolUnitTest.cpp \ 6 6 ../Fragmentation/Exporters/unittests/SaturatedFragmentUnitTest.cpp \ 7 ../Fragmentation/Exporters/unittests/SaturationDistanceMaximizerUnitTest.cpp 7 ../Fragmentation/Exporters/unittests/SaturationDistanceMaximizerUnitTest.cpp \ 8 ../Fragmentation/Exporters/unittests/SphericalPointDistributionUnitTest.cpp 8 9 9 10 FRAGMENTATIONEXPORTERSTESTSHEADERS = \ 10 11 ../Fragmentation/Exporters/unittests/HydrogenPoolUnitTest.hpp \ 11 12 ../Fragmentation/Exporters/unittests/SaturatedFragmentUnitTest.hpp \ 12 ../Fragmentation/Exporters/unittests/SaturationDistanceMaximizerUnitTest.hpp 13 ../Fragmentation/Exporters/unittests/SaturationDistanceMaximizerUnitTest.hpp \ 14 ../Fragmentation/Exporters/unittests/SphericalPointDistributionUnitTest.hpp 13 15 14 16 FRAGMENTATIONEXPORTERSTESTS = \ 15 17 HydrogenPoolUnitTest \ 16 18 SaturatedFragmentUnitTest \ 17 SaturationDistanceMaximizerUnitTest 19 SaturationDistanceMaximizerUnitTest \ 20 SphericalPointDistributionUnitTest 18 21 19 22 TESTS += $(FRAGMENTATIONEXPORTERSTESTS) … … 45 48 46 49 SaturationDistanceMaximizerUnitTest_SOURCES = \ 50 ../Fragmentation/Exporters/unittests/SaturationDistanceMaximizerUnitTest.cpp \ 47 51 ../Fragmentation/Exporters/unittests/SaturationDistanceMaximizerUnitTest.hpp \ 48 52 ../Fragmentation/Exporters/unittests/stubs/SaturatedBondStub.cpp … … 51 55 $(top_builddir)/LinearAlgebra/src/LinearAlgebra/libLinearAlgebra.la \ 52 56 ${FRAGMENTATIONEXPORTERSLIBS} 57 58 SphericalPointDistributionUnitTest_SOURCES = \ 59 ../Fragmentation/Exporters/unittests/SphericalPointDistributionUnitTest.cpp \ 60 ../Fragmentation/Exporters/unittests/SphericalPointDistributionUnitTest.hpp 61 SphericalPointDistributionUnitTest_LDADD = \ 62 ../libMolecuilderUI.la \ 63 $(top_builddir)/LinearAlgebra/src/LinearAlgebra/libLinearAlgebra.la \ 64 ${FRAGMENTATIONEXPORTERSLIBS} 53 65 54 66
Note:
See TracChangeset
for help on using the changeset viewer.