/*
* Project: MoleCuilder
* Description: creates and alters molecular systems
* Copyright (C) 2010-2012 University of Bonn. All rights reserved.
*
*
* This file is part of MoleCuilder.
*
* MoleCuilder is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* MoleCuilder is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MoleCuilder. If not, see .
*/
/*
* MatrixContainer.cpp
*
* Created on: Sep 15, 2011
* Author: heber
*/
// include config.h
#ifdef HAVE_CONFIG_H
#include
#endif
#include "CodePatterns/MemDebug.hpp"
#include
#include
#include
#include "CodePatterns/Log.hpp"
#include "KeySetsContainer.hpp"
#include "Fragmentation/helpers.hpp"
#include "Helpers/defs.hpp"
#include "Helpers/helpers.hpp"
#include "MatrixContainer.hpp"
/** Constructor of MatrixContainer class.
*/
MatrixContainer::MatrixContainer()
{
Header.resize(1);
RowCounter.resize(1);
ColumnCounter.resize(1);
ColumnCounter[0] = -1;
MatrixCounter = 0;
};
/** Destructor of MatrixContainer class.
*/
MatrixContainer::~MatrixContainer()
{}
/** Either copies index matrix from another MatrixContainer or initialises with trivial mapping if NULL.
* This either copies the index matrix or just maps 1 to 1, 2 to 2 and so on for all fragments.
* \param *Matrix pointer to other MatrixContainer
* \return true - copy/initialisation sucessful, false - dimension false for copying
*/
bool MatrixContainer::InitialiseIndices(class MatrixContainer *_container)
{
if (_container == NULL) {
LOG(3, "INFO: Initialising indices with trivial mapping.");
Indices.resize(MatrixCounter + 1);
for(int i=MatrixCounter+1;i--;) {
Indices[i].resize(RowCounter[i]);
for(int j=RowCounter[i];j--;)
Indices[i][j] = j;
}
} else {
std::stringstream output;
if (MatrixCounter != _container->MatrixCounter)
return false;
Indices.resize(MatrixCounter + 1);
for(int i=MatrixCounter+1;i--;) {
if (RowCounter[i] != _container->RowCounter[i])
return false;
Indices[i].resize(_container->RowCounter[i]);
for(int j=_container->RowCounter[i];j--;) {
Indices[i][j] = _container->Indices[i][j];
output << Indices[i][j] << "\t";
}
}
LOG(3, "INFO: Initialising indices from other MatrixContainer: " << output.str());
}
return true;
};
/** Parsing a number of matrices.
* -# open the matrix file
* -# skip some lines (\a skiplines)
* -# scan header lines for number of columns
* -# scan lines for number of rows
* -# allocate a temporary matrix
* -# loop over found column and row counts and parse in each entry
* -# use MatrixContainer::AddMatrix() to add the parsed matrix to the internal
* \param &input input stream
* \param skiplines number of inital lines to skip
* \param skiplines number of inital columns to skip
* \param MatrixNr index number in Matrix array to parse into
* \return parsing successful
*/
bool MatrixContainer::ParseMatrix(std::istream &input, int skiplines, int skipcolumns, size_t MatrixNr)
{
stringstream line;
string token;
char filename[1023];
if (input.fail()) {
ELOG(1, endl << "MatrixContainer::ParseMatrix: Unable to parse istream.");
//performCriticalExit();
return false;
}
// parse header
std::string header;
char dummy[1024];
for (int m=skiplines+1;m--;)
input.getline(dummy, 1023);
line.str(dummy);
for(int k=skipcolumns;k--;)
line >> header;
LOG(3, "INFO: Header of Matrix " << MatrixNr << " :" << line.str());
// scan header for number of columns
size_t ColumnCounter = 0;
while ( getline(line,token, '\t') ) {
if (token.length() > 0)
ColumnCounter++;
}
LOG(3, "INFO: "+line.str());
// scan rest for number of rows/lines
size_t RowCounter = -1;
while (!input.eof()) {
input.getline(filename, 1023);
LOG(3, "INFO: Comparing: " << strncmp(filename,"MeanForce",9));
RowCounter++; // then line was not last MeanForce
if (strncmp(filename,"MeanForce", 9) == 0) {
break;
}
}
// allocate temporary matrix
MatrixArray temp_matrix;
temp_matrix.resize(RowCounter);
for(MatrixArray::iterator iter = temp_matrix.begin(); iter != temp_matrix.end(); ++iter)
(*iter).resize(ColumnCounter);
// parse in each entry for this matrix
input.clear();
input.seekg(ios::beg);
for (int m=skiplines+1;m--;)
input.getline(dummy, 1023); // skip header
line.str(dummy);
LOG(3, "INFO: Header: " << line.str());
for(int k=skipcolumns;k--;) // skip columns in header too
line >> filename;
header = line.str();
for(size_t j=0;j> filename;
for(size_t k=0;(k> temp_matrix[j][k];
output << " " << std::setprecision(2) << temp_matrix[j][k] << endl;
}
LOG(3, output.str());
}
// finally add the matrix
return AddMatrix(header, temp_matrix, MatrixNr);
}
/** Adds a matrix at position \a MatrixNr to MatrixContainer::Matrix.
*
* @param header header to add for this matrix
* @param matrix to add
* @param MatrixNr position in MatrixContainer::Matrix.
* @return true - insertion ok, false - invalid matrix
*/
bool MatrixContainer::AddMatrix(const std::string &header, const MatrixArray &matrix, size_t MatrixNr)
{
// make some pre-checks
if (header.size() == 0)
ELOG(2, "The given header of the matrix to add is empty.");
if (matrix.size() == 0) {
ELOG(1, "RowCounter[" << MatrixNr << "]: " << RowCounter[MatrixNr] << " from input stream.");
return false;
}
if (matrix[0].size() == 0) {
ELOG(1, "ColumnCounter[" << MatrixNr << "]: " << ColumnCounter[MatrixNr] << " from ostream.");
return false;
}
// add header
if (Header.size() <= MatrixNr)
Header.resize(MatrixNr+1);
Header[MatrixNr] = header;
// row count
if (RowCounter.size() <= MatrixNr)
RowCounter.resize(MatrixNr+1);
RowCounter[MatrixNr] = matrix.size();
LOG(4, "INFO: RowCounter[" << MatrixNr << "]: " << RowCounter[MatrixNr] << " from input stream.");
// column count
if (ColumnCounter.size() <= MatrixNr)
ColumnCounter.resize(MatrixNr+1);
ColumnCounter[MatrixNr] = matrix[0].size();
LOG(4, "INFO: ColumnCounter[" << MatrixNr << "]: " << ColumnCounter[MatrixNr] << ".");
// allocate matrix ...
if (Matrix.size() <= MatrixNr)
Matrix.resize(MatrixNr+1);
MatrixCounter = Matrix.size()-1;
Matrix[MatrixNr].resize(RowCounter[MatrixNr] + 1);
for(int j=0;j<=RowCounter[MatrixNr];++j)
Matrix[MatrixNr][j].resize(ColumnCounter[MatrixNr]+1);
// .. and copy values
for(int j=0;j max)
max = fabs(Matrix[i][j][k]);
if (fabs(max) < MYEPSILON)
max += MYEPSILON;
return max;
};
/** Scans all elements of MatrixContainer::Matrix for smallest absolute value.
* \return smallest value of MatrixContainer::Matrix
*/
double MatrixContainer::FindMinValue()
{
double min = Matrix[0][0][0];
for(int i=MatrixCounter+1;i--;)
for(int j=RowCounter[i]+1;j--;)
for(int k=ColumnCounter[i];k--;)
if (fabs(Matrix[i][j][k]) < min)
min = fabs(Matrix[i][j][k]);
if (fabs(min) < MYEPSILON)
min += MYEPSILON;
return min;
};
/** Sets all values in the last of MatrixContainer::Matrix to \a value.
* \param value reset value
* \param skipcolumns skip initial columns
* \return true if successful
*/
bool MatrixContainer::SetLastMatrix(double value, int skipcolumns)
{
for(int j=RowCounter[MatrixCounter]+1;j--;)
for(int k=skipcolumns;k RowCounter[ KeySets.OrderSet[Order][CurrentFragment] ]) {
ELOG(0, "In fragment No. " << KeySets.OrderSet[Order][CurrentFragment] << " current force index " << m << " is greater than " << RowCounter[ KeySets.OrderSet[Order][CurrentFragment] ] << "!");
performCriticalExit();
return false;
}
if (Order == SubOrder) { // equal order is always copy from Energies
for(int l=ColumnCounter[ KeySets.OrderSet[SubOrder][j] ];l--;) // then adds/subtract each column
Matrix[ KeySets.OrderSet[Order][CurrentFragment] ][m][l] += MatrixValues.Matrix[ KeySets.OrderSet[SubOrder][j] ][k][l];
} else {
for(int l=ColumnCounter[ KeySets.OrderSet[SubOrder][j] ];l--;)
Matrix[ KeySets.OrderSet[Order][CurrentFragment] ][m][l] -= Matrix[ KeySets.OrderSet[SubOrder][j] ][k][l];
}
}
//if ((ColumnCounter[ KeySets.OrderSet[SubOrder][j] ]>1) && (RowCounter[0]-1 >= 1))
//LOG(0, "Fragments[ KeySets.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySets.OrderSet[Order][CurrentFragment] << " ][" << RowCounter[0]-1 << "][" << 1 << "] = " << Matrix[ KeySets.OrderSet[Order][CurrentFragment] ][RowCounter[0]-1][1]);
}
} else {
//LOG(0, "Fragment " << KeySets.OrderSet[SubOrder][j] << " is not contained in fragment " << KeySets.OrderSet[Order][CurrentFragment] << ".");
}
}
}
//LOG(0, "Final Fragments[ KeySets.OrderSet[" << Order << "][" << CurrentFragment << "]=" << KeySets.OrderSet[Order][CurrentFragment] << " ][" << KeySets.AtomCounter[0]-1 << "][" << 1 << "] = " << Matrix[ KeySets.OrderSet[Order][CurrentFragment] ][KeySets.AtomCounter[0]-1][1]);
}
return true;
};
/** Writes the summed total fragment terms \f$F_{ij}\f$ to file.
* \param *name inputdir
* \param *prefix prefix before \a EnergySuffix
* \return file was written
*/
bool MatrixContainer::WriteTotalFragments(const std::string name, const std::string prefix)
{
ofstream output;
char *FragmentNumber = NULL;
LOG(1, "STATUS: Writing fragment files.");
for(int i=0;i