Ignore:
Timestamp:
Dec 5, 2010, 12:19:33 AM (15 years ago)
Author:
Frederik Heber <heber@…>
Branches:
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, Candidate_v1.7.0, 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
Children:
001f8a
Parents:
6e06bd (diff), e828c0 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'SubspaceFactorizer' into stable

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/LinearAlgebra/MatrixContent.cpp

    r6e06bd rf03705  
    1515
    1616#include "LinearAlgebra/RealSpaceMatrix.hpp"
     17#include "Exceptions/NotInvertibleException.hpp"
    1718#include "Helpers/Assert.hpp"
    18 #include "Exceptions/NotInvertibleException.hpp"
     19#include "Helpers/defs.hpp"
    1920#include "Helpers/fast_functions.hpp"
    20 #include "Helpers/Assert.hpp"
    2121#include "LinearAlgebra/Vector.hpp"
    2222#include "LinearAlgebra/VectorContent.hpp"
     
    3030#include <gsl/gsl_vector.h>
    3131#include <cmath>
     32#include <cassert>
    3233#include <iostream>
     34#include <set>
    3335
    3436using namespace std;
     
    4547  content = gsl_matrix_calloc(rows, columns);
    4648}
     49
     50/** Constructor of class VectorContent.
     51 * We need this MatrixBaseCase for the VectorContentView class.
     52 * There no content should be allocated, as it is just a view with an internal
     53 * gsl_vector_view. Hence, MatrixBaseCase is just dummy class to give the
     54 * constructor a unique signature.
     55 * \param MatrixBaseCase
     56 */
     57MatrixContent::MatrixContent(size_t _rows, size_t _columns, MatrixBaseCase) :
     58    rows(_rows),
     59    columns(_columns)
     60{}
    4761
    4862/** Constructor for class MatrixContent.
     
    5266 */
    5367MatrixContent::MatrixContent(size_t _rows, size_t _columns, const double *src) :
    54         rows(_rows),
    55         columns(_columns)
     68    rows(_rows),
     69    columns(_columns)
    5670{
    5771  content = gsl_matrix_calloc(rows, columns);
     
    7589 */
    7690MatrixContent::MatrixContent(gsl_matrix *&src) :
    77         rows(src->size1),
    78         columns(src->size2)
     91    rows(src->size1),
     92    columns(src->size2)
    7993{
    8094  content = gsl_matrix_alloc(src->size1, src->size2);
     
    88102 */
    89103MatrixContent::MatrixContent(const MatrixContent &src) :
    90         rows(src.rows),
    91         columns(src.columns)
     104    rows(src.rows),
     105    columns(src.columns)
    92106{
    93107  content = gsl_matrix_alloc(src.rows, src.columns);
     
    99113 */
    100114MatrixContent::MatrixContent(const MatrixContent *src) :
    101         rows(src->rows),
    102         columns(src->columns)
     115    rows(src->rows),
     116    columns(src->columns)
    103117{
    104118  ASSERT(src != NULL, "MatrixContent::MatrixContent - pointer to source matrix is NULL!");
     
    114128}
    115129
     130/** Getter for MatrixContent::rows.
     131 * \return MatrixContent::rows
     132 */
     133const size_t MatrixContent::getRows() const
     134{
     135  return rows;
     136}
     137
     138/** Getter for MatrixContent::columns.
     139 * \return MatrixContent::columns
     140 */
     141const size_t MatrixContent::getColumns() const
     142{
     143  return columns;
     144}
     145
     146/** Return a VectorViewContent of the \a column -th column vector.
     147 *
     148 * @param column index of column
     149 * @return column of matrix as VectorContent
     150 */
     151VectorContent *MatrixContent::getColumnVector(size_t column) const
     152{
     153  ASSERT(column < columns,
     154      "MatrixContent::getColumnVector() - requested column "+toString(column)
     155      +" greater than dimension "+toString(columns));
     156  return (new VectorViewContent(gsl_matrix_column(content,column)));
     157}
     158
     159/** Returns a VectorViewContent of the \a row -th row vector.
     160 * @param row row index
     161 * @return VectorContent of row vector
     162 */
     163VectorContent *MatrixContent::getRowVector(size_t row) const
     164{
     165  ASSERT(row < rows,
     166      "MatrixContent::getColumnVector() - requested row "+toString(row)
     167      +" greater than dimension "+toString(rows));
     168  return (new VectorViewContent(gsl_matrix_row(content,row)));
     169}
     170
     171/** Returns the main diagonal of the matrix as VectorContent.
     172 * @return diagonal as VectorContent.
     173 */
     174VectorContent *MatrixContent::getDiagonalVector() const
     175{
     176  return (new VectorViewContent(gsl_matrix_diagonal(content)));
     177}
     178
    116179/** Set matrix to identity.
    117180 */
     
    120183  for(int i=rows;i--;){
    121184    for(int j=columns;j--;){
    122       set(i,j,i==j);
     185      set(i,j,(double)(i==j));
    123186    }
    124187  }
     
    187250const MatrixContent &MatrixContent::operator*=(const MatrixContent &rhs)
    188251{
    189   ASSERT(rows == rhs.rows,
    190       "MatrixContent::operator*=() - row dimension differ: "+toString(rows)+" != "+toString(rhs.rows)+".");
    191   ASSERT(columns == rhs.columns,
    192       "MatrixContent::operator*=() - columns dimension differ: "+toString(columns)+" != "+toString(rhs.columns)+".");
     252  ASSERT(rhs.columns == rhs.rows,
     253      "MatrixContent::operator*=() - rhs matrix is not square: "+toString(rhs.columns)+" != "+toString(rhs.rows)+".");
     254  ASSERT(columns == rhs.rows,
     255      "MatrixContent::operator*=() - columns dimension differ: "+toString(columns)+" != "+toString(rhs.rows)+".");
    193256  (*this) = (*this)*rhs;
    194257  return *this;
     
    201264const MatrixContent MatrixContent::operator*(const MatrixContent &rhs) const
    202265{
    203   gsl_matrix *res = gsl_matrix_alloc(rows, columns);
     266  ASSERT (columns == rhs.rows,
     267      "MatrixContent::operator*() - dimensions not match for matrix product (a,b)*(b,c) = (a,c):"
     268      "("+toString(rows)+","+toString(columns)+")*("+toString(rhs.rows)+","+toString(rhs.columns)+")");
     269  gsl_matrix *res = gsl_matrix_alloc(rows, rhs.columns);
    204270  gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, content, rhs.content, 0.0, res);
    205271  // gsl_matrix is taken over by constructor, hence no free
     
    209275}
    210276
     277/** Hadamard multiplication with copy operator.
     278 * The Hadamard product is component-wise matrix product.
     279 * \param &rhs matrix to hadamard-multiply with
     280 * \return reference to newly allocated MatrixContent
     281 */
     282const MatrixContent MatrixContent::operator&(const MatrixContent &rhs) const
     283{
     284  ASSERT ((rows == rhs.rows) && (columns == rhs.columns),
     285      "MatrixContent::operator&() - dimensions not match for matrix product (a,b) != (b,c):"
     286      "("+toString(rows)+","+toString(columns)+") != ("+toString(rhs.rows)+","+toString(rhs.columns)+")");
     287  gsl_matrix *res = gsl_matrix_alloc(rows, rhs.columns);
     288  for (size_t i=0;i<rows;++i)
     289    for (size_t j=0;j<columns;++j)
     290      gsl_matrix_set(res, i,j, gsl_matrix_get(content, i,j)*gsl_matrix_get(rhs.content, i,j));
     291  // gsl_matrix is taken over by constructor, hence no free
     292  MatrixContent tmp(res);
     293  gsl_matrix_free(res);
     294  return tmp;
     295}
     296
     297/** Hadamard multiplication with copy operator.
     298 * The Hadamard product is component-wise matrix product.
     299 * Note that Hadamard product can easily be done on top of \a *this matrix.
     300 * Hence, we don't need to use the multiply and copy operator as in the case of
     301 * MatrixContent::operator*=().
     302 * \param &rhs matrix to hadamard-multiply with
     303 * \return reference to newly allocated MatrixContent
     304 */
     305const MatrixContent &MatrixContent::operator&=(const MatrixContent &rhs)
     306{
     307  ASSERT ((rows == rhs.rows) && (columns == rhs.columns),
     308      "MatrixContent::operator&() - dimensions not match for matrix product (a,b) != (b,c):"
     309      "("+toString(rows)+","+toString(columns)+") != ("+toString(rhs.rows)+","+toString(rhs.columns)+")");
     310  for (size_t i=0;i<rows;++i)
     311    for (size_t j=0;j<columns;++j)
     312      gsl_matrix_set(content, i,j, gsl_matrix_get(content, i,j)*gsl_matrix_get(rhs.content, i,j));
     313  return *this;
     314}
     315
    211316/* ========================== Accessing =============================== */
    212317
     
    311416bool MatrixContent::SwapRowColumn(size_t i, size_t j)
    312417{
    313   assert (rows == columns && "The matrix must be square for swapping row against column to be possible.");
     418  ASSERT (rows == columns,
     419      "MatrixContent::SwapRowColumn() - The matrix must be square for swapping row against column to be possible.");
    314420  return (gsl_matrix_swap_rowcol (content, i, j) == GSL_SUCCESS);
    315421};
     
    344450}
    345451
    346 /** Transform the matrix to its eigenbasis ans return resulting eigenvalues.
     452/** Transform the matrix to its eigenbasis and return resulting eigenvalues.
     453 * Note that we only return real-space part in case of non-symmetric matrix.
    347454 * \warn return vector has to be freed'd
     455 * TODO: encapsulate return value in boost::shared_ptr or in VectorContent.
    348456 * \return gsl_vector pointer to vector of eigenvalues
    349457 */
    350458gsl_vector* MatrixContent::transformToEigenbasis()
    351459{
    352   ASSERT (rows == columns,
    353       "MatrixContent::transformToEigenbasis() - only implemented for square matrices: "+toString(rows)+"!="+toString(columns)+"!");
    354   gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(rows);
    355   gsl_vector *eval = gsl_vector_alloc(rows);
    356   gsl_matrix *evec = gsl_matrix_alloc(rows, rows);
    357   gsl_eigen_symmv(content, eval, evec, T);
    358   gsl_eigen_symmv_free(T);
    359   gsl_matrix_memcpy(content, evec);
    360   gsl_matrix_free(evec);
    361   return eval;
     460  if (rows == columns) { // symmetric
     461    gsl_eigen_symmv_workspace *T = gsl_eigen_symmv_alloc(rows);
     462    gsl_vector *eval = gsl_vector_alloc(rows);
     463    gsl_matrix *evec = gsl_matrix_alloc(rows, rows);
     464    gsl_eigen_symmv(content, eval, evec, T);
     465    gsl_eigen_symmv_free(T);
     466    gsl_matrix_memcpy(content, evec);
     467    gsl_matrix_free(evec);
     468    return eval;
     469  } else { // non-symmetric
     470    // blow up gsl_matrix in content to square matrix, fill other components with zero
     471    const size_t greaterDimension = rows > columns ? rows : columns;
     472    gsl_matrix *content_square = gsl_matrix_alloc(greaterDimension, greaterDimension);
     473    for (size_t i=0; i<greaterDimension; i++) {
     474      for (size_t j=0; j<greaterDimension; j++) {
     475        const double value = ((i < rows) && (j < columns)) ? gsl_matrix_get(content,i,j) : 0.;
     476        gsl_matrix_set(content_square, i,j, value);
     477      }
     478    }
     479
     480    // show squared matrix by putting it into a MatrixViewContent
     481    MatrixContent *ContentSquare = new MatrixViewContent(gsl_matrix_submatrix(content_square,0,0,content_square->size1, content_square->size2));
     482    std::cout << "The squared matrix is " << *ContentSquare << std::endl;
     483
     484    // solve eigenvalue problem
     485    gsl_eigen_nonsymmv_workspace *T = gsl_eigen_nonsymmv_alloc(rows);
     486    gsl_vector_complex *eval = gsl_vector_complex_alloc(greaterDimension);
     487    gsl_matrix_complex *evec = gsl_matrix_complex_alloc(greaterDimension, greaterDimension);
     488    gsl_eigen_nonsymmv(content_square, eval, evec, T);
     489    gsl_eigen_nonsymmv_free(T);
     490
     491    // copy eigenvectors real-parts into content_square and ...
     492    for (size_t i=0; i<greaterDimension; i++)
     493      for (size_t j=0; j<greaterDimension; j++)
     494        gsl_matrix_set(content_square, i,j, GSL_REAL(gsl_matrix_complex_get(evec,i,j)));
     495
     496    // ... show complex-valued eigenvector matrix
     497    std::cout << "The real-value eigenvector matrix is " << *ContentSquare << std::endl;
     498//    std::cout << "Resulting eigenvector matrix is [";
     499//    for (size_t i=0; i<greaterDimension; i++) {
     500//      for (size_t j=0; j<greaterDimension; j++) {
     501//        std::cout << "(" << GSL_REAL(gsl_matrix_complex_get(evec,i,j))
     502//            << "," << GSL_IMAG(gsl_matrix_complex_get(evec,i,j)) << ")";
     503//        if (j < greaterDimension-1)
     504//          std::cout << " ";
     505//      }
     506//      if (i < greaterDimension-1)
     507//        std::cout << "; ";
     508//    }
     509//    std::cout << "]" << std::endl;
     510
     511    // copy real-parts of complex eigenvalues and eigenvectors (column-wise orientation)
     512    gsl_vector *eval_real = gsl_vector_alloc(columns);
     513    size_t I=0;
     514    for (size_t i=0; i<greaterDimension; i++) { // only copy real space part
     515      if (fabs(GSL_REAL(gsl_vector_complex_get(eval,i))) > MYEPSILON) { // only take eigenvectors with value > 0
     516        std::cout << i << "th eigenvalue is (" << GSL_REAL(gsl_vector_complex_get(eval,i)) << "," << GSL_IMAG(gsl_vector_complex_get(eval,i)) << ")" << std::endl;
     517        for (size_t j=0; j<greaterDimension; j++) {
     518          if (fabs(GSL_IMAG(gsl_matrix_complex_get(evec,j,i))) > MYEPSILON)
     519            std::cerr << "MatrixContent::transformToEigenbasis() - WARNING: eigenvectors are complex-valued!" << std::endl;
     520          gsl_matrix_set(content, j,I, GSL_REAL(gsl_matrix_complex_get(evec,j,i)));
     521        }
     522        if (fabs(GSL_IMAG(gsl_vector_complex_get(eval,I))) > MYEPSILON)
     523          std::cerr << "MatrixContent::transformToEigenbasis() - WARNING: eigenvectors are complex-valued!" << std::endl;
     524        gsl_vector_set(eval_real, I, GSL_REAL(gsl_vector_complex_get(eval, i)));
     525        I++;
     526      }
     527    }
     528    gsl_matrix_complex_free(evec);
     529    gsl_vector_complex_free(eval);
     530    delete ContentSquare;
     531
     532    return eval_real;
     533  }
     534}
     535
     536
     537/** Sorts the eigenpairs in ascending order of the eigenvalues.
     538 * We assume that MatrixContent::transformToEigenbasis() has just been called.
     539 * @param eigenvalues vector of eigenvalue from
     540 *        MatrixContent::transformToEigenbasis()
     541 */
     542void MatrixContent::sortEigenbasis(gsl_vector *eigenvalues)
     543{
     544  gsl_eigen_symmv_sort (eigenvalues, content,
     545                          GSL_EIGEN_SORT_ABS_ASC);
    362546}
    363547
     
    414598{
    415599  int signum = 0;
    416   assert (rows == columns && "Determinant can only be calculated for square matrices.");
     600  ASSERT(rows == columns,
     601      "MatrixContent::Determinant() - determinant can only be calculated for square matrices.");
    417602  gsl_permutation *p = gsl_permutation_alloc(rows);
    418603  gsl_linalg_LU_decomp(content, p, &signum);
     
    473658}
    474659
    475 Vector operator*(const MatrixContent &mat,const Vector &vec)
    476 {
    477   Vector result;
    478   gsl_blas_dgemv( CblasNoTrans, 1.0, mat.content, vec.content->content, 0.0, result.content->content);
    479   return result;
    480 }
     660
     661std::ostream & operator<<(std::ostream &ost, const MatrixContent &mat)
     662{
     663  ost << "\\begin{pmatrix}";
     664  for (size_t i=0;i<mat.rows;i++) {
     665    for (size_t j=0;j<mat.columns;j++) {
     666      ost << mat.at(i,j) << " ";
     667      if (j != mat.columns-1)
     668        ost << "& ";
     669    }
     670    if (i != mat.rows-1)
     671      ost << "\\\\ ";
     672  }
     673  ost << "\\end{pmatrix}";
     674  return ost;
     675}
Note: See TracChangeset for help on using the changeset viewer.