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