← Back to team overview

yade-dev team mailing list archive

[Branch ~yade-dev/yade/trunk] Rev 2494: 1. Clean up Vector6 and friends

 

------------------------------------------------------------
revno: 2494
committer: Václav Šmilauer <eu@xxxxxxxx>
branch nick: yade
timestamp: Sun 2010-10-17 14:55:29 +0200
message:
  1. Clean up Vector6 and friends
  2. Create Matrix_computeUnitaryPositive template to be compat between eigen2 and eigen3 (in the future)
modified:
  lib/base/Math.hpp
  pkg/dem/Clump.cpp
  pkg/dem/PeriIsoCompressor.cpp
  pkg/dem/Tetra.cpp
  py/mathWrap/miniEigen.cpp


--
lp:yade
https://code.launchpad.net/~yade-dev/yade/trunk

Your team Yade developers is subscribed to branch lp:yade.
To unsubscribe from this branch go to https://code.launchpad.net/~yade-dev/yade/trunk/+edit-subscription
=== modified file 'lib/base/Math.hpp'
--- lib/base/Math.hpp	2010-10-17 08:43:51 +0000
+++ lib/base/Math.hpp	2010-10-17 12:55:29 +0000
@@ -25,24 +25,35 @@
 // different macros for different versions of eigen:
 //  http://bitbucket.org/eigen/eigen/issue/96/eigen_dont_align-doesnt-exist-in-205-but-appears-in-web
 
-//#define EIGEN2_SUPPORT  //This makes Eigen3 migration easier
-#define EIGEN_DONT_VECTORIZE
-#define EIGEN_DONT_ALIGN
+#define EIGEN2_SUPPORT  // This makes Eigen3 migration easier
+
+// disable optimization which are "unsafe":
+//    eigen objects cannot be passed by-value, otherwise they will no be aligned
+#if 1
+	#define EIGEN_DONT_VECTORIZE
+	#define EIGEN_DONT_ALIGN
+#endif
+
 #define EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
 #define EIGEN_NO_DEBUG
-	#include<Eigen/Core>
-	#include<Eigen/Geometry>
-	#include<Eigen/Array>
-	#include<Eigen/QR>
-	#include<Eigen/LU>
-	#include<float.h>
+#include<Eigen/Core>
+#include<Eigen/Geometry>
+#include<Eigen/Array>
+#include<Eigen/QR>
+#include<Eigen/LU>
+#include<Eigen/SVD>
+#include<float.h>
+
 // USING_PART_OF_NAMESPACE_EIGEN
 //using namespace eigen; // for eigen3
 // 
-// templates of those types with single parameter are not possible (for compat with Wm3), use macros for now
+
+// templates of those types with single parameter are not possible, use macros for now
 #define VECTOR2_TEMPLATE(Scalar) Eigen::Matrix<Scalar,2,1>
 #define VECTOR3_TEMPLATE(Scalar) Eigen::Matrix<Scalar,3,1>
+#define VECTOR6_TEMPLATE(Scalar) Eigen::Matrix<Scalar,6,1>
 #define MATRIX3_TEMPLATE(Scalar) Eigen::Matrix<Scalar,3,3>
+
 // this would be the proper way, but only works in c++-0x (not yet supported by gcc (4.5))
 #if 0
 	template<typename Scalar> using Vector2=Eigen::Matrix<Scalar,2,1>;
@@ -57,18 +68,19 @@
 typedef VECTOR2_TEMPLATE(Real) Vector2r;
 typedef VECTOR3_TEMPLATE(int) Vector3i;
 typedef VECTOR3_TEMPLATE(Real) Vector3r;
+typedef VECTOR6_TEMPLATE(Real) Vector6r;
+typedef VECTOR6_TEMPLATE(int) Vector6i;
 typedef MATRIX3_TEMPLATE(Real) Matrix3r;
 
 typedef Eigen::Quaternion<Real> Quaternionr;
 typedef Eigen::AngleAxis<Real> AngleAxisr;
 using Eigen::AngleAxis; using Eigen::Quaternion;
 
-
 // io
 template<class Scalar> std::ostream & operator<<(std::ostream &os, const VECTOR2_TEMPLATE(Scalar)& v){ os << v.x()<<" "<<v.y(); return os; };
 template<class Scalar> std::ostream & operator<<(std::ostream &os, const VECTOR3_TEMPLATE(Scalar)& v){ os << v.x()<<" "<<v.y()<<" "<<v.z(); return os; };
+template<class Scalar> std::ostream & operator<<(std::ostream &os, const VECTOR6_TEMPLATE(Scalar)& v){ os << v[0]<<" "<<v[1]<<" "<<v[2]<<" "<<v[3]<<" "<<v[4]<<" "<<v[5]; return os; };
 template<class Scalar> std::ostream & operator<<(std::ostream &os, const Eigen::Quaternion<Scalar>& q){ os<<q.w()<<" "<<q.x()<<" "<<q.y()<<" "<<q.z(); return os; };
-
 // operators
 //template<class Scalar> VECTOR3_TEMPLATE(Scalar) operator*(Scalar s, const VECTOR3_TEMPLATE(Scalar)& v) {return v*s;}
 //template<class Scalar> MATRIX3_TEMPLATE(Scalar) operator*(Scalar s, const MATRIX3_TEMPLATE(Scalar)& m) { return m*s; }
@@ -80,6 +92,8 @@
 template<typename Scalar> bool operator!=(const Quaternion<Scalar>& u, const Quaternion<Scalar>& v){ return !(u==v); }
 template<typename Scalar> bool operator==(const MATRIX3_TEMPLATE(Scalar)& m, const MATRIX3_TEMPLATE(Scalar)& n){ for(int i=0;i<3;i++)for(int j=0;j<3;j++)if(m(i,j)!=n(i,j)) return false; return true; }
 template<typename Scalar> bool operator!=(const MATRIX3_TEMPLATE(Scalar)& m, const MATRIX3_TEMPLATE(Scalar)& n){ return !(m==n); }
+template<typename Scalar> bool operator==(const VECTOR6_TEMPLATE(Scalar)& u, const VECTOR6_TEMPLATE(Scalar)& v){ return u[0]==v[0] && u[1]==v[1] && u[2]==v[2] && u[3]==v[3] && u[4]==v[4] && u[5]==v[5]; }
+template<typename Scalar> bool operator!=(const VECTOR6_TEMPLATE(Scalar)& u, const VECTOR6_TEMPLATE(Scalar)& v){ return !(u==v); }
 template<typename Scalar> bool operator==(const VECTOR3_TEMPLATE(Scalar)& u, const VECTOR3_TEMPLATE(Scalar)& v){ return u.x()==v.x() && u.y()==v.y() && u.z()==v.z(); }
 template<typename Scalar> bool operator!=(const VECTOR3_TEMPLATE(Scalar)& u, const VECTOR3_TEMPLATE(Scalar)& v){ return !(u==v); }
 template<typename Scalar> bool operator==(const VECTOR2_TEMPLATE(Scalar)& u, const VECTOR2_TEMPLATE(Scalar)& v){ return u.x()==v.x() && u.y()==v.y(); }
@@ -106,76 +120,40 @@
 };
 typedef Math<Real> Mathr;
 
-/*
- * Compatibility bridge for Wm3 and eigen (will be removed once Wm3 is dropped and replaced by respective eigen constructs;
- * see https://www.yade-dem.org/wiki/Wm3→Eigen
- *
- * TODO
- */
-
-// eigen: m << m00,m01,m02,m10,m11,m12,m20,m21,m22;
-template<typename Scalar> MATRIX3_TEMPLATE(Scalar) matrixFromElements(Scalar m00, Scalar m01, Scalar m02, Scalar m10, Scalar m11, Scalar m12, Scalar m20, Scalar m21, Scalar m22){ MATRIX3_TEMPLATE(Scalar) m; m(0,0)=m00; m(0,1)=m01; m(0,2)=m02; m(1,0)=m10; m(1,1)=m11; m(1,2)=m12; m(2,0)=m20; m(2,1)=m21; m(2,2)=m22; return m; }
+/* this was removed in eigen3, see http://forum.kde.org/viewtopic.php?f=74&t=90914 */
+template<typename MatrixT>
+void Matrix_computeUnitaryPositive(const MatrixT& in, MatrixT* unitary, MatrixT* positive){
+	assert(unitary); assert(positive); 
+	#if EIGEN_WORLD_VERSION<3
+		Eigen::SVD<MatrixT>(in).computeUnitaryPositive(unitary,positive);
+	#else
+		Eigen::JacobiSVD<MatrixT> svd(in, Eigen::ComputeThinU | Eigen::ComputeThinV);
+		*unitary=svd.matrixU() * svd.matrixV().adjoint();
+		*positive=svd.matrixV() * svd.singularValues().asDiagonal() * svg.matrixV().adjoint;
+	#endif
+}
 
 /*
  * Extra yade math functions and classes
  */
 
-// Vector6r
-class Vector6r : public Eigen::Matrix<Real,6,1> {
-	// from http://www.ros.org/wiki/eigen
-	typedef Eigen::Matrix<Real,6,1> BaseClass;
-	public:
-		Vector6r() : BaseClass() {};
-		template<typename OtherDerived> Vector6r(const Eigen::MatrixBase<OtherDerived>& other) : BaseClass(other) {}
-		Vector6r(Real v0, Real v1, Real v2, Real v3, Real v4, Real v5){
-			this->operator()(0)=v0; this->operator()(1)=v1; this->operator()(2)=v2;
-			this->operator()(3)=v3; this->operator()(4)=v4; this->operator()(5)=v5;
-		};
-		using BaseClass::operator=;
-		// conversion from tensor (Matrix3r=(xx,xy,xz, yx,yy,yz, zx,zy,zz)) to Verctor6=(xx,yy,zz,yz,zx,xy)
-		Vector6r fromMatrix (const Matrix3r& m, const bool strain=false) {
-			Real k=(strain? 2.:1.);
-			Vector6r ret;
-			ret(0)=m(0,0); ret(1)=m(1,1); ret(2)=m(2,2);
-			ret(3)=k*.5*(m(1,2)+m(2,1)); ret(4)=k*.5*(m(2,0)+m(0,2)); ret(5)=k*.5*(m(0,1)+m(1,0));
-			return ret;
-		};
-		// conversion from Verctor6=(xx,yy,zz,yz,zx,xy) to tensor (Matrix3r=(xx,xy,xz, yx,yy,yz, zx,zy,zz))
-		Matrix3r toMatrix (const bool strain=false) {
-			Matrix3r ret;
-			Real k=(strain? .5:1.);
-			ret(0,0)=this->operator()(0); ret(1,1)=this->operator()(1); ret(2,2)=this->operator()(2);
-			ret(0,1)=ret(1,0)=k*this->operator()(5); ret(0,2)=ret(2,0)=k*this->operator()(4); ret(1,2)=ret(2,1)=k*this->operator()(3);
-			return ret;
-		};
-		Real maxabs (void) {
-			Real ret = 0.;
-			for (int i=0; i<6; i++) {
-				if (ret < abs(this->operator()(i))) {ret = abs(this->operator()(i));}
-			}
-			return ret;
-		}
-};
-//std::ostream & operator<<(std::ostream &os, const Vector6r& v){ os << v(0)<<" "<<v(1)<<" "<<v(2)<<" "<<v(3)<<" "<<v(4)<<" "<<v(5); return os; };
-//bool operator==(const Vector6r& u, const Vector6r& v){ return u(0)==v(0) && u(1)==v(1) && u(2)==v(2) && u(3)==v(3) && u(4)==v(4) && u(5)==v(5); }
-//bool operator!=(const Vector6r& u, const Vector6r& v){ return !(u==v); }
 
-// Vector6i
-class Vector6i : public Eigen::Matrix<int,6,1> {
-	// from http://www.ros.org/wiki/eigen
-	typedef Eigen::Matrix<int,6,1> BaseClass;
-	public:
-		Vector6i() : BaseClass() {};
-		template<typename OtherDerived> Vector6i(const Eigen::MatrixBase<OtherDerived>& other) : BaseClass(other) {}
-		Vector6i(int v0, int v1, int v2, int v3, int v4, int v5){
-			this->operator()(0)=v0; this->operator()(1)=v1; this->operator()(2)=v2;
-			this->operator()(3)=v3; this->operator()(4)=v4; this->operator()(5)=v5;
-		};
-		using BaseClass::operator=;
-};
-//std::ostream & operator<<(std::ostream &os, const Vector6i& v){ os << v(0)<<" "<<v(1)<<" "<<v(2)<<" "<<v(3)<<" "<<v(4)<<" "<<v(5); return os; };
-//bool operator==(const Vector6i& u, const Vector6i& v){ return u(0)==v(0) && u(1)==v(1) && u(2)==v(2) && u(3)==v(3) && u(4)==v(4) && u(5)==v(5); }
-//bool operator!=(const Vector6i& u, const Vector6i& v){ return !(u==v); }
+/* convert Vector6r in the Voigt notation to corresponding 2nd order symmetric tensor (stored as Matrix3r)
+	if strain is true, then multiply non-diagonal parts by .5
+*/
+template<typename Scalar>
+MATRIX3_TEMPLATE(Scalar) voigt_toSymmTensor(const VECTOR6_TEMPLATE(Scalar)& v, bool strain=false){
+	Real k=(strain?.5:1.);
+	MATRIX3_TEMPLATE(Scalar) ret; ret<<v[0],k*v[5],k*v[4], k*v[5],v[1],k*v[3], k*v[4],k*v[3],v[2]; return ret;
+}
+/* convert 2nd order tensor to 6-vector (Voigt notation), symmetrizing the tensor;
+	if strain is true, multiply non-diagonal compoennts by 2.
+*/
+template<typename Scalar>
+VECTOR6_TEMPLATE(Scalar) tensor_toVoigt(const MATRIX3_TEMPLATE(Scalar)& m, bool strain=false){
+	int k=(strain?2:1);
+	VECTOR6_TEMPLATE(Scalar) ret; ret<<m(0,0),m(1,1),m(2,2),k*.5*(m(1,2)+m(2,1)),k*.5*(m(2,0)+m(0,2)),k*.5*(m(0,1)+m(1,0)); return ret;
+}
 
 
 __attribute__((unused))
@@ -276,8 +254,7 @@
 }
 
 template<class Archive>
-void serialize(Archive & ar, Vector6r & g, const unsigned int version)
-{
+void serialize(Archive & ar, Vector6r & g, const unsigned int version){
 	Real &v0=g[0], &v1=g[1], &v2=g[2], &v3=g[3], &v4=g[4], &v5=g[5];
 	ar & BOOST_SERIALIZATION_NVP(v0) & BOOST_SERIALIZATION_NVP(v1) & BOOST_SERIALIZATION_NVP(v2) & BOOST_SERIALIZATION_NVP(v3) & BOOST_SERIALIZATION_NVP(v4) & BOOST_SERIALIZATION_NVP(v5);
 }

=== modified file 'pkg/dem/Clump.cpp'
--- pkg/dem/Clump.cpp	2010-10-13 16:23:08 +0000
+++ pkg/dem/Clump.cpp	2010-10-17 12:55:29 +0000
@@ -274,9 +274,10 @@
 	//TRWM3VEC(off); TRVAR2(ooff,m); TRWM3MAT(I);
 	// translation away from centroid
 	/* I^c_jk=I'_jk-M*(delta_jk R.R - R_j*R_k) [http://en.wikipedia.org/wiki/Moments_of_inertia#Parallel_axes_theorem] */
-	I2+=m*matrixFromElements(/* dIxx */ ooff-off[0]*off[0], /* dIxy */ -off[0]*off[1], /* dIxz */ -off[0]*off[2],
+	Matrix3r dI; dI<</* dIxx */ ooff-off[0]*off[0], /* dIxy */ -off[0]*off[1], /* dIxz */ -off[0]*off[2],
 		/* sym */ 0., /* dIyy */ ooff-off[1]*off[1], /* dIyz */ -off[1]*off[2],
-		/* sym */ 0., /* sym */ 0., /* dIzz */ ooff-off[2]*off[2]);
+		/* sym */ 0., /* sym */ 0., /* dIzz */ ooff-off[2]*off[2];
+	I2+=m*dI;
 	I2(1,0)=I2(0,1); I2(2,0)=I2(0,2); I2(2,1)=I2(1,2);
 	//TRWM3MAT(I2);
 	return I2;

=== modified file 'pkg/dem/PeriIsoCompressor.cpp'
--- pkg/dem/PeriIsoCompressor.cpp	2010-10-17 08:43:51 +0000
+++ pkg/dem/PeriIsoCompressor.cpp	2010-10-17 12:55:29 +0000
@@ -370,10 +370,10 @@
 	// Update - update values from previous step to current step
 	stressOld = stress; // stresssOld = stress at previous step
 	sigma = Shop::stressTensorOfPeriodicCell(/*smallStrains=*/true); // current stress tensor
-	stress = stress.fromMatrix(sigma); // current stress vector
+	stress = tensor_toVoigt(sigma); // current stress vector
 	stressIdeal += stressRate*dt; // stress that would be obtained if the predictor would be perfect
 	strain += strainRate*dt; // current strain vector
-	epsilon = strain.toMatrix(/*strain=*/true); // current strain tensor
+	epsilon = voigt_toSymmTensor(strain,/*strain=*/true); // current strain tensor
 
 	/* StrainPredictor
 			extremely primitive predictor, but roboust enough and works fine :-) could be replaced by some more rigorous in future.
@@ -399,7 +399,7 @@
 			//for (int i=0; i<lenPs; i++) { strainRate(ps(i)) -= maxStrainRate; }
 		}
 		else { // actual predictor
-			Real sr=strainRate.maxabs();
+			Real sr=strainRate.cwise().abs().maxCoeff();
 			for (int i=0; i<lenPs; i++) {
 				int j=ps(i);
 				// linear extrapolation of stress error (difference between actual and ideal stress)
@@ -412,28 +412,16 @@
 	}
 	
 	// correction coefficient ix strainRate.maxabs() > maxStrainRate
-	Real srCorr = (strainRate.maxabs() > maxStrainRate)? (maxStrainRate/strainRate.maxabs()):1.;
+	Real srCorr = (strainRate.cwise().abs().maxCoeff() > maxStrainRate)? (maxStrainRate/strainRate.cwise().abs().maxCoeff()):1.;
 	strainRate *= srCorr;
 
 	// Actual action (see the documentation for more info)
 	const Matrix3r& trsf=scene->cell->trsf;
 	// compute rotational and nonrotational (strain in local coordinates) part of trsf
-	Eigen::SVD<Matrix3r>(trsf).computeUnitaryPositive(&rot,&nonrot);
-	/*
-	//Eigen3 does not have computeUnitaryPositive() implemented. Next few lines of code replace missing functions. Tested. Anton,
-	Matrix3r mU, mV, mS;
-        Eigen::JacobiSVD<Matrix3r> svd(trsf, Eigen::ComputeThinU | Eigen::ComputeThinV);
-
-        mU = svd.matrixU();
-        mV = svd.matrixV();
-        mS = svd.singularValues().asDiagonal();
-
-        rot = mU * mV.adjoint();
-        nonrot = mV * mS * mV.adjoint(); 
-	*/
+	Matrix_computeUnitaryPositive(trsf,&rot,&nonrot);
 	 
 	// prescribed velocity gradient (strain tensor rate) in global coordinates
-	epsilonRate = strainRate.toMatrix(/*strain=*/true); 
+	epsilonRate = voigt_toSymmTensor(strainRate,/*strain=*/true); 
 	/* transformation of prescribed strain rate (computed by predictor) into local cell coordinates,
 	   multiplying by time to obtain strain increment and adding it to nonrot (current strain in local coordinates)*/
 	nonrot += rot.transpose()*(epsilonRate*dt)*rot; 
@@ -444,7 +432,7 @@
 	velGrad = ((rot*nonrot)*trsf.inverse()- Matrix3r::Identity()) / dt ;
 	progress += srCorr/nSteps;
 
-	if (progress >= 1. || strain.maxabs() > maxStrain) {
+	if (progress >= 1. || strain.cwise().abs().maxCoeff() > maxStrain) {
 		if(doneHook.empty()){ LOG_INFO("No doneHook set, dying."); dead=true; }
 		else{ LOG_INFO("Running doneHook: "<<doneHook);	pyRunString(doneHook);}
 	}

=== modified file 'pkg/dem/Tetra.cpp'
--- pkg/dem/Tetra.cpp	2010-10-13 16:23:08 +0000
+++ pkg/dem/Tetra.cpp	2010-10-17 12:55:29 +0000
@@ -515,10 +515,11 @@
 		2*x2*y2+x3*y2+x4*y2+x1*y3+x2*y3+2*x3*y3+
 		x4*y3+x1*y4+x2*y4+x3*y4+2*x4*y4)/120.;
 
-	return matrixFromElements(
+	Matrix3r ret; ret<<
 		a   , -b__, -c__,
 		-b__, b   , -a__,
-		-c__, -a__, c    );
+		-c__, -a__, c    ;
+	return ret;
 
 	#undef x1
 	#undef y1

=== modified file 'py/mathWrap/miniEigen.cpp'
--- py/mathWrap/miniEigen.cpp	2010-10-17 01:06:13 +0000
+++ py/mathWrap/miniEigen.cpp	2010-10-17 12:55:29 +0000
@@ -16,117 +16,80 @@
 #define IDX_CHECK(i,MAX){ if(i<0 || i>=MAX) { PyErr_SetString(PyExc_IndexError, ("Index out of range 0.." + boost::lexical_cast<std::string>(MAX-1)).c_str()); bp::throw_error_already_set(); } }
 #define IDX2_CHECKED_TUPLE_INTS(tuple,max2,arr2) {int l=bp::len(tuple); if(l!=2) { PyErr_SetString(PyExc_IndexError,"Index must be integer or a 2-tuple"); bp::throw_error_already_set(); } for(int _i=0; _i<2; _i++) { bp::extract<int> val(tuple[_i]); if(!val.check()) throw std::runtime_error("Unable to convert "+boost::lexical_cast<std::string>(_i)+"-th index to int."); int v=val(); IDX_CHECK(v,max2[_i]); arr2[_i]=v; }  }
 
+void Vector6r_set_item(Vector6r & self, int idx, Real value){ IDX_CHECK(idx,6); self[idx]=value; }
+void Vector6i_set_item(Vector6i & self, int idx, int  value){ IDX_CHECK(idx,6); self[idx]=value; }
 void Vector3r_set_item(Vector3r & self, int idx, Real value){ IDX_CHECK(idx,3); self[idx]=value; }
 void Vector3i_set_item(Vector3i & self, int idx, int  value){ IDX_CHECK(idx,3); self[idx]=value; }
 void Vector2r_set_item(Vector2r & self, int idx, Real value){ IDX_CHECK(idx,2); self[idx]=value; }
 void Vector2i_set_item(Vector2i & self, int idx, int  value){ IDX_CHECK(idx,2); self[idx]=value; }
-void Vector6r_set_item(Vector6r & self, int idx, Real value){ IDX_CHECK(idx,6); self[idx]=value; }
-void Vector6i_set_item(Vector6i & self, int idx, int  value){ IDX_CHECK(idx,6); self[idx]=value; }
 
 void Quaternionr_set_item(Quaternionr & self, int idx, Real value){ IDX_CHECK(idx,4);  if(idx==0) self.x()=value; else if(idx==1) self.y()=value; else if(idx==2) self.z()=value; else if(idx==3) self.w()=value; }
 void Matrix3r_set_item(Matrix3r & self, bp::tuple _idx, Real value){ int idx[2]; int mx[2]={3,3}; IDX2_CHECKED_TUPLE_INTS(_idx,mx,idx); self(idx[0],idx[1])=value; }
 void Matrix3r_set_item_linear(Matrix3r & self, int idx, Real value){ IDX_CHECK(idx,9); self(idx/3,idx%3)=value; }
 
+Real Vector6r_get_item(const Vector6r & self, int idx){ IDX_CHECK(idx,6); return self[idx]; }
+int  Vector6i_get_item(const Vector6r & self, int idx){ IDX_CHECK(idx,6); return self[idx]; }
 Real Vector3r_get_item(const Vector3r & self, int idx){ IDX_CHECK(idx,3); return self[idx]; }
 int  Vector3i_get_item(const Vector3i & self, int idx){ IDX_CHECK(idx,3); return self[idx]; }
 Real Vector2r_get_item(const Vector2r & self, int idx){ IDX_CHECK(idx,2); return self[idx]; }
 int  Vector2i_get_item(const Vector2i & self, int idx){ IDX_CHECK(idx,2); return self[idx]; }
-Real Vector6r_get_item(const Vector6r & self, int idx){ IDX_CHECK(idx,6); return self[idx]; }
-int  Vector6i_get_item(const Vector6i & self, int idx){ IDX_CHECK(idx,6); return self[idx]; }
 
 Real Quaternionr_get_item(const Quaternionr & self, int idx){ IDX_CHECK(idx,4); if(idx==0) return self.x(); if(idx==1) return self.y(); if(idx==2) return self.z(); return self.w(); }
 Real Matrix3r_get_item(Matrix3r & self, bp::tuple _idx){ int idx[2]; int mx[2]={3,3}; IDX2_CHECKED_TUPLE_INTS(_idx,mx,idx); return self(idx[0],idx[1]); }
 Real Matrix3r_get_item_linear(Matrix3r & self, int idx){ IDX_CHECK(idx,9); return self(idx/3,idx%3); }
 
+std::string Vector6r_str(const Vector6r & self){ return std::string("Vector6(")+boost::lexical_cast<std::string>(self[0])+","+boost::lexical_cast<std::string>(self[1])+","+boost::lexical_cast<std::string>(self[2])+", "+boost::lexical_cast<std::string>(self[3])+","+boost::lexical_cast<std::string>(self[4])+","+boost::lexical_cast<std::string>(self[5])+")";}
+std::string Vector6i_str(const Vector6i & self){ return std::string("Vector6i(")+boost::lexical_cast<std::string>(self[0])+","+boost::lexical_cast<std::string>(self[1])+","+boost::lexical_cast<std::string>(self[2])+", "+boost::lexical_cast<std::string>(self[3])+","+boost::lexical_cast<std::string>(self[4])+","+boost::lexical_cast<std::string>(self[5])+")";}
 std::string Vector3r_str(const Vector3r & self){ return std::string("Vector3(")+boost::lexical_cast<std::string>(self[0])+","+boost::lexical_cast<std::string>(self[1])+","+boost::lexical_cast<std::string>(self[2])+")";}
 std::string Vector3i_str(const Vector3i & self){ return std::string("Vector3i(")+boost::lexical_cast<std::string>(self[0])+","+boost::lexical_cast<std::string>(self[1])+","+boost::lexical_cast<std::string>(self[2])+")";}
 std::string Vector2r_str(const Vector2r & self){ return std::string("Vector2(")+boost::lexical_cast<std::string>(self[0])+","+boost::lexical_cast<std::string>(self[1])+")";}
 std::string Vector2i_str(const Vector2i & self){ return std::string("Vector2i(")+boost::lexical_cast<std::string>(self[0])+","+boost::lexical_cast<std::string>(self[1])+")";}
-std::string Vector6r_str(const Vector6r & self){ return std::string("Vector6(")+boost::lexical_cast<std::string>(self[0])+","+boost::lexical_cast<std::string>(self[1])+","+boost::lexical_cast<std::string>(self[2])+","+boost::lexical_cast<std::string>(self[3])+","+boost::lexical_cast<std::string>(self[4])+","+boost::lexical_cast<std::string>(self[5])+")";}
-std::string Vector6i_str(const Vector6i & self){ return std::string("Vector6i(")+boost::lexical_cast<std::string>(self[0])+","+boost::lexical_cast<std::string>(self[1])+","+boost::lexical_cast<std::string>(self[2])+","+boost::lexical_cast<std::string>(self[3])+","+boost::lexical_cast<std::string>(self[4])+","+boost::lexical_cast<std::string>(self[5])+")";}
 std::string Quaternionr_str(const Quaternionr & self){ AngleAxisr aa(self); return std::string("Quaternion((")+boost::lexical_cast<std::string>(aa.axis()[0])+","+boost::lexical_cast<std::string>(aa.axis()[1])+","+boost::lexical_cast<std::string>(aa.axis()[2])+"),"+boost::lexical_cast<std::string>(aa.angle())+")";}
 std::string Matrix3r_str(const Matrix3r & self){ std::ostringstream oss; oss<<"Matrix3("; for(int i=0; i<3; i++) for(int j=0; j<3; j++) oss<<self(i,j)<<((i==2 && j==2)?")":",")<<((i<2 && j==2)?" ":""); return oss.str(); }
 
+int Vector6r_len(){return 6;}
+int Vector6i_len(){return 6;}
 int Vector3r_len(){return 3;}
 int Vector3i_len(){return 3;}
 int Vector2r_len(){return 2;}
 int Vector2i_len(){return 2;}
-int Vector6r_len(){return 6;}
-int Vector6i_len(){return 6;}
 int Quaternionr_len(){return 4;}
 int Matrix3r_len(){return 9;}
 
 // pickling support
 struct Matrix3r_pickle: bp::pickle_suite{static bp::tuple getinitargs(const Matrix3r& x){ return bp::make_tuple(x(0,0),x(0,1),x(0,2),x(1,0),x(1,1),x(1,2),x(2,0),x(2,1),x(2,2));} };
 struct Quaternionr_pickle: bp::pickle_suite{static bp::tuple getinitargs(const Quaternionr& x){ return bp::make_tuple(x.w(),x.x(),x.y(),x.z());} };
+struct Vector6r_pickle: bp::pickle_suite{static bp::tuple getinitargs(const Vector6r& x){ return bp::make_tuple(x[0],x[1],x[2],x[3],x[4],x[5]);} };
+struct Vector6i_pickle: bp::pickle_suite{static bp::tuple getinitargs(const Vector6i& x){ return bp::make_tuple(x[0],x[1],x[2],x[3],x[4],x[5]);} };
 struct Vector3r_pickle: bp::pickle_suite{static bp::tuple getinitargs(const Vector3r& x){ return bp::make_tuple(x[0],x[1],x[2]);} };
 struct Vector3i_pickle: bp::pickle_suite{static bp::tuple getinitargs(const Vector3i& x){ return bp::make_tuple(x[0],x[1],x[2]);} };
 struct Vector2r_pickle: bp::pickle_suite{static bp::tuple getinitargs(const Vector2r& x){ return bp::make_tuple(x[0],x[1]);} };
 struct Vector2i_pickle: bp::pickle_suite{static bp::tuple getinitargs(const Vector2i& x){ return bp::make_tuple(x[0],x[1]);} };
-struct Vector6r_pickle: bp::pickle_suite{static bp::tuple getinitargs(const Vector6r& x){ return bp::make_tuple(x[0],x[1],x[2],x[3],x[4],x[5]);} };
-struct Vector6i_pickle: bp::pickle_suite{static bp::tuple getinitargs(const Vector6i& x){ return bp::make_tuple(x[0],x[1],x[2],x[3],x[4],x[5]);} };
 
 #undef IDX_CHECK
 
-// automagic converters from sequence (list, tuple, …) to Vector{2,3,6}{r,i}
-struct custom_Vector3r_from_sequence{
-	custom_Vector3r_from_sequence(){	bp::converter::registry::push_back(&convertible,&construct,bp::type_id<Vector3r>()); }
-	static void* convertible(PyObject* obj_ptr){ if(!PySequence_Check(obj_ptr) || PySequence_Size(obj_ptr)!=3) return 0;	return obj_ptr; }
-	static void construct(PyObject* obj_ptr, bp::converter::rvalue_from_python_stage1_data* data){
-		void* storage=((bp::converter::rvalue_from_python_storage<Vector3r>*)(data))->storage.bytes;
-		new (storage) Vector3r(bp::extract<Real>(PySequence_GetItem(obj_ptr,0)),bp::extract<Real>(PySequence_GetItem(obj_ptr,1)),bp::extract<Real>(PySequence_GetItem(obj_ptr,2)));
-		data->convertible=storage;
-	}
-};
-struct custom_Vector3i_from_sequence{
-	custom_Vector3i_from_sequence(){	bp::converter::registry::push_back(&convertible,&construct,bp::type_id<Vector3i>()); }
-	static void* convertible(PyObject* obj_ptr){ if(!PySequence_Check(obj_ptr) || PySequence_Size(obj_ptr)!=3) return 0;	return obj_ptr; }
-	static void construct(PyObject* obj_ptr, bp::converter::rvalue_from_python_stage1_data* data){
-		void* storage=((bp::converter::rvalue_from_python_storage<Vector3i>*)(data))->storage.bytes;
-		new (storage) Vector3i(bp::extract<int>(PySequence_GetItem(obj_ptr,0)),bp::extract<int>(PySequence_GetItem(obj_ptr,1)),bp::extract<int>(PySequence_GetItem(obj_ptr,2)));
-		data->convertible=storage;
-	}
-};
-struct custom_Vector2r_from_sequence{
-	custom_Vector2r_from_sequence(){	bp::converter::registry::push_back(&convertible,&construct,bp::type_id<Vector2r>()); }
-	static void* convertible(PyObject* obj_ptr){ if(!PySequence_Check(obj_ptr) || PySequence_Size(obj_ptr)!=2) return 0;	return obj_ptr; }
-	static void construct(PyObject* obj_ptr, bp::converter::rvalue_from_python_stage1_data* data){
-		void* storage=((bp::converter::rvalue_from_python_storage<Vector2r>*)(data))->storage.bytes;
-		new (storage) Vector2r(bp::extract<Real>(PySequence_GetItem(obj_ptr,0)),bp::extract<Real>(PySequence_GetItem(obj_ptr,1)));
-		data->convertible=storage;
-	}
-};
-struct custom_Vector2i_from_sequence{
-	custom_Vector2i_from_sequence(){	bp::converter::registry::push_back(&convertible,&construct,bp::type_id<Vector2i>()); }
-	static void* convertible(PyObject* obj_ptr){ if(!PySequence_Check(obj_ptr) || PySequence_Size(obj_ptr)!=2) return 0;	return obj_ptr; }
-	static void construct(PyObject* obj_ptr, bp::converter::rvalue_from_python_stage1_data* data){
-		void* storage=((bp::converter::rvalue_from_python_storage<Vector2i>*)(data))->storage.bytes;
-		new (storage) Vector2i(bp::extract<int>(PySequence_GetItem(obj_ptr,0)),bp::extract<int>(PySequence_GetItem(obj_ptr,1)));
-		data->convertible=storage;
-	}
-};
-
-struct custom_Vector6r_from_sequence{
-	custom_Vector6r_from_sequence(){	bp::converter::registry::push_back(&convertible,&construct,bp::type_id<Vector6r>()); }
-	static void* convertible(PyObject* obj_ptr){ if(!PySequence_Check(obj_ptr) || PySequence_Size(obj_ptr)!=6) return 0;	return obj_ptr; }
-	static void construct(PyObject* obj_ptr, bp::converter::rvalue_from_python_stage1_data* data){
-		void* storage=((bp::converter::rvalue_from_python_storage<Vector6r>*)(data))->storage.bytes;
-		new (storage) Vector6r(bp::extract<Real>(PySequence_GetItem(obj_ptr,0)),bp::extract<Real>(PySequence_GetItem(obj_ptr,1)),bp::extract<Real>(PySequence_GetItem(obj_ptr,2)),bp::extract<Real>(PySequence_GetItem(obj_ptr,3)),bp::extract<Real>(PySequence_GetItem(obj_ptr,4)),bp::extract<Real>(PySequence_GetItem(obj_ptr,5)));
-		data->convertible=storage;
-	}
-};
-struct custom_Vector6i_from_sequence{
-	custom_Vector6i_from_sequence(){	bp::converter::registry::push_back(&convertible,&construct,bp::type_id<Vector6i>()); }
-	static void* convertible(PyObject* obj_ptr){ if(!PySequence_Check(obj_ptr) || PySequence_Size(obj_ptr)!=6) return 0;	return obj_ptr; }
-	static void construct(PyObject* obj_ptr, bp::converter::rvalue_from_python_stage1_data* data){
-		void* storage=((bp::converter::rvalue_from_python_storage<Vector6i>*)(data))->storage.bytes;
-		new (storage) Vector6i(bp::extract<int>(PySequence_GetItem(obj_ptr,0)),bp::extract<int>(PySequence_GetItem(obj_ptr,1)),bp::extract<int>(PySequence_GetItem(obj_ptr,2)),bp::extract<int>(PySequence_GetItem(obj_ptr,3)),bp::extract<int>(PySequence_GetItem(obj_ptr,4)),bp::extract<int>(PySequence_GetItem(obj_ptr,5)));
+/* template to define custom converter from sequence/list or approriate length and type, to eigen's Vector
+   - length is stored in VT::RowsAtCompileTime
+	- type is VT::Scalar
+*/
+template<class VT>
+struct custom_VectorAnyAny_from_sequence{
+	custom_VectorAnyAny_from_sequence(){ bp::converter::registry::push_back(&convertible,&construct,bp::type_id<VT>()); }
+	static void* convertible(PyObject* obj_ptr){ if(!PySequence_Check(obj_ptr) || PySequence_Size(obj_ptr)!=VT::RowsAtCompileTime) return 0; return obj_ptr; }
+	static void construct(PyObject* obj_ptr, bp::converter::rvalue_from_python_stage1_data* data){
+		void* storage=((bp::converter::rvalue_from_python_storage<VT>*)(data))->storage.bytes;
+		new (storage) VT;
+		for(size_t i=0; i<VT::RowsAtCompileTime; i++) (*((VT*)storage))[i]=bp::extract<typename VT::Scalar>(PySequence_GetItem(obj_ptr,i));
 		data->convertible=storage;
 	}
 };
 
 static Matrix3r* Matrix3r_fromElements(Real m00, Real m01, Real m02, Real m10, Real m11, Real m12, Real m20, Real m21, Real m22){ Matrix3r* m(new Matrix3r); (*m)<<m00,m01,m02,m10,m11,m12,m20,m21,m22; return m; }
+static Vector6r* Vector6r_fromElements(Real v0, Real v1, Real v2, Real v3, Real v4, Real v5){ Vector6r* v(new Vector6r); (*v)<<v0,v1,v2,v3,v4,v5; return v; }
+static Vector6i* Vector6i_fromElements(int v0, int v1, int v2, int v3, int v4, int v5){ Vector6i* v(new Vector6i); (*v)<<v0,v1,v2,v3,v4,v5; return v; }
 static Vector3r Matrix3r_diagonal(const Matrix3r& m){ return Vector3r(m.diagonal()); }
+static Vector6r Matrix3r_toVoigt(const Matrix3r& m, bool strain=false){ return tensor_toVoigt(m,strain); }
+static Matrix3r Vector6r_toSymmTensor(const Vector6r& v, bool strain=false){ return voigt_toSymmTensor(v,strain); }
 static Quaternionr Quaternionr_setFromTwoVectors(Quaternionr& q, const Vector3r& u, const Vector3r& v){ return q.setFromTwoVectors(u,v); }
 static Vector3r Quaternionr_Rotate(Quaternionr& q, const Vector3r& u){ return q*u; }
 // supposed to return raw pointer (or auto_ptr), boost::python takes care of the lifetime management
@@ -141,11 +104,6 @@
 static Real Vector2i_dot(const Vector2i& self, const Vector2i& v){ return self.dot(v); }
 static Vector3r Vector3r_cross(const Vector3r& self, const Vector3r& v){ return self.cross(v); }
 static Vector3i Vector3i_cross(const Vector3i& self, const Vector3i& v){ return self.cross(v); }
-static Real Vector6r_dot(const Vector6r& self, const Vector6r& v){ return self.dot(v); }
-static Real Vector6i_dot(const Vector6i& self, const Vector6i& v){ return self.dot(v); }
-static Real Vector6r_maxabs(Vector6r& self){ return self.maxabs(); }
-static Vector6r Vector6r_fromMatrix(Vector6r& self,const Matrix3r& m, const bool strain=false){ return self.fromMatrix(m,strain); }
-static Matrix3r Vector6r_toMatrix(Vector6r& self,const bool strain=false){ return self.toMatrix(strain); }
 static bool Quaternionr__eq__(const Quaternionr& q1, const Quaternionr& q2){ return q1==q2; }
 static bool Quaternionr__neq__(const Quaternionr& q1, const Quaternionr& q2){ return q1!=q2; }
 #include<Eigen/SVD>
@@ -159,12 +117,12 @@
 
 EIG_WRAP_METH0(Matrix3r,Zero);
 EIG_WRAP_METH0(Matrix3r,Identity);
+EIG_WRAP_METH0(Vector6r,Zero); EIG_WRAP_METH0(Vector6r,Ones);
+EIG_WRAP_METH0(Vector6i,Zero); EIG_WRAP_METH0(Vector6i,Ones);
 EIG_WRAP_METH0(Vector3r,Zero); EIG_WRAP_METH0(Vector3r,UnitX); EIG_WRAP_METH0(Vector3r,UnitY); EIG_WRAP_METH0(Vector3r,UnitZ); EIG_WRAP_METH0(Vector3r,Ones);
 EIG_WRAP_METH0(Vector3i,Zero); EIG_WRAP_METH0(Vector3i,UnitX); EIG_WRAP_METH0(Vector3i,UnitY); EIG_WRAP_METH0(Vector3i,UnitZ); EIG_WRAP_METH0(Vector3i,Ones);
 EIG_WRAP_METH0(Vector2r,Zero); EIG_WRAP_METH0(Vector2r,UnitX); EIG_WRAP_METH0(Vector2r,UnitY); EIG_WRAP_METH0(Vector2r,Ones);
 EIG_WRAP_METH0(Vector2i,Zero); EIG_WRAP_METH0(Vector2i,UnitX); EIG_WRAP_METH0(Vector2i,UnitY); EIG_WRAP_METH0(Vector2i,Ones);
-EIG_WRAP_METH0(Vector6r,Zero); EIG_WRAP_METH0(Vector6r,Ones);
-EIG_WRAP_METH0(Vector6i,Zero); EIG_WRAP_METH0(Vector6i,Ones);
 EIG_WRAP_METH0(Quaternionr,Identity);
 
 #define EIG_OP1(klass,op,sym) typeof((sym klass()).eval()) klass##op(const klass& self){ return (sym self).eval();}
@@ -182,6 +140,19 @@
 EIG_OP2(Matrix3r,__div__,/,Real) EIG_OP2_INPLACE(Matrix3r,__idiv__,/=,Real)
 EIG_OP2(Matrix3r,__div__,/,int) EIG_OP2_INPLACE(Matrix3r,__idiv__,/=,int)
 
+EIG_OP1(Vector6r,__neg__,-);
+EIG_OP2(Vector6r,__add__,+,Vector6r); EIG_OP2_INPLACE(Vector6r,__iadd__,+=,Vector6r)
+EIG_OP2(Vector6r,__sub__,-,Vector6r); EIG_OP2_INPLACE(Vector6r,__isub__,-=,Vector6r)
+EIG_OP2(Vector6r,__mul__,*,Real) EIG_OP2(Vector6r,__rmul__,*,Real) EIG_OP2_INPLACE(Vector6r,__imul__,*=,Real) EIG_OP2(Vector6r,__div__,/,Real) EIG_OP2_INPLACE(Vector6r,__idiv__,/=,Real)
+EIG_OP2(
+Vector6r,__mul__,*,int) EIG_OP2(Vector6r,__rmul__,*,int) EIG_OP2_INPLACE(Vector6r,__imul__,*=,int) EIG_OP2(Vector6r,__div__,/,int) EIG_OP2_INPLACE(Vector6r,__idiv__,/=,int)
+
+EIG_OP1(Vector6i,__neg__,-);
+EIG_OP2(Vector6i,__add__,+,Vector6i); EIG_OP2_INPLACE(Vector6i,__iadd__,+=,Vector6i)
+EIG_OP2(Vector6i,__sub__,-,Vector6i); EIG_OP2_INPLACE(Vector6i,__isub__,-=,Vector6i)
+EIG_OP2(
+Vector6i,__mul__,*,int) EIG_OP2(Vector6i,__rmul__,*,int) EIG_OP2_INPLACE(Vector6i,__imul__,*=,int) EIG_OP2(Vector6i,__div__,/,int) EIG_OP2_INPLACE(Vector6i,__idiv__,/=,int)
+
 EIG_OP1(Vector3r,__neg__,-);
 EIG_OP2(Vector3r,__add__,+,Vector3r); EIG_OP2_INPLACE(Vector3r,__iadd__,+=,Vector3r)
 EIG_OP2(Vector3r,__sub__,-,Vector3r); EIG_OP2_INPLACE(Vector3r,__isub__,-=,Vector3r)
@@ -205,28 +176,19 @@
 EIG_OP2(Vector2i,__sub__,-,Vector2i); EIG_OP2_INPLACE(Vector2i,__isub__,-=,Vector2i)
 EIG_OP2(Vector2i,__mul__,*,int)  EIG_OP2_INPLACE(Vector2i,__imul__,*=,int) EIG_OP2(Vector2i,__rmul__,*,int)
 
-EIG_OP1(Vector6r,__neg__,-);
-EIG_OP2(Vector6r,__add__,+,Vector6r); EIG_OP2_INPLACE(Vector6r,__iadd__,+=,Vector6r)
-EIG_OP2(Vector6r,__sub__,-,Vector6r); EIG_OP2_INPLACE(Vector6r,__isub__,-=,Vector6r)
-EIG_OP2(Vector6r,__mul__,*,Real) EIG_OP2(Vector6r,__rmul__,*,Real) EIG_OP2_INPLACE(Vector6r,__imul__,*=,Real) EIG_OP2(Vector6r,__div__,/,Real) EIG_OP2_INPLACE(Vector6r,__idiv__,/=,Real)
-EIG_OP2(Vector6r,__mul__,*,int) EIG_OP2(Vector6r,__rmul__,*,int) EIG_OP2_INPLACE(Vector6r,__imul__,*=,int) EIG_OP2(Vector6r,__div__,/,int) EIG_OP2_INPLACE(Vector6r,__idiv__,/=,int)
-
-EIG_OP1(Vector6i,__neg__,-);
-EIG_OP2(Vector6i,__add__,+,Vector6i); EIG_OP2_INPLACE(Vector6i,__iadd__,+=,Vector6i)
-EIG_OP2(Vector6i,__sub__,-,Vector6i); EIG_OP2_INPLACE(Vector6i,__isub__,-=,Vector6i)
-EIG_OP2(Vector6i,__mul__,*,int)  EIG_OP2_INPLACE(Vector6i,__imul__,*=,int) EIG_OP2(Vector6i,__rmul__,*,int)
 
 BOOST_PYTHON_MODULE(miniEigen){
 	bp::scope().attr("__doc__")="Basic math functions for Yade: small matrix, vector and quaternion classes. This module internally wraps small parts of the `Eigen <http://eigen.tuxfamily.org>`_ library. Refer to its documentation for details. All classes in this module support pickling.";
 
 	YADE_SET_DOCSTRING_OPTS;
 
-	custom_Vector3r_from_sequence();
-	custom_Vector3i_from_sequence();
-	custom_Vector2r_from_sequence();
-	custom_Vector2i_from_sequence();
-	custom_Vector6r_from_sequence();
-	custom_Vector6i_from_sequence();
+
+	custom_VectorAnyAny_from_sequence<Vector6r>();
+	custom_VectorAnyAny_from_sequence<Vector6i>();
+	custom_VectorAnyAny_from_sequence<Vector3r>();
+	custom_VectorAnyAny_from_sequence<Vector3i>();
+	custom_VectorAnyAny_from_sequence<Vector2r>();
+	custom_VectorAnyAny_from_sequence<Vector2i>();
 
 	bp::class_<Matrix3r>("Matrix3","3x3 float matrix.\n\nSupported operations (``m`` is a Matrix3, ``f`` if a float/int, ``v`` is a Vector3): ``-m``, ``m+m``, ``m+=m``, ``m-m``, ``m-=m``, ``m*f``, ``f*m``, ``m*=f``, ``m/f``, ``m/=f``, ``m*m``, ``m*=m``, ``m*v``, ``v*m``, ``m==m``, ``m!=m``.",bp::init<>())
 		.def(bp::init<Matrix3r const &>((bp::arg("m"))))
@@ -258,6 +220,8 @@
 		.def("__setitem__",&::Matrix3r_set_item_linear).def("__getitem__",&::Matrix3r_get_item_linear)
 		.add_static_property("Identity",&Matrix3r_Identity)
 		.add_static_property("Zero",&Matrix3r_Zero)
+		// specials
+		.def("toVoigt",&Matrix3r_toVoigt,(bp::arg("strain")=false),"Convert 2nd order tensor to 6-vector (Voigt notation), symmetrizing the tensor;	if *strain* is ``True``, multiply non-diagonal compoennts by 2.")
 		
 	;
 	bp::class_<Quaternionr>("Quaternion","Quaternion representing rotation.\n\nSupported operations (``q`` is a Quaternion, ``v`` is a Vector3): ``q*q`` (rotation composition), ``q*=q``, ``q*v`` (rotating ``v`` by ``q``), ``q==q``, ``q!=q``.",bp::init<>())
@@ -288,7 +252,57 @@
 		.def("__setitem__",&Quaternionr_set_item).def("__getitem__",&Quaternionr_get_item)
 		.def("__str__",&Quaternionr_str).def("__repr__",&Quaternionr_str)
 	;
-	bp::class_<Vector3r>("Vector3","3-dimensional float vector.\n\nSupported operatrions (``f`` if a float/int, ``v`` is a Vector3): ``-v``, ``v+v``, ``v+=v``, ``v-v``, ``v-=v``, ``v*f``, ``f*v``, ``v*=f``, ``v/f``, ``v/=f``, ``v==v``, ``v!=v``, plus operations with ``Matrix3`` and ``Quaternion``.\n\nImplicit conversion from sequence (list,tuple, …) of 3 floats.",bp::init<>())
+	bp::class_<Vector6r>("Vector6","6-dimensional float vector.\n\nSupported operations (``f`` if a float/int, ``v`` is a Vector6): ``-v``, ``v+v``, ``v+=v``, ``v-v``, ``v-=v``, ``v*f``, ``f*v``, ``v*=f``, ``v/f``, ``v/=f``, ``v==v``, ``v!=v``.\n\nImplicit conversion from sequence (list,tuple, …) of 6 floats.",bp::init<>())
+		.def(bp::init<Vector6r>((bp::arg("other"))))
+		.def("__init__",bp::make_constructor(&Vector6r_fromElements,bp::default_call_policies(),(bp::arg("v0"),bp::arg("v1"),bp::arg("v2"),bp::arg("v3"),bp::arg("v4"),bp::arg("v5"))))
+		.def_pickle(Vector6r_pickle())
+		// properties
+		.add_static_property("Ones",&Vector6r_Ones).add_static_property("Zero",&Vector6r_Zero)
+		//.add_static_property("UnitX",&Vector6r_UnitX).add_static_property("UnitY",&Vector6r_UnitY).add_static_property("UnitZ",&Vector6r_UnitZ)
+		// methods
+		//.def("dot",&Vector6r_dot).def("cross",&Vector6r_cross)
+		.def("norm",&Vector6r::norm).def("squaredNorm",&Vector6r::squaredNorm).def("normalize",&Vector6r::normalize).def("normalized",&Vector6r::normalized)
+		// operators
+		.def("__neg__",&Vector6r__neg__) // -v
+		.def("__add__",&Vector6r__add__Vector6r).def("__iadd__",&Vector6r__iadd__Vector6r) // +, +=
+		.def("__sub__",&Vector6r__sub__Vector6r).def("__isub__",&Vector6r__isub__Vector6r) // -, -=
+		.def("__mul__",&Vector6r__mul__Real).def("__rmul__",&Vector6r__rmul__Real) // f*v, v*f
+		.def("__div__",&Vector6r__div__Real).def("__idiv__",&Vector6r__idiv__Real) // v/f, v/=f
+		.def("__mul__",&Vector6r__mul__int).def("__rmul__",&Vector6r__rmul__int) // f*v, v*f
+		.def("__div__",&Vector6r__div__int).def("__idiv__",&Vector6r__idiv__int) // v/f, v/=f
+		.def(bp::self != bp::self).def(bp::self == bp::self)
+		// specials
+		.def("__len__",&::Vector6r_len).staticmethod("__len__")
+		.def("__setitem__",&::Vector6r_set_item).def("__getitem__",&::Vector6r_get_item)
+		.def("__str__",&::Vector6r_str).def("__repr__",&::Vector6r_str)
+		// specials
+		.def("toSymmTensor",&Vector6r_toSymmTensor,(bp::args("strain")=false),"Convert Vector6 in the Voigt notation to the corresponding 2nd order symmetric tensor (as Matrix3); if *strain* is ``True``, multiply non-diagonal components by .5")
+	;
+
+	bp::class_<Vector6i>("Vector6i","6-dimensional float vector.\n\nSupported operations (``f`` if a float/int, ``v`` is a Vector6): ``-v``, ``v+v``, ``v+=v``, ``v-v``, ``v-=v``, ``v*f``, ``f*v``, ``v*=f``, ``v/f``, ``v/=f``, ``v==v``, ``v!=v``.\n\nImplicit conversion from sequence (list,tuple, …) of 6 floats.",bp::init<>())
+		.def(bp::init<Vector6i>((bp::arg("other"))))
+		.def("__init__",bp::make_constructor(&Vector6i_fromElements,bp::default_call_policies(),(bp::arg("v0"),bp::arg("v1"),bp::arg("v2"),bp::arg("v3"),bp::arg("v4"),bp::arg("v5"))))
+		.def_pickle(Vector6i_pickle())
+		// properties
+		.add_static_property("Ones",&Vector6i_Ones).add_static_property("Zero",&Vector6i_Zero)
+		//.add_static_property("UnitX",&Vector6i_UnitX).add_static_property("UnitY",&Vector6i_UnitY).add_static_property("UnitZ",&Vector6i_UnitZ)
+		// methods
+		//.def("dot",&Vector6i_dot).def("cross",&Vector6i_cross)
+		.def("norm",&Vector6i::norm).def("squaredNorm",&Vector6i::squaredNorm).def("normalize",&Vector6i::normalize).def("normalized",&Vector6i::normalized)
+		// operators
+		.def("__neg__",&Vector6i__neg__) // -v
+		.def("__add__",&Vector6i__add__Vector6i).def("__iadd__",&Vector6i__iadd__Vector6i) // +, +=
+		.def("__sub__",&Vector6i__sub__Vector6i).def("__isub__",&Vector6i__isub__Vector6i) // -, -=
+		.def("__mul__",&Vector6i__mul__int).def("__rmul__",&Vector6i__rmul__int) // f*v, v*f
+		.def("__div__",&Vector6i__div__int).def("__idiv__",&Vector6i__idiv__int) // v/f, v/=f
+		.def(bp::self != bp::self).def(bp::self == bp::self)
+		// specials
+		.def("__len__",&::Vector6i_len).staticmethod("__len__")
+		.def("__setitem__",&::Vector6i_set_item).def("__getitem__",&::Vector6i_get_item)
+		.def("__str__",&::Vector6i_str).def("__repr__",&::Vector6i_str)
+	;
+
+	bp::class_<Vector3r>("Vector3","3-dimensional float vector.\n\nSupported operations (``f`` if a float/int, ``v`` is a Vector3): ``-v``, ``v+v``, ``v+=v``, ``v-v``, ``v-=v``, ``v*f``, ``f*v``, ``v*=f``, ``v/f``, ``v/=f``, ``v==v``, ``v!=v``, plus operations with ``Matrix3`` and ``Quaternion``.\n\nImplicit conversion from sequence (list,tuple, …) of 3 floats.",bp::init<>())
 		.def(bp::init<Vector3r>((bp::arg("other"))))
 		.def(bp::init<Real,Real,Real>((bp::arg("x"),bp::arg("y"),bp::arg("z"))))
 		.def_pickle(Vector3r_pickle())
@@ -312,7 +326,7 @@
 		.def("__setitem__",&::Vector3r_set_item).def("__getitem__",&::Vector3r_get_item)
 		.def("__str__",&::Vector3r_str).def("__repr__",&::Vector3r_str)
 	;	
-	bp::class_<Vector3i>("Vector3i","3-dimensional integer vector.\n\nSupported operatrions (``i`` if an int, ``v`` is a Vector3i): ``-v``, ``v+v``, ``v+=v``, ``v-v``, ``v-=v``, ``v*i``, ``i*v``, ``v*=i``, ``v==v``, ``v!=v``.\n\nImplicit conversion from sequence  (list,tuple, …) of 3 integers.",bp::init<>())
+	bp::class_<Vector3i>("Vector3i","3-dimensional integer vector.\n\nSupported operations (``i`` if an int, ``v`` is a Vector3i): ``-v``, ``v+v``, ``v+=v``, ``v-v``, ``v-=v``, ``v*i``, ``i*v``, ``v*=i``, ``v==v``, ``v!=v``.\n\nImplicit conversion from sequence  (list,tuple, …) of 3 integers.",bp::init<>())
 		.def(bp::init<Vector3i>((bp::arg("other"))))
 		.def(bp::init<int,int,int>((bp::arg("x"),bp::arg("y"),bp::arg("z"))))
 		.def_pickle(Vector3i_pickle())
@@ -333,7 +347,7 @@
 		.def("__setitem__",&::Vector3i_set_item).def("__getitem__",&::Vector3i_get_item)
 		.def("__str__",&::Vector3i_str).def("__repr__",&::Vector3i_str)
 	;	
-	bp::class_<Vector2r>("Vector2","3-dimensional float vector.\n\nSupported operatrions (``f`` if a float/int, ``v`` is a Vector3): ``-v``, ``v+v``, ``v+=v``, ``v-v``, ``v-=v``, ``v*f``, ``f*v``, ``v*=f``, ``v/f``, ``v/=f``, ``v==v``, ``v!=v``.\n\nImplicit conversion from sequence (list,tuple, …) of 2 floats.",bp::init<>())
+	bp::class_<Vector2r>("Vector2","3-dimensional float vector.\n\nSupported operations (``f`` if a float/int, ``v`` is a Vector3): ``-v``, ``v+v``, ``v+=v``, ``v-v``, ``v-=v``, ``v*f``, ``f*v``, ``v*=f``, ``v/f``, ``v/=f``, ``v==v``, ``v!=v``.\n\nImplicit conversion from sequence (list,tuple, …) of 2 floats.",bp::init<>())
 		.def(bp::init<Vector2r>((bp::arg("other"))))
 		.def(bp::init<Real,Real>((bp::arg("x"),bp::arg("y"))))
 		.def_pickle(Vector2r_pickle())
@@ -357,7 +371,7 @@
 		.def("__setitem__",&::Vector2r_set_item).def("__getitem__",&::Vector2r_get_item)
 		.def("__str__",&::Vector2r_str).def("__repr__",&::Vector2r_str)
 	;	
-	bp::class_<Vector2i>("Vector2i","2-dimensional integer vector.\n\nSupported operatrions (``i`` if an int, ``v`` is a Vector2i): ``-v``, ``v+v``, ``v+=v``, ``v-v``, ``v-=v``, ``v*i``, ``i*v``, ``v*=i``, ``v==v``, ``v!=v``.\n\nImplicit conversion from sequence (list,tuple, …) of 2 integers.",bp::init<>())
+	bp::class_<Vector2i>("Vector2i","2-dimensional integer vector.\n\nSupported operations (``i`` if an int, ``v`` is a Vector2i): ``-v``, ``v+v``, ``v+=v``, ``v-v``, ``v-=v``, ``v*i``, ``i*v``, ``v*=i``, ``v==v``, ``v!=v``.\n\nImplicit conversion from sequence (list,tuple, …) of 2 integers.",bp::init<>())
 		.def(bp::init<Vector2i>((bp::arg("other"))))
 		.def(bp::init<int,int>((bp::arg("x"),bp::arg("y"))))
 		.def_pickle(Vector2i_pickle())
@@ -378,51 +392,7 @@
 		.def("__setitem__",&::Vector2i_set_item).def("__getitem__",&::Vector2i_get_item)
 		.def("__str__",&::Vector2i_str).def("__repr__",&::Vector2i_str)
 	;	
-	bp::class_<Vector6r>("Vector6","6-dimensional float vector.\n\nSupported operatrions (``f`` if a float/int, ``v`` is a Vector6): ``-v``, ``v+v``, ``v+=v``, ``v-v``, ``v-=v``, ``v*f``, ``f*v``, ``v*=f``, ``v/f``, ``v/=f``, ``v==v``, ``v!=v``, plus operations with ``Matrix3``.\n\nImplicit conversion from sequence (list,tuple, …) of 6 floats.",bp::init<>())
-		.def(bp::init<Vector6r>((bp::arg("other"))))
-		.def(bp::init<Real,Real,Real,Real,Real,Real>((bp::arg("v0"),bp::arg("v1"),bp::arg("v2"),bp::arg("v3"),bp::arg("v4"),bp::arg("v5"))))
-		.def_pickle(Vector6r_pickle())
-		// properties
-		.add_static_property("Ones",&Vector6r_Ones).add_static_property("Zero",&Vector6r_Zero)
-		// methods
-		.def("dot",&Vector6r_dot)
-		//.def("setFromTwoVectors",&Quaternionr_setFromTwoVectors,((bp::arg("u"),bp::arg("v"))))
-		.def("maxabs",&Vector6r_maxabs)
-		.def("toMatrix",&Vector6r_toMatrix,((bp::arg("strain")=false)),"conversion from \"engineering\" (Vector6(xx,yy,zz,yz,zx,xy)) to \"tensorial\" (Matrix3(xx,xy,xz, yx,yy,yz, zx,zy,zz)) quantities (stress and strain)")
-		.def("fromMatrix",&Vector6r_fromMatrix,((bp::arg("strain")=false)),"conversion from \"tensorial\" (Matrix3(xx,xy,xz, yx,yy,yz, zx,zy,zz)) to  \"engineering\" (Vector6(xx,yy,zz,yz,zx,xy)) quantities (stress and strain)")
-		// operators
-		.def("__neg__",&Vector6r__neg__) // -v
-		.def("__add__",&Vector6r__add__Vector6r).def("__iadd__",&Vector6r__iadd__Vector6r) // +, +=
-		.def("__sub__",&Vector6r__sub__Vector6r).def("__isub__",&Vector6r__isub__Vector6r) // -, -=
-		.def("__mul__",&Vector6r__mul__Real).def("__rmul__",&Vector6r__rmul__Real) // f*v, v*f
-		.def("__div__",&Vector6r__div__Real).def("__idiv__",&Vector6r__idiv__Real) // v/f, v/=f
-		.def("__mul__",&Vector6r__mul__int).def("__rmul__",&Vector6r__rmul__int) // f*v, v*f
-		.def("__div__",&Vector6r__div__int).def("__idiv__",&Vector6r__idiv__int) // v/f, v/=f
-		.def(bp::self != bp::self).def(bp::self == bp::self)
-		// specials
-		.def("__len__",&::Vector6r_len).staticmethod("__len__")
-		.def("__setitem__",&::Vector6r_set_item).def("__getitem__",&::Vector6r_get_item)
-		.def("__str__",&::Vector6r_str).def("__repr__",&::Vector6r_str)
-	;	
-	bp::class_<Vector6i>("Vector6i","6-dimensional integer vector.\n\nSupported operatrions (``i`` if an int, ``v`` is a Vector6i): ``-v``, ``v+v``, ``v+=v``, ``v-v``, ``v-=v``, ``v*i``, ``i*v``, ``v*=i``, ``v==v``, ``v!=v``.\n\nImplicit conversion from sequence  (list,tuple, …) of 6 integers.",bp::init<>())
-		.def(bp::init<Vector6i>((bp::arg("other"))))
-		.def(bp::init<int,int,int,int,int,int>((bp::arg("v0"),bp::arg("v1"),bp::arg("v2"),bp::arg("v3"),bp::arg("v4"),bp::arg("v5"))))
-		.def_pickle(Vector6i_pickle())
-		// properties
-		.add_static_property("Ones",&Vector6i_Ones).add_static_property("Zero",&Vector6i_Zero)
-		// methods
-		.def("dot",&Vector6i_dot)
-		// operators
-		.def("__neg__",&Vector6i__neg__) // -v
-		.def("__add__",&Vector6i__add__Vector6i).def("__iadd__",&Vector6i__iadd__Vector6i) // +, +=
-		.def("__sub__",&Vector6i__sub__Vector6i).def("__isub__",&Vector6i__isub__Vector6i) // -, -=
-		.def("__mul__",&Vector6i__mul__int).def("__rmul__",&Vector6i__rmul__int) // f*v, v*f
-		.def(bp::self != bp::self).def(bp::self == bp::self)
-		// specials
-		.def("__len__",&::Vector6i_len).staticmethod("__len__")
-		.def("__setitem__",&::Vector6i_set_item).def("__getitem__",&::Vector6i_get_item)
-		.def("__str__",&::Vector6i_str).def("__repr__",&::Vector6i_str)
-	;
+	
 };