source: src/LinearAlgebra/Subspace.cpp@ 9df680

Action_Thermostats Add_AtomRandomPerturbation Add_FitFragmentPartialChargesAction Add_RotateAroundBondAction Add_SelectAtomByNameAction Added_ParseSaveFragmentResults AddingActions_SaveParseParticleParameters Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_ParticleName_to_Atom Adding_StructOpt_integration_tests AtomFragments Automaking_mpqc_open AutomationFragmentation_failures Candidate_v1.5.4 Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator CombiningParticlePotentialParsing Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_BoundInBox_CenterInBox_MoleculeActions Fix_ChargeSampling_PBC Fix_ChronosMutex Fix_FitPartialCharges Fix_FitPotential_needs_atomicnumbers Fix_ForceAnnealing Fix_IndependentFragmentGrids Fix_ParseParticles Fix_ParseParticles_split_forward_backward_Actions Fix_PopActions Fix_QtFragmentList_sorted_selection Fix_Restrictedkeyset_FragmentMolecule Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns Fix_fitting_potentials Fixes ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion FragmentAction_writes_AtomFragments FragmentMolecule_checks_bonddegrees GeometryObjects Gui_Fixes Gui_displays_atomic_force_velocity ImplicitCharges IndependentFragmentGrids IndependentFragmentGrids_IndividualZeroInstances IndependentFragmentGrids_IntegrationTest IndependentFragmentGrids_Sole_NN_Calculation JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix MoreRobust_FragmentAutomation ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PdbParser_setsAtomName PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks Rewrite_FitPartialCharges RotateToPrincipalAxisSystem_UndoRedo SaturateAtoms_findBestMatching SaturateAtoms_singleDegree StoppableMakroAction Subpackage_CodePatterns Subpackage_JobMarket Subpackage_LinearAlgebra Subpackage_levmar Subpackage_mpqc_open Subpackage_vmg Switchable_LogView ThirdParty_MPQC_rebuilt_buildsystem TrajectoryDependenant_MaxOrder TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps TremoloParser_setsAtomName Ubuntu_1604_changes stable
Last change on this file since 9df680 was ad011c, checked in by Frederik Heber <heber@…>, 14 years ago

CodePatterns places all includes now in subfolder CodePatterns/.

  • change all includes accordingly.
  • this was necessary as Helpers and Patterns are not very distinctive names for include folders. Already now, we had a conflict between Helpers from CodePatterns and Helpers from this project.
  • changed compilation test in ax_codepatterns.m4 when changing CodePatterns includes.
  • Property mode set to 100644
File size: 20.7 KB
Line 
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 */
39Subspace::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 */
58Subspace::~Subspace()
59{}
60
61
62/** Diagonalizes the subspace matrix.
63 *
64 */
65void 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 */
108void 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 */
144void 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 */
164void 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 */
191void 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 */
204void 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 */
217void 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 */
239void 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 */
254const 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 */
310const 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 */
320bool 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 */
335bool 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 */
350const 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 */
409void 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 */
441const 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 */
462const 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 */
475void 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 */
537const 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 */
553const 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}
Note: See TracBrowser for help on using the repository browser.