| [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 | } | 
|---|