[9c5296] | 1 | /*
|
---|
| 2 | * Project: MoleCuilder
|
---|
| 3 | * Description: creates and alters molecular systems
|
---|
| 4 | * Copyright (C) 2010 University of Bonn. All rights reserved.
|
---|
| 5 | * Please see the LICENSE file or "Copyright notice" in builder.cpp for details.
|
---|
| 6 | */
|
---|
| 7 |
|
---|
| 8 | /*
|
---|
| 9 | * Subspace.cpp
|
---|
| 10 | *
|
---|
| 11 | * Created on: Nov 22, 2010
|
---|
| 12 | * Author: heber
|
---|
| 13 | */
|
---|
| 14 |
|
---|
| 15 | // include config.h
|
---|
| 16 | #ifdef HAVE_CONFIG_H
|
---|
| 17 | #include <config.h>
|
---|
| 18 | #endif
|
---|
| 19 |
|
---|
[ad011c] | 20 | #include "CodePatterns/MemDebug.hpp"
|
---|
[9c5296] | 21 |
|
---|
| 22 | #include <boost/shared_ptr.hpp>
|
---|
| 23 | #include <boost/foreach.hpp>
|
---|
| 24 |
|
---|
[ad011c] | 25 | #include "CodePatterns/Assert.hpp"
|
---|
| 26 | #include "CodePatterns/Log.hpp"
|
---|
| 27 | #include "CodePatterns/toString.hpp"
|
---|
| 28 | #include "CodePatterns/Verbose.hpp"
|
---|
[9c5296] | 29 |
|
---|
| 30 | #include "Eigenspace.hpp"
|
---|
| 31 | #include "Subspace.hpp"
|
---|
| 32 |
|
---|
[286af5f] | 33 |
|
---|
[9c5296] | 34 | /** Constructor for class Subspace.
|
---|
| 35 | *
|
---|
| 36 | * @param _s indices that make up this subspace
|
---|
| 37 | * @param _FullSpace reference to the full eigenspace
|
---|
| 38 | */
|
---|
| 39 | Subspace::Subspace(indexset & _s, Eigenspace &_FullSpace) :
|
---|
| 40 | Eigenspace(_s),
|
---|
[a06042] | 41 | ProjectToSubspace(_FullSpace.getIndices().size(), _s.size()),
|
---|
| 42 | ProjectFromSubspace(_s.size(), _FullSpace.getIndices().size()),
|
---|
[286af5f] | 43 | FullSpace(_FullSpace),
|
---|
| 44 | ZeroVector(_FullSpace.getIndices().size())
|
---|
[a06042] | 45 | {
|
---|
[286af5f] | 46 | // TODO: away with both of this when calculateEigenSubspace() works
|
---|
[a06042] | 47 | // create projection matrices
|
---|
| 48 | createProjectionMatrices();
|
---|
| 49 |
|
---|
| 50 | // create eigenspace matrices
|
---|
[e828c0] | 51 | EigenspaceMatrix = projectFullspaceMatrixToSubspace(FullSpace.getEigenspaceMatrix());
|
---|
[a06042] | 52 | }
|
---|
[9c5296] | 53 |
|
---|
| 54 |
|
---|
| 55 | /** Destructor for class Subspace.
|
---|
| 56 | *
|
---|
| 57 | */
|
---|
| 58 | Subspace::~Subspace()
|
---|
| 59 | {}
|
---|
| 60 |
|
---|
| 61 |
|
---|
| 62 | /** Diagonalizes the subspace matrix.
|
---|
| 63 | *
|
---|
| 64 | */
|
---|
| 65 | void Subspace::calculateEigenSubspace()
|
---|
| 66 | {
|
---|
[286af5f] | 67 | // project down
|
---|
| 68 | createProjectionMatrices();
|
---|
| 69 | // remove subsubspace directions
|
---|
[e828c0] | 70 | //correctProjectionMatricesFromSubIndices();
|
---|
[286af5f] | 71 | // solve
|
---|
[e828c0] | 72 | EigenspaceMatrix = projectFullspaceMatrixToSubspace(FullSpace.getEigenspaceMatrix());
|
---|
[286af5f] | 73 | EigenvectorMatrix = EigenspaceMatrix;
|
---|
| 74 | VectorContent *EigenvalueVector = new VectorContent(EigenvectorMatrix.transformToEigenbasis());
|
---|
| 75 | Eigenvalues.clear();
|
---|
| 76 | for(size_t i = 0; i< EigenvalueVector->getDimension(); ++i) {
|
---|
| 77 | Eigenvalues.push_back( EigenvalueVector->at(i) );
|
---|
| 78 | }
|
---|
| 79 | delete EigenvalueVector;
|
---|
[e828c0] | 80 |
|
---|
[286af5f] | 81 | // create mapping
|
---|
| 82 | createLocalMapping();
|
---|
[e828c0] | 83 |
|
---|
| 84 | // swap the eigenvectors/-values to their correct sequence
|
---|
| 85 | sortEigenvectors();
|
---|
| 86 |
|
---|
| 87 | // scale eigenvectors by their eigenvalues for the subsequent correction
|
---|
| 88 | scaleEigenvectorsbyEigenvalue();
|
---|
| 89 |
|
---|
| 90 | // let only remain corrections to lower orders on this order
|
---|
| 91 | correctEigenvectorsFromSubIndices();
|
---|
| 92 |
|
---|
| 93 | if (!EigenvectorMatrix.IsNull()) {
|
---|
| 94 | // get correct eigenvalues
|
---|
| 95 | getNormofEigenvectorAsEigenvalue();
|
---|
| 96 |
|
---|
| 97 | DoLog(2) && (Log() << Verbose(2) << "Eigenvector matrix is " << EigenvectorMatrix << std::endl);
|
---|
| 98 | DoLog(2) && (Log() << Verbose(2) << "Eigenvalues are " << Eigenvalues << std::endl);
|
---|
| 99 |
|
---|
| 100 | }
|
---|
[9c5296] | 101 | }
|
---|
| 102 |
|
---|
| 103 |
|
---|
| 104 | /** Projects a given full matrix down into the subspace of this class.
|
---|
| 105 | *
|
---|
| 106 | * @param bigmatrix full matrix to project into subspace
|
---|
| 107 | */
|
---|
| 108 | void Subspace::getSubspacematrixFromBigmatrix(const MatrixContent & bigmatrix)
|
---|
| 109 | {
|
---|
| 110 | // check whether subsystem is big enough for both index sets
|
---|
| 111 | ASSERT(Indices.size() <= bigmatrix.getRows(),
|
---|
| 112 | "embedEigenspaceMatrix() - bigmatrix has less rows "+toString(bigmatrix.getRows())
|
---|
| 113 | +" than needed by index set "
|
---|
| 114 | +toString(Indices.size())+"!");
|
---|
| 115 | ASSERT(Indices.size() <= bigmatrix.getColumns(),
|
---|
| 116 | "embedEigenspaceMatrix() - bigmatrix has less columns "+toString(bigmatrix.getColumns())
|
---|
| 117 | +" than needed by index set "
|
---|
| 118 | +toString(Indices.size())+"!");
|
---|
| 119 |
|
---|
| 120 | // construct small matrix
|
---|
| 121 | MatrixContent *subsystem = new MatrixContent(Indices.size(), Indices.size());
|
---|
| 122 | size_t localrow = 0; // local row indices for the subsystem
|
---|
| 123 | size_t localcolumn = 0;
|
---|
| 124 | BOOST_FOREACH( size_t rowindex, Indices) {
|
---|
| 125 | localcolumn = 0;
|
---|
| 126 | BOOST_FOREACH( size_t columnindex, Indices) {
|
---|
| 127 | ASSERT((rowindex < bigmatrix.getRows()) && (columnindex < bigmatrix.getColumns()),
|
---|
| 128 | "current index pair ("
|
---|
| 129 | +toString(rowindex)+","+toString(columnindex)
|
---|
| 130 | +") is out of bounds of bigmatrix ("
|
---|
| 131 | +toString(bigmatrix.getRows())+","+toString(bigmatrix.getColumns())
|
---|
| 132 | +")");
|
---|
| 133 | subsystem->at(localrow,localcolumn) = (*Eigenvectors[rowindex]) * (bigmatrix * (*Eigenvectors[columnindex]));
|
---|
| 134 | localcolumn++;
|
---|
| 135 | }
|
---|
| 136 | localrow++;
|
---|
| 137 | }
|
---|
| 138 | }
|
---|
| 139 |
|
---|
| 140 |
|
---|
[e828c0] | 141 | /** Sort the eigenvectors in the order of Subspace::Indices.
|
---|
| 142 | *
|
---|
| 143 | */
|
---|
| 144 | void Subspace::sortEigenvectors()
|
---|
| 145 | {
|
---|
| 146 | DoLog(1) && (Log() << Verbose(1) << "Sorting Eigenvectors ..." << std::endl);
|
---|
| 147 | MatrixContent tempMatrix = EigenvectorMatrix;
|
---|
| 148 | eigenvalueset tempValues = Eigenvalues;
|
---|
| 149 | size_t localindex = 0;
|
---|
| 150 | BOOST_FOREACH( size_t iter, Indices) {
|
---|
| 151 | Log() << Verbose(1) << GlobalToLocal[iter] << "th eigenvector is associated to "
|
---|
| 152 | << iter << " and goes to column " << localindex << "." << std::endl;
|
---|
| 153 | boost::shared_ptr<VectorContent> columnvector(tempMatrix.getColumnVector(GlobalToLocal[iter]));
|
---|
| 154 | *Eigenvectors[localindex] = *columnvector;
|
---|
| 155 | Eigenvalues[localindex] = tempValues[GlobalToLocal[iter]];
|
---|
| 156 | ++localindex;
|
---|
| 157 | }
|
---|
| 158 | }
|
---|
| 159 |
|
---|
| 160 |
|
---|
| 161 | /** We remove the projections from lower subspaces from our Eigenspacematrix.
|
---|
| 162 | * This is intended to diminish parallel changing of eigenspaces.
|
---|
| 163 | */
|
---|
[9c5296] | 164 | void Subspace::correctEigenvectorsFromSubIndices()
|
---|
| 165 | {
|
---|
[e828c0] | 166 | DoLog(1) && (Log() << Verbose(1) << "Correcting EigenvectorMatrix ... " << std::endl);
|
---|
| 167 | BOOST_FOREACH( boost::shared_ptr<Subspace> iter, SubIndices ) {
|
---|
| 168 | const MatrixContent tempMatrix =
|
---|
| 169 | projectFullspaceMatrixToSubspace(
|
---|
| 170 | iter->projectSubspaceMatrixToFullspace(iter->getEigenvectorMatrix())
|
---|
| 171 | );
|
---|
| 172 | DoLog(1) && (Log() << Verbose(1) << "Subtracting matrix from " << *iter << ":" << tempMatrix << std::endl);
|
---|
| 173 | EigenvectorMatrix -= tempMatrix;
|
---|
| 174 | }
|
---|
| 175 | DoLog(1) && (Log() << Verbose(1) << "Corrected EigenvectorMatrix is " << EigenvectorMatrix << std::endl);
|
---|
| 176 |
|
---|
| 177 | // check for null vectors
|
---|
| 178 | const size_t max = EigenvectorMatrix.getColumns();
|
---|
| 179 | for(size_t i = 0; i< max; ++i) {
|
---|
| 180 | if (Eigenvectors[i]->IsZero()) {
|
---|
| 181 | Eigenvalues[i] = 0.;
|
---|
| 182 | Eigenvectors[i]->setZero();
|
---|
| 183 | }
|
---|
| 184 | }
|
---|
| 185 | }
|
---|
| 186 |
|
---|
| 187 |
|
---|
| 188 | /** Scale the local eigenvectors each by their eigenvalue.
|
---|
| 189 | *
|
---|
| 190 | */
|
---|
| 191 | void Subspace::scaleEigenvectorsbyEigenvalue()
|
---|
| 192 | {
|
---|
| 193 | size_t localindex = 0;
|
---|
| 194 | BOOST_FOREACH( boost::shared_ptr<VectorContent> ev, Eigenvectors) {
|
---|
| 195 | *ev *= Eigenvalues[localindex];
|
---|
| 196 | ++localindex;
|
---|
| 197 | }
|
---|
| 198 | }
|
---|
| 199 |
|
---|
| 200 |
|
---|
| 201 | /** Get Norm of each eigenvector to serve als eigenvalue.
|
---|
| 202 | *
|
---|
| 203 | */
|
---|
| 204 | void Subspace::getNormofEigenvectorAsEigenvalue()
|
---|
| 205 | {
|
---|
| 206 | size_t localindex = 0;
|
---|
| 207 | BOOST_FOREACH( boost::shared_ptr<VectorContent> ev, Eigenvectors) {
|
---|
| 208 | Eigenvalues[localindex] = ev->Norm();
|
---|
| 209 | ++localindex;
|
---|
| 210 | }
|
---|
| 211 | }
|
---|
| 212 |
|
---|
| 213 |
|
---|
| 214 | /** We remove the projections from lower subspaces from our Eigenspacematrix.
|
---|
| 215 | * This is intended to diminish parallel changing of eigenspaces.
|
---|
| 216 | */
|
---|
| 217 | void Subspace::correctProjectionMatricesFromSubIndices()
|
---|
| 218 | {
|
---|
| 219 | MatrixContent subtractMatrix(ProjectToSubspace.getRows(), ProjectToSubspace.getColumns());
|
---|
| 220 | DoLog(1) && (Log() << Verbose(1) << "Correcting ProjectToSubspace ... " << std::endl);
|
---|
| 221 | BOOST_FOREACH( boost::shared_ptr<Subspace> iter, SubIndices ) {
|
---|
| 222 | const MatrixContent tempMatrix = iter->getEigenvectorMatrix();
|
---|
| 223 | const MatrixContent tempMatrix2 = iter->projectSubspaceMatrixToFullspace(tempMatrix);
|
---|
| 224 | const MatrixContent tempMatrix3 = (tempMatrix2 * ProjectToSubspace);
|
---|
| 225 | DoLog(1) && (Log() << Verbose(1) << "Subtracting matrix from " << *iter << ":" << tempMatrix3 << std::endl);
|
---|
| 226 | subtractMatrix += tempMatrix3;
|
---|
| 227 | }
|
---|
| 228 | ProjectToSubspace -= subtractMatrix;
|
---|
| 229 | DoLog(1) && (Log() << Verbose(1) << "Corrected ProjectToSubspace is " << ProjectToSubspace << std::endl);
|
---|
| 230 |
|
---|
| 231 | ProjectFromSubspace = ((const MatrixContent)ProjectToSubspace).transpose();
|
---|
| 232 | DoLog(1) && (Log() << Verbose(1) << "Corrected ProjectFromSubspace is " << ProjectFromSubspace << std::endl);
|
---|
[9c5296] | 233 | }
|
---|
| 234 |
|
---|
| 235 |
|
---|
| 236 | /** Creates the inverse of LocalToGlobal.
|
---|
| 237 | * Mapping is one-to-one and onto, hence it's simply turning around the map.
|
---|
| 238 | */
|
---|
| 239 | void Subspace::invertLocalToGlobalMapping()
|
---|
| 240 | {
|
---|
| 241 | GlobalToLocal.clear();
|
---|
| 242 | for (mapping::const_iterator iter = LocalToGlobal.begin();
|
---|
| 243 | iter != LocalToGlobal.end();
|
---|
| 244 | ++iter) {
|
---|
| 245 | GlobalToLocal.insert( make_pair(iter->second, iter->first) );
|
---|
| 246 | }
|
---|
| 247 | }
|
---|
| 248 |
|
---|
| 249 |
|
---|
| 250 | /** Project calculated Eigenvectors into full space.
|
---|
| 251 | *
|
---|
| 252 | * @return set of projected eigenvectors.
|
---|
| 253 | */
|
---|
[286af5f] | 254 | const Eigenspace::eigenvectorset & Subspace::getEigenvectorsInFullSpace()
|
---|
[9c5296] | 255 | {
|
---|
| 256 | // check whether bigmatrix is at least as big as EigenspaceMatrix
|
---|
| 257 | ASSERT(Eigenvectors.size() > 0,
|
---|
| 258 | "embedEigenspaceMatrix() - no Eigenvectors given!");
|
---|
| 259 | ASSERT(EigenspaceMatrix.getRows() <= Eigenvectors[0]->getDimension(),
|
---|
| 260 | "embedEigenspaceMatrix() - EigenspaceMatrix has more rows "
|
---|
| 261 | +toString(EigenspaceMatrix.getRows())+" than eigenvectors "
|
---|
| 262 | +toString(Eigenvectors[0]->getDimension())+"!");
|
---|
| 263 | ASSERT(EigenspaceMatrix.getColumns() <= Eigenvectors.size(),
|
---|
| 264 | "embedEigenspaceMatrix() - EigenspaceMatrix has more columns "
|
---|
| 265 | +toString(EigenspaceMatrix.getColumns())+" than eigenvectors "
|
---|
| 266 | +toString(Eigenvectors.size())+"!");
|
---|
| 267 | // check whether EigenspaceMatrix is big enough for both index sets
|
---|
| 268 | ASSERT(EigenspaceMatrix.getColumns() == EigenspaceMatrix.getRows(),
|
---|
| 269 | "embedEigenspaceMatrix() - EigenspaceMatrix is not square "
|
---|
| 270 | +toString(EigenspaceMatrix.getRows())+" than needed by index set "
|
---|
| 271 | +toString(EigenspaceMatrix.getColumns())+"!");
|
---|
| 272 | ASSERT(Indices.size() == EigenspaceMatrix.getColumns(),
|
---|
| 273 | "embedEigenspaceMatrix() - EigenspaceMatrix has not the same number of columns "
|
---|
| 274 | +toString(EigenspaceMatrix.getColumns())+" compared to the index set "
|
---|
| 275 | +toString(Indices.size())+"!");
|
---|
| 276 |
|
---|
| 277 | // construct intermediate matrix
|
---|
| 278 | MatrixContent *intermediatematrix = new MatrixContent(Eigenvectors[0]->getDimension(), Indices.size());
|
---|
| 279 | size_t localcolumn = 0;
|
---|
| 280 | BOOST_FOREACH(size_t columnindex, Indices) {
|
---|
| 281 | // create two vectors from each row and copy assign them
|
---|
| 282 | boost::shared_ptr<VectorContent> srceigenvector(Eigenvectors[columnindex]);
|
---|
| 283 | boost::shared_ptr<VectorContent> desteigenvector(intermediatematrix->getColumnVector(localcolumn));
|
---|
| 284 | *desteigenvector = *srceigenvector;
|
---|
| 285 | localcolumn++;
|
---|
| 286 | }
|
---|
| 287 | // matrix product with eigenbasis EigenspaceMatrix matrix
|
---|
| 288 | *intermediatematrix *= EigenspaceMatrix;
|
---|
| 289 |
|
---|
| 290 | // and place at right columns into bigmatrix
|
---|
| 291 | MatrixContent *bigmatrix = new MatrixContent(Eigenvectors[0]->getDimension(), Eigenvectors.size());
|
---|
| 292 | bigmatrix->setZero();
|
---|
| 293 | localcolumn = 0;
|
---|
| 294 | BOOST_FOREACH(size_t columnindex, Indices) {
|
---|
| 295 | // create two vectors from each row and copy assign them
|
---|
| 296 | boost::shared_ptr<VectorContent> srceigenvector(intermediatematrix->getColumnVector(localcolumn));
|
---|
| 297 | boost::shared_ptr<VectorContent> desteigenvector(bigmatrix->getColumnVector(columnindex));
|
---|
| 298 | *desteigenvector = *srceigenvector;
|
---|
| 299 | localcolumn++;
|
---|
| 300 | }
|
---|
| 301 |
|
---|
| 302 | return Eigenvectors;
|
---|
| 303 | }
|
---|
| 304 |
|
---|
| 305 |
|
---|
[e828c0] | 306 | /** Getter for Subspace::SubIndices.
|
---|
| 307 | *
|
---|
| 308 | * @return const reference to Subspace::SubIndices.
|
---|
| 309 | */
|
---|
| 310 | const Subspace::subset & Subspace::getSubIndices() const
|
---|
| 311 | {
|
---|
| 312 | return SubIndices;
|
---|
| 313 | }
|
---|
| 314 |
|
---|
[9c5296] | 315 | /** Remove a subset of indices from the SubIndices.
|
---|
| 316 | *
|
---|
| 317 | * @param _s subset to remove
|
---|
| 318 | * @return true - removed, false - not found
|
---|
| 319 | */
|
---|
| 320 | bool Subspace::removeSubset(boost::shared_ptr<Subspace> &_s)
|
---|
| 321 | {
|
---|
| 322 | if (SubIndices.count(_s) != 0) {
|
---|
| 323 | SubIndices.erase(_s);
|
---|
| 324 | return true;
|
---|
| 325 | } else {
|
---|
| 326 | return false;
|
---|
| 327 | }
|
---|
| 328 | }
|
---|
| 329 |
|
---|
| 330 | /** Add a subspace set to SubIndices.
|
---|
| 331 | *
|
---|
| 332 | * @param _s subset to add
|
---|
| 333 | * @return true - not present before, false - has already been present
|
---|
| 334 | */
|
---|
| 335 | bool Subspace::addSubset(boost::shared_ptr<Subspace> & _s)
|
---|
| 336 | {
|
---|
| 337 | if (SubIndices.count(_s) != 0)
|
---|
| 338 | return false;
|
---|
| 339 | else {
|
---|
| 340 | SubIndices.insert(_s);
|
---|
| 341 | return true;
|
---|
| 342 | }
|
---|
| 343 | }
|
---|
| 344 |
|
---|
| 345 |
|
---|
| 346 | /** Simply a getter for Eigenvectors, as they are stored as subspace eigenvectors.
|
---|
| 347 | *
|
---|
| 348 | * @return set of eigenvectors in subspace
|
---|
| 349 | */
|
---|
[286af5f] | 350 | const MatrixContent & Subspace::getEigenvectorMatrixInFullSpace()
|
---|
[9c5296] | 351 | {
|
---|
[286af5f] | 352 | // check whether bigmatrix is at least as big as EigenspaceMatrix
|
---|
[e828c0] | 353 | ASSERT(EigenspaceMatrix.getRows() <= FullSpace.getEigenspaceMatrix().getRows(),
|
---|
[286af5f] | 354 | "embedEigenspaceMatrix() - EigenspaceMatrix has more rows "
|
---|
[e828c0] | 355 | +toString(EigenspaceMatrix.getRows())+" than FullSpace::EigenspaceMatrix "
|
---|
[286af5f] | 356 | +toString(Eigenvectors[0]->getDimension())+"!");
|
---|
[e828c0] | 357 | ASSERT(EigenspaceMatrix.getColumns() <= FullSpace.getEigenspaceMatrix().getColumns(),
|
---|
[286af5f] | 358 | "embedEigenspaceMatrix() - EigenspaceMatrix has more columns "
|
---|
[e828c0] | 359 | +toString(EigenspaceMatrix.getColumns())+" than FullSpace::EigenspaceMatrix "
|
---|
[286af5f] | 360 | +toString(Eigenvectors.size())+"!");
|
---|
| 361 | // check whether EigenspaceMatrix is big enough for both index sets
|
---|
| 362 | ASSERT(EigenspaceMatrix.getColumns() == EigenspaceMatrix.getRows(),
|
---|
| 363 | "embedEigenspaceMatrix() - EigenspaceMatrix is not square "
|
---|
| 364 | +toString(EigenspaceMatrix.getRows())+" than needed by index set "
|
---|
| 365 | +toString(EigenspaceMatrix.getColumns())+"!");
|
---|
| 366 | ASSERT(Indices.size() == EigenspaceMatrix.getColumns(),
|
---|
| 367 | "embedEigenspaceMatrix() - EigenspaceMatrix has not the same number of columns "
|
---|
| 368 | +toString(EigenspaceMatrix.getColumns())+" compared to the index set "
|
---|
| 369 | +toString(Indices.size())+"!");
|
---|
| 370 |
|
---|
| 371 | // construct intermediate matrix
|
---|
[e828c0] | 372 | MatrixContent *bigmatrix = new MatrixContent(
|
---|
| 373 | FullSpace.getEigenspaceMatrix().getRows(),
|
---|
| 374 | FullSpace.getEigenspaceMatrix().getColumns());
|
---|
| 375 | *bigmatrix = ProjectToSubspace * EigenspaceMatrix * ProjectFromSubspace;
|
---|
| 376 |
|
---|
| 377 | // MatrixContent *intermediatematrix = new MatrixContent(FullSpace.getEigenspaceMatrix().getRows(), Indices.size());
|
---|
| 378 | // size_t localcolumn = 0;
|
---|
| 379 | // BOOST_FOREACH(size_t columnindex, Indices) {
|
---|
| 380 | // // create two vectors from each row and copy assign them
|
---|
| 381 | // boost::shared_ptr<VectorContent> srceigenvector(Eigenvectors[columnindex]);
|
---|
| 382 | // boost::shared_ptr<VectorContent> desteigenvector(intermediatematrix->getColumnVector(localcolumn));
|
---|
| 383 | // *desteigenvector = *srceigenvector;
|
---|
| 384 | // localcolumn++;
|
---|
| 385 | // }
|
---|
| 386 | // // matrix product with eigenbasis EigenspaceMatrix matrix
|
---|
| 387 | // *intermediatematrix *= EigenspaceMatrix;
|
---|
| 388 | //
|
---|
| 389 | // // and place at right columns into bigmatrix
|
---|
| 390 | // MatrixContent *bigmatrix = new MatrixContent(FullSpace.getEigenspaceMatrix().getRows(), Eigenvectors.size());
|
---|
| 391 | // bigmatrix->setZero();
|
---|
| 392 | // localcolumn = 0;
|
---|
| 393 | // BOOST_FOREACH(size_t columnindex, Indices) {
|
---|
| 394 | // // create two vectors from each row and copy assign them
|
---|
| 395 | // boost::shared_ptr<VectorContent> srceigenvector(intermediatematrix->getColumnVector(localcolumn));
|
---|
| 396 | // boost::shared_ptr<VectorContent> desteigenvector(bigmatrix->getColumnVector(columnindex));
|
---|
| 397 | // *desteigenvector = *srceigenvector;
|
---|
| 398 | // localcolumn++;
|
---|
| 399 | // }
|
---|
[286af5f] | 400 |
|
---|
| 401 | return *bigmatrix;
|
---|
[9c5296] | 402 | }
|
---|
| 403 |
|
---|
[a06042] | 404 |
|
---|
| 405 | /** Creates the projection matrix from Subspace::FullSpace::EigenvectorMatrix.
|
---|
| 406 | * We simply copy the respective eigenvectors from Subspace::FullSpace into
|
---|
| 407 | * Subspace::Eigenvectors.
|
---|
| 408 | */
|
---|
| 409 | void Subspace::createProjectionMatrices()
|
---|
| 410 | {
|
---|
| 411 | // first ProjectToSubspace
|
---|
| 412 |
|
---|
| 413 | // generate column vectors
|
---|
| 414 | std::vector< boost::shared_ptr<VectorContent> > ColumnVectors;
|
---|
| 415 | for (size_t i = 0; i < Indices.size(); ++i) {
|
---|
| 416 | boost::shared_ptr<VectorContent> p(ProjectToSubspace.getColumnVector(i));
|
---|
| 417 | ColumnVectors.push_back( p );
|
---|
| 418 | }
|
---|
| 419 |
|
---|
| 420 | // then copy from real eigenvectors
|
---|
| 421 | size_t localindex = 0;
|
---|
| 422 | BOOST_FOREACH(size_t iter, Indices) {
|
---|
| 423 | *ColumnVectors[localindex] = FullSpace.getEigenvector(iter);
|
---|
[e828c0] | 424 | ++localindex;
|
---|
[a06042] | 425 | }
|
---|
[e828c0] | 426 | DoLog(2) && (Log() << Verbose(2) << "ProjectionToSubspace matrix is " << ProjectToSubspace << std::endl);
|
---|
[a06042] | 427 |
|
---|
| 428 | // then ProjectFromSubspace is just transposed
|
---|
| 429 | ProjectFromSubspace = ((const MatrixContent)ProjectToSubspace).transpose();
|
---|
[e828c0] | 430 | DoLog(2) && (Log() << Verbose(2) << "ProjectFromSubspace matrix is " << ProjectFromSubspace << std::endl);
|
---|
[a06042] | 431 | }
|
---|
| 432 |
|
---|
| 433 |
|
---|
[e828c0] | 434 | /** Creates the subspace matrix by projecting down the given \a _fullmatrix.
|
---|
[a06042] | 435 | * We just perform \f$M = P^t \cdot A \cdot P\f$, when P are the projection matrix,
|
---|
| 436 | * A the full matrix and M the subspace matrix.
|
---|
[e828c0] | 437 | *
|
---|
| 438 | * @param _fullmatrix full matrix A to project into subspace
|
---|
| 439 | * @return subspace matrix M
|
---|
[a06042] | 440 | */
|
---|
[e828c0] | 441 | const MatrixContent Subspace::projectFullspaceMatrixToSubspace(const MatrixContent &_fullmatrix) const
|
---|
[a06042] | 442 | {
|
---|
[e828c0] | 443 | ASSERT((FullSpace.getIndices().size() == _fullmatrix.getRows())
|
---|
| 444 | && (FullSpace.getIndices().size() == _fullmatrix.getColumns()),
|
---|
| 445 | "Subspace::projectSubspaceMatrixToFullspace() - dimensions of this subspace "
|
---|
| 446 | +toString(Indices.size())+" and the given matrix ("
|
---|
| 447 | +toString(_fullmatrix.getRows())+" x "+toString(_fullmatrix.getColumns())+") differ!");
|
---|
[a06042] | 448 | // construct small matrix
|
---|
[e828c0] | 449 | MatrixContent tempMatrix = ProjectFromSubspace * _fullmatrix * ProjectToSubspace;
|
---|
| 450 | return tempMatrix;
|
---|
| 451 | DoLog(2) && (Log() << Verbose(2) << "returned subspace matrix is " << tempMatrix << std::endl);
|
---|
| 452 | }
|
---|
| 453 |
|
---|
| 454 |
|
---|
| 455 | /** Creates a full space matrix which is the projection of given \a _subspacematrix
|
---|
| 456 | * from the subspace.
|
---|
| 457 | *
|
---|
| 458 | * @param _subspacematrix subspace matrix
|
---|
| 459 | * @return full matrix of the Subspace::EigenspaceMatrix projected into
|
---|
| 460 | * Subspace::FullSpace.
|
---|
| 461 | */
|
---|
| 462 | const MatrixContent Subspace::projectSubspaceMatrixToFullspace(const MatrixContent &_subspacematrix) const
|
---|
| 463 | {
|
---|
| 464 | ASSERT((Indices.size() == _subspacematrix.getRows()) && (Indices.size() == _subspacematrix.getColumns()),
|
---|
| 465 | "Subspace::projectSubspaceMatrixToFullspace() - dimensions of this subspace "
|
---|
| 466 | +toString(Indices.size())+" and the given matrix ("
|
---|
| 467 | +toString(_subspacematrix.getRows())+" x "+toString(_subspacematrix.getColumns())+") differ!");
|
---|
| 468 | return (ProjectToSubspace * _subspacematrix * ProjectFromSubspace);
|
---|
[a06042] | 469 | }
|
---|
[286af5f] | 470 |
|
---|
| 471 |
|
---|
[e828c0] | 472 | /** We associate local Eigenvectors with ones from FullSpace by a parallelity
|
---|
[286af5f] | 473 | * criterion.
|
---|
| 474 | */
|
---|
| 475 | void Subspace::createLocalMapping()
|
---|
| 476 | {
|
---|
| 477 | // first LocalToGlobal
|
---|
| 478 | LocalToGlobal.clear();
|
---|
| 479 | IndexSet CorrespondenceList(Indices); // is to ensure one-to-one mapping
|
---|
| 480 |
|
---|
| 481 | for (size_t localindex = 0; localindex< Indices.size(); ++localindex) {
|
---|
| 482 | boost::shared_ptr<VectorContent> &CurrentEigenvector = Eigenvectors[localindex];
|
---|
[e828c0] | 483 | VectorContent tempCurrentEigenvector = ProjectToSubspace * (*CurrentEigenvector);
|
---|
| 484 | Log() << Verbose(1) << "Current Eigenvector is " << *CurrentEigenvector
|
---|
| 485 | << " --(projected)-> " << tempCurrentEigenvector << std::endl;
|
---|
| 486 | if (Eigenvalues[localindex] == 0) {
|
---|
| 487 | DoLog(2) && (Log() << Verbose(2) << "Is null, skipping." << std::endl);
|
---|
| 488 | continue;
|
---|
| 489 | }
|
---|
[286af5f] | 490 |
|
---|
| 491 | // (for now settle with the one we are most parallel to)
|
---|
| 492 | size_t mostparallel_index = FullSpace.getIndices().size();
|
---|
| 493 | double mostparallel_scalarproduct = 0.;
|
---|
| 494 | BOOST_FOREACH( size_t indexiter, CorrespondenceList) {
|
---|
[e828c0] | 495 | DoLog(2) && (Log() << Verbose(2) << "Comparing to old " << indexiter << "th eigenvector " << FullSpace.getEigenvector(indexiter) << std::endl);
|
---|
| 496 | const double scalarproduct = (FullSpace.getEigenvector(indexiter)) * ( tempCurrentEigenvector );
|
---|
| 497 | DoLog(2) && (Log() << Verbose(2) << "SKP is " << scalarproduct << std::endl);
|
---|
[286af5f] | 498 | if (fabs(scalarproduct) > fabs(mostparallel_scalarproduct)) {
|
---|
| 499 | mostparallel_scalarproduct = scalarproduct;
|
---|
| 500 | mostparallel_index = indexiter;
|
---|
| 501 | }
|
---|
| 502 | }
|
---|
| 503 | // and make the assignment if we found one
|
---|
| 504 | if (mostparallel_index != FullSpace.getIndices().size()) {
|
---|
| 505 | // put into std::list for later use
|
---|
| 506 | // invert if pointing in negative direction
|
---|
| 507 | if (mostparallel_scalarproduct < 0) {
|
---|
| 508 | *CurrentEigenvector *= -1.;
|
---|
[e828c0] | 509 | DoLog(1) && (Log() << Verbose(1) << "Associating (inverted) " << *CurrentEigenvector << " with " << mostparallel_index << "th's fullspace eigenvector." << std::endl);
|
---|
[286af5f] | 510 | } else {
|
---|
[e828c0] | 511 | DoLog(1) && (Log() << Verbose(1) << "Associating " << *CurrentEigenvector << " with " << mostparallel_index << "th's fullspace eigenvector." << std::endl);
|
---|
[286af5f] | 512 | }
|
---|
| 513 | ASSERT( LocalToGlobal.count(localindex) == 0,
|
---|
| 514 | "Subspace::createLocalMapping() - localindex "+toString(localindex)+" already assigned to "
|
---|
| 515 | +toString(LocalToGlobal[localindex])+" !=? "+toString(mostparallel_index)+".");
|
---|
| 516 | LocalToGlobal.insert( make_pair(localindex, mostparallel_index) );
|
---|
| 517 | CorrespondenceList.erase(mostparallel_index);
|
---|
| 518 | }
|
---|
| 519 | }
|
---|
| 520 |
|
---|
| 521 | // then invert mapping
|
---|
| 522 | GlobalToLocal.clear();
|
---|
| 523 | BOOST_FOREACH(mapping::value_type iter, LocalToGlobal) {
|
---|
| 524 | ASSERT(GlobalToLocal.count(iter.second) == 0,
|
---|
| 525 | "Subspace::createLocalMapping() - LocalToGlobal is not bijective, key "
|
---|
| 526 | +toString(iter.second)+" present more than once!");
|
---|
| 527 | GlobalToLocal.insert( make_pair(iter.second, iter.first) );
|
---|
| 528 | }
|
---|
| 529 | }
|
---|
| 530 |
|
---|
| 531 |
|
---|
| 532 | /** Get the local eigenvector that is most parallel to the \a i'th full one.
|
---|
| 533 | * We just the internal mapping Subspace::GlobalToLocal.
|
---|
| 534 | * @param i index of global eigenvector
|
---|
| 535 | * @return local eigenvector, most parallel
|
---|
| 536 | */
|
---|
| 537 | const VectorContent Subspace::getEigenvectorParallelToFullOne(size_t i)
|
---|
| 538 | {
|
---|
| 539 | if (GlobalToLocal.count(i) == 0) {
|
---|
| 540 | return ZeroVector;
|
---|
| 541 | } else {
|
---|
| 542 | return ProjectToSubspace*(*Eigenvectors[GlobalToLocal[i]]);
|
---|
| 543 | }
|
---|
| 544 | }
|
---|
| 545 |
|
---|
| 546 |
|
---|
| 547 | /** Get the local eigenvalue of the eigenvector that is most parallel to the
|
---|
| 548 | * \a i'th full one.
|
---|
| 549 | * We just the internal mapping Subspace::GlobalToLocal.
|
---|
| 550 | * @param i index of global eigenvector
|
---|
| 551 | * @return eigenvalue of local eigenvector, most parallel
|
---|
| 552 | */
|
---|
| 553 | const double Subspace::getEigenvalueOfEigenvectorParallelToFullOne(size_t i)
|
---|
| 554 | {
|
---|
| 555 | if (GlobalToLocal.count(i) == 0) {
|
---|
| 556 | return 0.;
|
---|
| 557 | } else {
|
---|
| 558 | return Eigenvalues[GlobalToLocal[i]];
|
---|
| 559 | }
|
---|
| 560 | }
|
---|