Changeset f03705 for src/LinearAlgebra/MatrixContent.cpp
- Timestamp:
- Dec 5, 2010, 12:19:33 AM (15 years ago)
- 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. - File:
-
- 1 edited
-
src/LinearAlgebra/MatrixContent.cpp (modified) (16 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/LinearAlgebra/MatrixContent.cpp
r6e06bd rf03705 15 15 16 16 #include "LinearAlgebra/RealSpaceMatrix.hpp" 17 #include "Exceptions/NotInvertibleException.hpp" 17 18 #include "Helpers/Assert.hpp" 18 #include " Exceptions/NotInvertibleException.hpp"19 #include "Helpers/defs.hpp" 19 20 #include "Helpers/fast_functions.hpp" 20 #include "Helpers/Assert.hpp"21 21 #include "LinearAlgebra/Vector.hpp" 22 22 #include "LinearAlgebra/VectorContent.hpp" … … 30 30 #include <gsl/gsl_vector.h> 31 31 #include <cmath> 32 #include <cassert> 32 33 #include <iostream> 34 #include <set> 33 35 34 36 using namespace std; … … 45 47 content = gsl_matrix_calloc(rows, columns); 46 48 } 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 */ 57 MatrixContent::MatrixContent(size_t _rows, size_t _columns, MatrixBaseCase) : 58 rows(_rows), 59 columns(_columns) 60 {} 47 61 48 62 /** Constructor for class MatrixContent. … … 52 66 */ 53 67 MatrixContent::MatrixContent(size_t _rows, size_t _columns, const double *src) : 54 rows(_rows),55 columns(_columns)68 rows(_rows), 69 columns(_columns) 56 70 { 57 71 content = gsl_matrix_calloc(rows, columns); … … 75 89 */ 76 90 MatrixContent::MatrixContent(gsl_matrix *&src) : 77 rows(src->size1),78 columns(src->size2)91 rows(src->size1), 92 columns(src->size2) 79 93 { 80 94 content = gsl_matrix_alloc(src->size1, src->size2); … … 88 102 */ 89 103 MatrixContent::MatrixContent(const MatrixContent &src) : 90 rows(src.rows),91 columns(src.columns)104 rows(src.rows), 105 columns(src.columns) 92 106 { 93 107 content = gsl_matrix_alloc(src.rows, src.columns); … … 99 113 */ 100 114 MatrixContent::MatrixContent(const MatrixContent *src) : 101 rows(src->rows),102 columns(src->columns)115 rows(src->rows), 116 columns(src->columns) 103 117 { 104 118 ASSERT(src != NULL, "MatrixContent::MatrixContent - pointer to source matrix is NULL!"); … … 114 128 } 115 129 130 /** Getter for MatrixContent::rows. 131 * \return MatrixContent::rows 132 */ 133 const size_t MatrixContent::getRows() const 134 { 135 return rows; 136 } 137 138 /** Getter for MatrixContent::columns. 139 * \return MatrixContent::columns 140 */ 141 const 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 */ 151 VectorContent *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 */ 163 VectorContent *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 */ 174 VectorContent *MatrixContent::getDiagonalVector() const 175 { 176 return (new VectorViewContent(gsl_matrix_diagonal(content))); 177 } 178 116 179 /** Set matrix to identity. 117 180 */ … … 120 183 for(int i=rows;i--;){ 121 184 for(int j=columns;j--;){ 122 set(i,j, i==j);185 set(i,j,(double)(i==j)); 123 186 } 124 187 } … … 187 250 const MatrixContent &MatrixContent::operator*=(const MatrixContent &rhs) 188 251 { 189 ASSERT(r ows == rhs.rows,190 "MatrixContent::operator*=() - r ow 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)+"."); 193 256 (*this) = (*this)*rhs; 194 257 return *this; … … 201 264 const MatrixContent MatrixContent::operator*(const MatrixContent &rhs) const 202 265 { 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); 204 270 gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1.0, content, rhs.content, 0.0, res); 205 271 // gsl_matrix is taken over by constructor, hence no free … … 209 275 } 210 276 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 */ 282 const 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 */ 305 const 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 211 316 /* ========================== Accessing =============================== */ 212 317 … … 311 416 bool MatrixContent::SwapRowColumn(size_t i, size_t j) 312 417 { 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."); 314 420 return (gsl_matrix_swap_rowcol (content, i, j) == GSL_SUCCESS); 315 421 }; … … 344 450 } 345 451 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. 347 454 * \warn return vector has to be freed'd 455 * TODO: encapsulate return value in boost::shared_ptr or in VectorContent. 348 456 * \return gsl_vector pointer to vector of eigenvalues 349 457 */ 350 458 gsl_vector* MatrixContent::transformToEigenbasis() 351 459 { 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 */ 542 void MatrixContent::sortEigenbasis(gsl_vector *eigenvalues) 543 { 544 gsl_eigen_symmv_sort (eigenvalues, content, 545 GSL_EIGEN_SORT_ABS_ASC); 362 546 } 363 547 … … 414 598 { 415 599 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."); 417 602 gsl_permutation *p = gsl_permutation_alloc(rows); 418 603 gsl_linalg_LU_decomp(content, p, &signum); … … 473 658 } 474 659 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 661 std::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.
