| 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 |  | 
|---|
| 20 | #include "CodePatterns/MemDebug.hpp" | 
|---|
| 21 |  | 
|---|
| 22 | #include <boost/shared_ptr.hpp> | 
|---|
| 23 | #include <boost/foreach.hpp> | 
|---|
| 24 |  | 
|---|
| 25 | #include "CodePatterns/Assert.hpp" | 
|---|
| 26 | #include "CodePatterns/Log.hpp" | 
|---|
| 27 | #include "CodePatterns/toString.hpp" | 
|---|
| 28 | #include "CodePatterns/Verbose.hpp" | 
|---|
| 29 |  | 
|---|
| 30 | #include "Eigenspace.hpp" | 
|---|
| 31 | #include "Subspace.hpp" | 
|---|
| 32 |  | 
|---|
| 33 |  | 
|---|
| 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), | 
|---|
| 41 | ProjectToSubspace(_FullSpace.getIndices().size(), _s.size()), | 
|---|
| 42 | ProjectFromSubspace(_s.size(), _FullSpace.getIndices().size()), | 
|---|
| 43 | FullSpace(_FullSpace), | 
|---|
| 44 | ZeroVector(_FullSpace.getIndices().size()) | 
|---|
| 45 | { | 
|---|
| 46 | // TODO: away with both of this when calculateEigenSubspace() works | 
|---|
| 47 | // create projection matrices | 
|---|
| 48 | createProjectionMatrices(); | 
|---|
| 49 |  | 
|---|
| 50 | // create eigenspace matrices | 
|---|
| 51 | EigenspaceMatrix = projectFullspaceMatrixToSubspace(FullSpace.getEigenspaceMatrix()); | 
|---|
| 52 | } | 
|---|
| 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 | { | 
|---|
| 67 | // project down | 
|---|
| 68 | createProjectionMatrices(); | 
|---|
| 69 | // remove subsubspace directions | 
|---|
| 70 | //correctProjectionMatricesFromSubIndices(); | 
|---|
| 71 | // solve | 
|---|
| 72 | EigenspaceMatrix = projectFullspaceMatrixToSubspace(FullSpace.getEigenspaceMatrix()); | 
|---|
| 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; | 
|---|
| 80 |  | 
|---|
| 81 | // create mapping | 
|---|
| 82 | createLocalMapping(); | 
|---|
| 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 | } | 
|---|
| 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 |  | 
|---|
| 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 | */ | 
|---|
| 164 | void Subspace::correctEigenvectorsFromSubIndices() | 
|---|
| 165 | { | 
|---|
| 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); | 
|---|
| 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 | */ | 
|---|
| 254 | const Eigenspace::eigenvectorset & Subspace::getEigenvectorsInFullSpace() | 
|---|
| 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 |  | 
|---|
| 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 |  | 
|---|
| 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 | */ | 
|---|
| 350 | const MatrixContent & Subspace::getEigenvectorMatrixInFullSpace() | 
|---|
| 351 | { | 
|---|
| 352 | // check whether bigmatrix is at least as big as EigenspaceMatrix | 
|---|
| 353 | ASSERT(EigenspaceMatrix.getRows() <= FullSpace.getEigenspaceMatrix().getRows(), | 
|---|
| 354 | "embedEigenspaceMatrix() - EigenspaceMatrix has more rows " | 
|---|
| 355 | +toString(EigenspaceMatrix.getRows())+" than FullSpace::EigenspaceMatrix " | 
|---|
| 356 | +toString(Eigenvectors[0]->getDimension())+"!"); | 
|---|
| 357 | ASSERT(EigenspaceMatrix.getColumns() <= FullSpace.getEigenspaceMatrix().getColumns(), | 
|---|
| 358 | "embedEigenspaceMatrix() - EigenspaceMatrix has more columns " | 
|---|
| 359 | +toString(EigenspaceMatrix.getColumns())+" than FullSpace::EigenspaceMatrix " | 
|---|
| 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 | 
|---|
| 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 | //  } | 
|---|
| 400 |  | 
|---|
| 401 | return *bigmatrix; | 
|---|
| 402 | } | 
|---|
| 403 |  | 
|---|
| 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); | 
|---|
| 424 | ++localindex; | 
|---|
| 425 | } | 
|---|
| 426 | DoLog(2) && (Log() << Verbose(2) << "ProjectionToSubspace matrix is " << ProjectToSubspace << std::endl); | 
|---|
| 427 |  | 
|---|
| 428 | // then ProjectFromSubspace is just transposed | 
|---|
| 429 | ProjectFromSubspace = ((const MatrixContent)ProjectToSubspace).transpose(); | 
|---|
| 430 | DoLog(2) && (Log() << Verbose(2) << "ProjectFromSubspace matrix is " << ProjectFromSubspace << std::endl); | 
|---|
| 431 | } | 
|---|
| 432 |  | 
|---|
| 433 |  | 
|---|
| 434 | /** Creates the subspace matrix by projecting down the given \a _fullmatrix. | 
|---|
| 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. | 
|---|
| 437 | * | 
|---|
| 438 | *  @param _fullmatrix full matrix A to project into subspace | 
|---|
| 439 | *  @return subspace matrix M | 
|---|
| 440 | */ | 
|---|
| 441 | const MatrixContent Subspace::projectFullspaceMatrixToSubspace(const MatrixContent &_fullmatrix) const | 
|---|
| 442 | { | 
|---|
| 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!"); | 
|---|
| 448 | // construct small matrix | 
|---|
| 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); | 
|---|
| 469 | } | 
|---|
| 470 |  | 
|---|
| 471 |  | 
|---|
| 472 | /** We associate local Eigenvectors with ones from FullSpace by a parallelity | 
|---|
| 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]; | 
|---|
| 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 | } | 
|---|
| 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) { | 
|---|
| 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); | 
|---|
| 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.; | 
|---|
| 509 | DoLog(1) && (Log() << Verbose(1) << "Associating (inverted) " << *CurrentEigenvector << " with " << mostparallel_index << "th's fullspace eigenvector." << std::endl); | 
|---|
| 510 | } else { | 
|---|
| 511 | DoLog(1) && (Log() << Verbose(1) << "Associating " << *CurrentEigenvector << " with " << mostparallel_index << "th's fullspace eigenvector." << std::endl); | 
|---|
| 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 | } | 
|---|