- Timestamp:
- Sep 12, 2016, 2:03:15 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, 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, 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:
- 92bc5c
- Parents:
- 8d38e6
- git-author:
- Frederik Heber <heber@…> (06/05/14 17:16:26)
- git-committer:
- Frederik Heber <heber@…> (09/12/16 14:03:15)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Fragmentation/Exporters/SphericalPointDistribution.cpp
r8d38e6 rf9d85f 43 43 44 44 #include <algorithm> 45 #include <boost/math/quaternion.hpp> 45 46 #include <cmath> 46 47 #include <functional> … … 225 226 } 226 227 227 /** Convert cartesian to polar coordinates.228 *229 * \param _cartesian vector in cartesian coordinates230 * \return vector containing \f$ (r,\theta, \varphi \f$ tuple for polar coordinates231 */232 std::vector<double> getPolarCoordinates(const Vector &_cartesian)233 {234 std::vector<double> polar(3,0.);235 const double xsqr = _cartesian[0] * _cartesian[0];236 const double ysqr = _cartesian[1] * _cartesian[1];237 polar[0] = sqrt(xsqr + ysqr + _cartesian[2]*_cartesian[2]);238 if (fabs(_cartesian[2]) < std::numeric_limits<double>::epsilon()*1e4) {239 if (fabs(xsqr + ysqr) < std::numeric_limits<double>::epsilon()*1e4) {240 polar[1] = 0.;241 } else {242 // xsqr + ysqr is always non-negative243 polar[1] = M_PI/2.;244 }245 } else {246 polar[1] = atan( sqrt(xsqr + ysqr)/_cartesian[2]);247 if (_cartesian[2] <= -std::numeric_limits<double>::epsilon()*1e4)248 polar[1] += M_PI;249 }250 251 if (fabs(_cartesian[0]) < std::numeric_limits<double>::epsilon()*1e4) {252 if (fabs(_cartesian[1]) < std::numeric_limits<double>::epsilon()*1e4) {253 polar[2] = 0.;254 } else if (_cartesian[1] > std::numeric_limits<double>::epsilon()*1e4) {255 polar[2] = M_PI/2.;256 } else {257 polar[2] = -M_PI/2.;258 }259 } else {260 polar[2] = atan ( _cartesian[1]/_cartesian[0] );261 if (_cartesian[0] <= -std::numeric_limits<double>::epsilon()*1e4)262 polar[2] += M_PI;263 }264 return polar;265 }266 267 /** Calculate cartesian coordinates from given polar ones.268 *269 * \param _polar vector with polar coordinates270 * \return cartesian coordinates271 */272 Vector getCartesianCoordinates(const std::vector<double> &_polar)273 {274 Vector cartesian;275 ASSERT( _polar.size() == 3,276 "convertToCartesianCoordinates() - tuples has insufficient components.");277 cartesian[0] = _polar[0] * sin(_polar[1]) * cos(_polar[2]);278 cartesian[1] = _polar[0] * sin(_polar[1]) * sin(_polar[2]);279 cartesian[2] = _polar[0] * cos(_polar[1]);280 return cartesian;281 }282 283 228 /** Rotates a given polygon around x, y, and z axis by the given angles. 284 229 * 285 230 * \param _polygon polygon whose points to rotate 286 * \param _ angles vector with rotation angles for x,y,z axis231 * \param _q quaternion specifying the rotation of the coordinate system 287 232 */ 288 233 SphericalPointDistribution::Polygon_t rotatePolygon( 289 234 const SphericalPointDistribution::Polygon_t &_polygon, 290 const std::vector<double> &_angles)235 const boost::math::quaternion<double> &_q) 291 236 { 292 237 SphericalPointDistribution::Polygon_t rotated_polygon = _polygon; 293 RealSpaceMatrix rotation; 294 ASSERT( _angles.size() == 3, 295 "rotatePolygon() - not exactly "+toString(3)+" components given."); 238 boost::math::quaternion<double> q_inverse = 239 boost::math::conj(_q)/(boost::math::norm(_q)); 296 240 297 241 // apply rotation angles 298 242 for (SphericalPointDistribution::Polygon_t::iterator iter = rotated_polygon.begin(); 299 243 iter != rotated_polygon.end(); ++iter) { 300 // transform to polar 301 std::vector<double> polar = getPolarCoordinates(*iter); 302 LOG(5, "DEBUG: Converting " << *iter << " to " << polar); 303 // sum up difference 304 std::transform( 305 _angles.begin(), _angles.end(), 306 polar.begin(), 307 polar.begin(), 308 std::plus<double>()); 309 // convert back 310 *iter = getCartesianCoordinates(polar); 311 LOG(5, "DEBUG: Converting modified " << polar << " to " << *iter); 244 Vector ¤t = *iter; 245 boost::math::quaternion<double> p(0, current[0], current[1], current[2]); 246 p = _q * p * q_inverse; 247 LOG(5, "DEBUG: Rotated point is " << p); 248 // i have no idea why but first component comes up with wrong sign 249 current[0] = -p.R_component_2(); 250 current[1] = p.R_component_3(); 251 current[2] = p.R_component_4(); 312 252 } 313 253 … … 352 292 // determine rotation angles to align the two point distributions with 353 293 // respect to bestmatching 354 std::vector<double> angles(NDIM); 355 Vector newCenter; 294 SphericalPointDistribution::Polygon_t rotated_newpolygon; 356 295 Vector oldCenter; 357 296 { 358 297 // calculate center of triangle/line/point consisting of first points of matching 298 Vector newCenter; 359 299 IndexList_t::const_iterator iter = MCS.bestmatching.begin(); 360 300 unsigned int i = 0; … … 367 307 LOG(4, "DEBUG: oldCenter is " << oldCenter << ", newCenter is " << newCenter); 368 308 369 // transform to polar coordinates and note difference in angular parts 370 std::vector<double> oldpolar = getPolarCoordinates(oldCenter); 371 std::vector<double> newpolar = getPolarCoordinates(newCenter); 372 std::vector<double> differencepolar; 373 std::transform( 374 oldpolar.begin(), oldpolar.end(), 375 newpolar.begin(), 376 std::back_inserter(differencepolar), 377 std::minus<double>()); 378 LOG(3, "INFO: (r,theta,phi) angles are" << differencepolar); 379 } 380 // rotate _newpolygon 381 SphericalPointDistribution::Polygon_t rotated_newpolygon = 382 rotatePolygon(_newpolygon, angles); 383 LOG(5, "DEBUG: Rotated new polygon is " << rotated_newpolygon); 384 309 if ((oldCenter - newCenter).NormSquared() > std::numeric_limits<double>::epsilon()*1e4) { 310 // setup quaternion 311 Vector RotationAxis = newCenter; 312 RotationAxis.VectorProduct(oldCenter); 313 RotationAxis.Normalize(); 314 const double RotationAngle = oldCenter.Angle(newCenter)/(M_PI/2.); 315 // RotationAxis.Angle(oldCenter) - RotationAxis.Angle(newCenter); 316 boost::math::quaternion<double> q 317 (RotationAngle, RotationAxis[0], RotationAxis[1], RotationAxis[2]); 318 LOG(5, "DEBUG: RotationAxis is " << RotationAxis 319 << ", RotationAngle is " << RotationAngle); 320 LOG(5, "DEBUG: Quaternion describing rotation is " << q); 321 #ifndef NDEBUG 322 { 323 // check that rotation works in DEBUG mode 324 boost::math::quaternion<double> p(0., newCenter[0], newCenter[1], newCenter[2]); 325 boost::math::quaternion<double> q_inverse = 326 boost::math::conj(q)/(boost::math::norm(q)); 327 p = q * p * q_inverse; 328 boost::math::quaternion<double> identity(1,0,0,0); 329 ASSERT( boost::math::norm(q*q_inverse - identity) < std::numeric_limits<double>::epsilon()*1e4, 330 "matchSphericalPointDistributions() - quaternion does not rotate newCenter " 331 +toString(q*q_inverse)+" into oldCenter "+toString(identity)+"."); 332 boost::math::quaternion<double> comparison(0., -oldCenter[0], oldCenter[1], oldCenter[2]); 333 ASSERT( boost::math::norm(p - comparison) < std::numeric_limits<double>::epsilon()*1e4, 334 "matchSphericalPointDistributions() - quaternion does not rotate newCenter " 335 +toString(p)+" into oldCenter "+toString(comparison)+"."); 336 } 337 #endif 338 339 // rotate spherical distribution 340 rotated_newpolygon = rotatePolygon(_newpolygon, q); 341 LOG(5, "DEBUG: Rotated new polygon is " << rotated_newpolygon); 342 } else { 343 rotated_newpolygon = _newpolygon; 344 } 345 } 346 // rotate triangle/line/point around itself to match orientation 385 347 const Line RotationAxis(zeroVec, oldCenter); 386 348 const double RotationAngle =
Note:
See TracChangeset
for help on using the changeset viewer.