Newer
Older
#ifndef ORTHOGONAL_MATRIX_HH
#define ORTHOGONAL_MATRIX_HH
#include <dune/common/fmatrix.hh>
#include <dune/gfe/skewmatrix.hh>
/** \brief An orthogonal \f$ n \times n \f$ matrix
* \tparam T Type of the matrix entries
* \tparam N Space dimension
*/
template <class T, int N>
class OrthogonalMatrix
{
public:
/** \brief The type used for coordinates */
typedef T ctype;
/** \brief Dimension of the manifold formed by the orthogonal matrices */
static const int dim = N*(N-1)/2;
/** \brief Coordinates are embedded into a Euclidean space of N x N - matrices */
static const int embeddedDim = N*N;
/** \brief The type used for global coordinates */
typedef Dune::FieldVector<T,embeddedDim> CoordinateType;
/** \brief Member of the corresponding Lie algebra. This really is a skew-symmetric matrix */
typedef Dune::FieldVector<T,dim> TangentVector;
/** \brief A tangent vector as a vector in the surrounding coordinate space */
typedef Dune::FieldVector<T,embeddedDim> EmbeddedTangentVector;
/** \brief Default constructor -- leaves the matrix uninitialized */
OrthogonalMatrix()
{}
/** \brief Constructor from a general matrix
*
* It is not checked whether the matrix is really orthogonal
*/
explicit OrthogonalMatrix(const Dune::FieldMatrix<T,N,N>& matrix)
: data_(matrix)
{}
/** \brief Copy constructor
*
* It is not checked whether the matrix is really orthogonal
*/
explicit OrthogonalMatrix(const CoordinateType& other)
{
DUNE_THROW(Dune::NotImplemented, "constructor");
}
/** \brief Const access to the matrix entries */
const Dune::FieldMatrix<T,N,N>& data() const
{
return data_;
}
/** \brief Project the input matrix onto the tangent space at "this"
*
* See Absil, Mahoney, Sepulche, Example 5.3.2 for the formula
* \f[ P_X \xi = X \operatorname{skew} (X^T \xi) \f]
*
*/
Dune::FieldMatrix<T,N,N> projectOntoTangentSpace(const Dune::FieldMatrix<T,N,N>& matrix) const
{
// rename to get the same notation as Absil & Co
const Dune::FieldMatrix<T,N,N>& X = data_;
// X^T \xi
Dune::FieldMatrix<T,N,N> XTxi(0);
for (int i=0; i<N; i++)
for (int j=0; j<N; j++)
for (int k=0; k<N; k++)
XTxi[i][j] += X[k][i] * matrix[k][j];
// skew (X^T \xi)
Dune::FieldMatrix<T,N,N> skewXTxi(0);
for (int i=0; i<N; i++)
for (int j=0; j<N; j++)
skewXTxi[i][j] = 0.5 * ( XTxi[i][j] - XTxi[j][i] );
// X skew (X^T \xi)
Dune::FieldMatrix<T,N,N> result(0);
for (int i=0; i<N; i++)
for (int j=0; j<N; j++)
for (int k=0; k<N; k++)
result[i][j] += X[i][k] * skewXTxi[k][j];
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/** \brief Rebind the OrthogonalMatrix to another coordinate type */
template<class U>
struct rebind
{
typedef OrthogonalMatrix<U,N> other;
};
OrthogonalMatrix& operator= (const CoordinateType& other)
{
std::size_t idx = 0;
for (int i=0; i<N; i++)
for (int j=0; j<N; j++)
data_[i][j] = other[idx++];
return *this;
}
/** \brief The exponential map from a given point $p \in SO(n)$.
\param v A tangent vector.
*/
static OrthogonalMatrix<T,3> exp(const OrthogonalMatrix<T,N>& p, const TangentVector& v)
{
DUNE_THROW(Dune::NotImplemented, "exp");
}
/** \brief Return the actual matrix */
void matrix(Dune::FieldMatrix<T,N,N>& m) const
{
m = data_;
}
/** \brief Project tangent vector of R^n onto the normal space space */
EmbeddedTangentVector projectOntoNormalSpace(const EmbeddedTangentVector& v) const
{
DUNE_THROW(Dune::NotImplemented, "projectOntoNormalSpace");
}
/** \brief The Weingarten map */
EmbeddedTangentVector weingarten(const EmbeddedTangentVector& z, const EmbeddedTangentVector& v) const
{
EmbeddedTangentVector result;
DUNE_THROW(Dune::NotImplemented, "weingarten");
return result;
}
static OrthogonalMatrix<T,N> projectOnto(const CoordinateType& p)
{
DUNE_THROW(Dune::NotImplemented, "projectOnto");
}
// TODO return type is wrong
static Dune::FieldMatrix<T,1,1> derivativeOfProjection(const CoordinateType& p)
{
Dune::FieldMatrix<T,1,1> result;
return result;
}
/** \brief The global coordinates, if you really want them */
CoordinateType globalCoordinates() const
{
CoordinateType result;
std::size_t idx = 0;
for (int i=0; i<N; i++)
for (int j=0; j<N; j++)
result[idx++] = data_[i][j];
return result;
}
/** \brief Compute an orthonormal basis of the tangent space of SO(n). */
Dune::FieldMatrix<T,dim,embeddedDim> orthonormalFrame() const
{
Dune::FieldMatrix<T,dim,embeddedDim> result;
DUNE_THROW(Dune::NotImplemented, "orthonormalFrame");
return result;
}
private:
/** \brief The actual data */
Dune::FieldMatrix<T,N,N> data_;
};
#endif // ORTHOGONAL_MATRIX_HH