/* * SphericalPointDistribution.hpp * * Created on: May 29, 2014 * Author: heber */ #ifndef SPHERICALPOINTDISTRIBUTION_HPP_ #define SPHERICALPOINTDISTRIBUTION_HPP_ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include "CodePatterns/Assert.hpp" #include #include #include "LinearAlgebra/Vector.hpp" /** contains getters for the VSEPR model for specific number of electrons. * * This struct contains specialized functions returning a list of Vectors * (points in space) to match the VSEPR model for the given number of electrons. * * This is implemented via template specialization of the function get(). * * These specializations are taken from the python script \b CreateVspeShapes.py * by Christian Neuen, 07th May 2009. */ struct SphericalPointDistribution { /** Cstor for SphericalPointDistribution, allows setting radius of sphere * * \param _BondLength desired radius of sphere */ SphericalPointDistribution(const double _Bondlength = 1.) : Bondlength(_Bondlength), SQRT_3(sqrt(3.0)) {} //!> typedef for the list of points typedef std::list Polygon_t; /** General getter function for the distribution of points on the surface. * * \warn this function needs to be specialized! * * \return Polygon_t with points on the surface centered at (0,0,0) */ template Polygon_t get() { ASSERT(0, "SphericalPointDistribution::get() - not specialized for "+toString(N)+"."); } /** Matches a given spherical distribution with another containing more * points. * * This is a helper to determine points where to best insert saturation * hydrogens. * * \param _polygon current occupied positions * \param _newpolygon ideal distribution to match best with current occupied * positions * \return remaining vacant positions relative to \a _polygon */ static Polygon_t matchSphericalPointDistributions( const Polygon_t &_polygon, const Polygon_t &_newpolygon ); //!> default radius of the spherical distribution const double Bondlength; //!> precalculated value for root of 3 const double SQRT_3; }; SphericalPointDistribution::Polygon_t SphericalPointDistribution::matchSphericalPointDistributions( const SphericalPointDistribution::Polygon_t &_polygon, const SphericalPointDistribution::Polygon_t &_newpolygon ) { SphericalPointDistribution::Polygon_t remainingpolygon = _newpolygon; return remainingpolygon; } template <> SphericalPointDistribution::Polygon_t SphericalPointDistribution::get<2>() { Polygon_t polygon; polygon.push_back( Vector(Bondlength,0.,0.)); polygon.push_back( Vector(-Bondlength,0.,0.)); ASSERT( polygon.size() == 2, "SphericalPointDistribution::get<2>() - polygon has wrong size."); return polygon; } template <> SphericalPointDistribution::Polygon_t SphericalPointDistribution::get<3>() { Polygon_t polygon; polygon.push_back( Vector(Bondlength,0.,0.)); polygon.push_back( Vector(-Bondlength*0.5, SQRT_3*0.5,0.)); polygon.push_back( Vector(-Bondlength*0.5, -SQRT_3*0.5,0.)); ASSERT( polygon.size() == 3, "SphericalPointDistribution::get<3>() - polygon has wrong size."); return polygon; } template <> SphericalPointDistribution::Polygon_t SphericalPointDistribution::get<4>() { Polygon_t polygon; polygon.push_back( Vector(Bondlength,0.,0.)); polygon.push_back( Vector(-Bondlength/3.0, Bondlength*2.0*M_SQRT2/3.0,0.)); polygon.push_back( Vector(-Bondlength/3.0, -Bondlength*M_SQRT2/3.0, Bondlength*M_SQRT2/SQRT_3)); polygon.push_back( Vector(-Bondlength/3.0, -Bondlength*M_SQRT2/3.0, -Bondlength*M_SQRT2/SQRT_3)); ASSERT( polygon.size() == 4, "SphericalPointDistribution::get<4>() - polygon has wrong size."); return polygon; } template <> SphericalPointDistribution::Polygon_t SphericalPointDistribution::get<5>() { Polygon_t polygon; polygon.push_back( Vector(Bondlength,0.,0.)); polygon.push_back( Vector(-Bondlength, 0.0, 0.0)); polygon.push_back( Vector(0.0, Bondlength, 0.0)); polygon.push_back( Vector(0.0, -Bondlength*0.5, Bondlength*SQRT_3*0.5)); polygon.push_back( Vector(0.0, -Bondlength*0.5, -Bondlength*SQRT_3*0.5)); ASSERT( polygon.size() == 5, "SphericalPointDistribution::get<5>() - polygon has wrong size."); return polygon; } template <> SphericalPointDistribution::Polygon_t SphericalPointDistribution::get<6>() { Polygon_t polygon; polygon.push_back( Vector(Bondlength,0.,0.)); polygon.push_back( Vector(-Bondlength, 0.0, 0.0)); polygon.push_back( Vector(0.0, Bondlength, 0.0)); polygon.push_back( Vector(0.0, -Bondlength, 0.0)); polygon.push_back( Vector(0.0, 0.0, Bondlength)); polygon.push_back( Vector(0.0, 0.0, -Bondlength)); ASSERT( polygon.size() == 6, "SphericalPointDistribution::get<6>() - polygon has wrong size."); return polygon; } template <> SphericalPointDistribution::Polygon_t SphericalPointDistribution::get<7>() { Polygon_t polygon; polygon.push_back( Vector(Bondlength,0.,0.)); polygon.push_back( Vector(-Bondlength, 0.0, 0.0)); polygon.push_back( Vector(0.0, Bondlength, 0.0)); polygon.push_back( Vector(0.0, Bondlength*cos(M_PI*0.4), Bondlength*sin(M_PI*0.4))); polygon.push_back( Vector(0.0, Bondlength*cos(M_PI*0.8), Bondlength*sin(M_PI*0.8))); polygon.push_back( Vector(0.0, Bondlength*cos(M_PI*1.2), Bondlength*sin(M_PI*1.2))); polygon.push_back( Vector(0.0, Bondlength*cos(M_PI*1.6), Bondlength*sin(M_PI*1.6))); ASSERT( polygon.size() == 7, "SphericalPointDistribution::get<7>() - polygon has wrong size."); return polygon; } template <> SphericalPointDistribution::Polygon_t SphericalPointDistribution::get<8>() { Polygon_t polygon; polygon.push_back( Vector(Bondlength,0.,0.)); polygon.push_back( Vector(-Bondlength, 0.0, 0.0)); polygon.push_back( Vector(-Bondlength/3.0, Bondlength*2.0*M_SQRT2/3.0, 0.0)); polygon.push_back( Vector(-Bondlength/3.0, -Bondlength*M_SQRT2/3.0, Bondlength*M_SQRT2/SQRT_3)); polygon.push_back( Vector(-Bondlength/3.0, -Bondlength*M_SQRT2/3.0, -Bondlength*M_SQRT2/SQRT_3)); polygon.push_back( Vector(Bondlength/3.0, -Bondlength*2.0*M_SQRT2/3.0, 0.0)); polygon.push_back( Vector(Bondlength/3.0, Bondlength*M_SQRT2/3.0, -Bondlength*M_SQRT2/SQRT_3)); polygon.push_back( Vector(Bondlength/3.0, Bondlength*M_SQRT2/3.0, Bondlength*M_SQRT2/SQRT_3)); ASSERT( polygon.size() == 8, "SphericalPointDistribution::get<8>() - polygon has wrong size."); return polygon; } template <> SphericalPointDistribution::Polygon_t SphericalPointDistribution::get<9>() { Polygon_t polygon; polygon.push_back( Vector(Bondlength,0.,0.)); polygon.push_back( Vector(Bondlength*cos(0.4*M_PI), Bondlength*sin(0.4*M_PI), 0.0)); polygon.push_back( Vector(Bondlength*cos(0.4*M_PI), -Bondlength*sin(0.4*M_PI), 0.0)); polygon.push_back( Vector(Bondlength*cos(0.4*M_PI), 0.0, Bondlength*sin(0.4*M_PI))); polygon.push_back( Vector(Bondlength*cos(0.4*M_PI), 0.0, -Bondlength*sin(0.4*M_PI))); polygon.push_back( Vector(Bondlength*cos(0.8*M_PI), Bondlength*sin(0.8*M_PI)*sin(0.25*M_PI), Bondlength*sin(0.8*M_PI)*cos(0.25*M_PI))); polygon.push_back( Vector(Bondlength*cos(0.8*M_PI), Bondlength*sin(0.8*M_PI)*sin(0.75*M_PI), Bondlength*sin(0.8*M_PI)*cos(0.75*M_PI))); polygon.push_back( Vector(Bondlength*cos(0.8*M_PI), Bondlength*sin(0.8*M_PI)*sin(1.25*M_PI), Bondlength*sin(0.8*M_PI)*cos(1.25*M_PI))); polygon.push_back( Vector(Bondlength*cos(0.8*M_PI), Bondlength*sin(0.8*M_PI)*sin(1.75*M_PI), Bondlength*sin(0.8*M_PI)*cos(1.75*M_PI))); ASSERT( polygon.size() == 9, "SphericalPointDistribution::get<9>() - polygon has wrong size."); return polygon; } template <> SphericalPointDistribution::Polygon_t SphericalPointDistribution::get<10>() { Polygon_t polygon; polygon.push_back( Vector(Bondlength,0.,0.)); polygon.push_back( Vector(-Bondlength, 0.0, 0.0)); const double temp_Bondlength = Bondlength*0.5*SQRT_3; polygon.push_back( Vector(temp_Bondlength/SQRT_3, temp_Bondlength, 0.0)); polygon.push_back( Vector(temp_Bondlength/SQRT_3, -temp_Bondlength, 0.0)); polygon.push_back( Vector(temp_Bondlength/SQRT_3, 0.0, temp_Bondlength)); polygon.push_back( Vector(temp_Bondlength/SQRT_3, 0.0, -temp_Bondlength)); polygon.push_back( Vector(-temp_Bondlength/SQRT_3, temp_Bondlength*sin(0.25*M_PI), temp_Bondlength*cos(0.25*M_PI))); polygon.push_back( Vector(-temp_Bondlength/SQRT_3, temp_Bondlength*sin(0.75*M_PI), temp_Bondlength*cos(0.75*M_PI))); polygon.push_back( Vector(-temp_Bondlength/SQRT_3, temp_Bondlength*sin(1.25*M_PI), temp_Bondlength*cos(1.25*M_PI))); polygon.push_back( Vector(-temp_Bondlength/SQRT_3, temp_Bondlength*sin(1.75*M_PI), temp_Bondlength*cos(1.75*M_PI))); ASSERT( polygon.size() == 10, "SphericalPointDistribution::get<10>() - polygon has wrong size."); return polygon; } template <> SphericalPointDistribution::Polygon_t SphericalPointDistribution::get<11>() { Polygon_t polygon; polygon.push_back( Vector(Bondlength,0.,0.)); { const double temp_Bondlength = Bondlength*sin(0.4*M_PI); polygon.push_back( Vector(Bondlength*cos(0.4*M_PI), temp_Bondlength, 0.0)); polygon.push_back( Vector(Bondlength*cos(0.4*M_PI), temp_Bondlength*cos(0.4*M_PI), temp_Bondlength*sin(0.4*M_PI))); polygon.push_back( Vector(Bondlength*cos(0.4*M_PI), temp_Bondlength*cos(0.8*M_PI), temp_Bondlength*sin(0.8*M_PI))); polygon.push_back( Vector(Bondlength*cos(0.4*M_PI), temp_Bondlength*cos(1.2*M_PI), temp_Bondlength*sin(1.2*M_PI))); polygon.push_back( Vector(Bondlength*cos(0.4*M_PI), temp_Bondlength*cos(1.6*M_PI), temp_Bondlength*sin(1.6*M_PI))); } { const double temp_Bondlength = Bondlength*sin(0.8*M_PI); polygon.push_back( Vector(Bondlength*cos(0.8*M_PI), temp_Bondlength*cos(0.2*M_PI), temp_Bondlength*sin(0.2*M_PI))); polygon.push_back( Vector(Bondlength*cos(0.8*M_PI), temp_Bondlength*cos(0.6*M_PI), temp_Bondlength*sin(0.6*M_PI))); polygon.push_back( Vector(Bondlength*cos(0.8*M_PI), temp_Bondlength*cos(1.0*M_PI), temp_Bondlength*sin(1.0*M_PI))); polygon.push_back( Vector(Bondlength*cos(0.8*M_PI), temp_Bondlength*cos(1.4*M_PI), temp_Bondlength*sin(1.4*M_PI))); polygon.push_back( Vector(Bondlength*cos(0.8*M_PI), temp_Bondlength*cos(1.8*M_PI), temp_Bondlength*sin(1.8*M_PI))); } ASSERT( polygon.size() == 11, "SphericalPointDistribution::get<11>() - polygon has wrong size."); return polygon; } template <> SphericalPointDistribution::Polygon_t SphericalPointDistribution::get<12>() { Polygon_t polygon; polygon.push_back( Vector(Bondlength,0.,0.)); polygon.push_back( Vector(-Bondlength, 0.0, 0.0)); const double temp_Bondlength = Bondlength*0.5*SQRT_3; polygon.push_back( Vector(temp_Bondlength/SQRT_3, temp_Bondlength, 0.0)); polygon.push_back( Vector(temp_Bondlength/SQRT_3, temp_Bondlength*cos(0.4*M_PI), temp_Bondlength*sin(0.4*M_PI))); polygon.push_back( Vector(temp_Bondlength/SQRT_3, temp_Bondlength*cos(0.8*M_PI), temp_Bondlength*sin(0.8*M_PI))); polygon.push_back( Vector(temp_Bondlength/SQRT_3, temp_Bondlength*cos(1.2*M_PI), temp_Bondlength*sin(1.2*M_PI))); polygon.push_back( Vector(temp_Bondlength/SQRT_3, temp_Bondlength*cos(1.6*M_PI), temp_Bondlength*sin(1.6*M_PI))); polygon.push_back( Vector(-temp_Bondlength/SQRT_3, -temp_Bondlength, 0.0)); polygon.push_back( Vector(-temp_Bondlength/SQRT_3, -temp_Bondlength*cos(0.4*M_PI), -temp_Bondlength*sin(0.4*M_PI))); polygon.push_back( Vector(-temp_Bondlength/SQRT_3, -temp_Bondlength*cos(0.8*M_PI), -temp_Bondlength*sin(0.8*M_PI))); polygon.push_back( Vector(-temp_Bondlength/SQRT_3, -temp_Bondlength*cos(1.2*M_PI), -temp_Bondlength*sin(1.2*M_PI))); polygon.push_back( Vector(-temp_Bondlength/SQRT_3, -temp_Bondlength*cos(1.6*M_PI), -temp_Bondlength*sin(1.6*M_PI))); ASSERT( polygon.size() == 12, "SphericalPointDistribution::get<12>() - polygon has wrong size."); return polygon; } template <> SphericalPointDistribution::Polygon_t SphericalPointDistribution::get<14>() { Polygon_t polygon; polygon.push_back( Vector(Bondlength,0.,0.)); polygon.push_back( Vector(-Bondlength, 0.0, 0.0)); const double temp_Bondlength = Bondlength*0.5*SQRT_3; polygon.push_back( Vector(temp_Bondlength/SQRT_3, temp_Bondlength, 0.0)); polygon.push_back( Vector(temp_Bondlength/SQRT_3, temp_Bondlength*cos(M_PI/3.0), temp_Bondlength*sin(M_PI/3.0))); polygon.push_back( Vector(temp_Bondlength/SQRT_3, temp_Bondlength*cos(2.0*M_PI/3.0), temp_Bondlength*sin(2.0*M_PI/3.0))); polygon.push_back( Vector(temp_Bondlength/SQRT_3, -temp_Bondlength, 0.0)); polygon.push_back( Vector(temp_Bondlength/SQRT_3, temp_Bondlength*cos(4.0*M_PI/3.0), temp_Bondlength*sin(4.0*M_PI/3.0))); polygon.push_back( Vector(temp_Bondlength/SQRT_3, temp_Bondlength*cos(5.0*M_PI/3.0), temp_Bondlength*sin(5.0*M_PI/3.0))); polygon.push_back( Vector(-temp_Bondlength/SQRT_3, temp_Bondlength*cos(M_PI/6.0), temp_Bondlength*sin(M_PI/6.0))); polygon.push_back( Vector(-temp_Bondlength/SQRT_3, temp_Bondlength*cos(M_PI/3.0 +M_PI/6.0), temp_Bondlength*sin(M_PI/3.0+M_PI/6.0))); polygon.push_back( Vector(-temp_Bondlength/SQRT_3, temp_Bondlength*cos(2.0*M_PI/3.0 +M_PI/6.0), temp_Bondlength*sin(2.0*M_PI/3.0 +M_PI/6.0))); polygon.push_back( Vector(-temp_Bondlength/SQRT_3, temp_Bondlength*cos(3.0*M_PI/3.0 +M_PI/6.0), temp_Bondlength*sin(3.0*M_PI/3.0 +M_PI/6.0))); polygon.push_back( Vector(-temp_Bondlength/SQRT_3, temp_Bondlength*cos(4.0*M_PI/3.0 +M_PI/6.0), temp_Bondlength*sin(4.0*M_PI/3.0 +M_PI/6.0))); polygon.push_back( Vector(-temp_Bondlength/SQRT_3, temp_Bondlength*cos(5.0*M_PI/3.0 +M_PI/6.0), temp_Bondlength*sin(5.0*M_PI/3.0 +M_PI/6.0))); ASSERT( polygon.size() == 14, "SphericalPointDistribution::get<14>() - polygon has wrong size."); return polygon; } #endif /* SPHERICALPOINTDISTRIBUTION_HPP_ */