From 34ea81b14810bf3b9d14a9072b4e4d640b39a33f Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Sat, 27 Apr 2019 13:42:21 -0600 Subject: [PATCH 01/68] Removed matrix files --- src/libcatnip/matrix.cpp | 946 --------------------------------------- src/libcatnip/matrix.hpp | 100 ----- 2 files changed, 1046 deletions(-) delete mode 100644 src/libcatnip/matrix.cpp delete mode 100644 src/libcatnip/matrix.hpp diff --git a/src/libcatnip/matrix.cpp b/src/libcatnip/matrix.cpp deleted file mode 100644 index b206b70..0000000 --- a/src/libcatnip/matrix.cpp +++ /dev/null @@ -1,946 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "matrix.hpp" - -using namespace std; - -namespace catnip { - -Matrix Matrix_diag(const Matrix &mat) { - - if (mat.get_cols() > 1 && mat.get_rows() > 1) { - throw invalid_argument( - "ERROR Matrix_diag can only create a diagonal " - "matrix from a vector.\n"); - } - - if (mat.get_shel() > 1) { - throw invalid_argument( - "ERROR Matrix_diag cannot create diagonal matrix " - "from a 3d matrix, it must be passed a vector.\n"); - } - - if (mat.get_cols() > mat.get_rows()) { - int len = mat.get_cols(); - Matrix mat2(len, len); - for (int i = 1; i <= len; i++) { - double val = mat.get_elem(1, i); - mat2.set_elem(val, i, i); - } - return mat2; - } else { - int len = mat.get_rows(); - Matrix mat2(len, len); - for (int i = 1; i <= len; i++) { - double val = mat.get_elem(i, 1); - mat2.set_elem(val, i, i); - } - return mat2; - } -} - -Matrix Matrix_copy(const Matrix &mat) { - - Matrix mat2(mat.get_rows(), mat.get_cols(), mat.get_shel()); - - int i; - int j; - int k; - double val; - - for (i = 1; i <= mat.get_rows(); i++) { - for (j = 1; j <= mat.get_cols(); j++) { - for (k = 1; k <= mat.get_shel(); k++) { - val = mat.get_elem(i, j, k); - mat2.set_elem(val, i, j, k); - } - } - } - - return mat2; -} - -Matrix Matrix_concatenate_rows(Matrix mat1,const Matrix & mat2) { - - // For this function to work both mat1 and mat2 must have - // the same number of columns and shelves - - if (mat1.get_cols() != mat2.get_cols()) { - std::cerr << "ERROR to concatenate the rows mat1 and mat2 must\n"; - std::cerr << " have the same number of cols!\n"; - Matrix m; - return m; - } - - if (mat1.get_shel() != mat2.get_shel()) { - std::cerr << "ERROR to concatenate the rows mat1 and mat2 must\n"; - std::cerr << " have the same number of shelves!\n"; - Matrix m; - return m; - } - - int totalrows; - int rowsMat1 = mat1.get_rows(); - totalrows = rowsMat1 + mat2.get_rows(); - Matrix mat3(totalrows, mat1.get_cols(), mat1.get_shel()); - - int i; - int j; - int k; - double val; - - for (i = 1; i <= mat1.get_rows(); i++) { - for (j = 1; j <= mat1.get_cols(); j++) { - for (k = 1; k <= mat1.get_shel(); k++) { - val = mat1.get_elem(i, j, k); - mat3.set_elem(val, i, j, k); - } - } - } - - for (i = 1; i <= mat2.get_rows(); i++) { - for (j = 1; j <= mat2.get_cols(); j++) { - for (k = 1; k <= mat2.get_shel(); k++) { - val = mat2.get_elem(i, j, k); - mat3.set_elem(val, i + rowsMat1, j, k); - } - } - } - - return mat3; -} - -Matrix Matrix_concatenate_cols(const Matrix &mat1, const Matrix &mat2) { - - // For this function to work both mat1 and mat2 must have - // the same number of columns and shelves - - if (mat1.get_rows() != mat2.get_rows()) { - std::cerr << "ERROR to concatenate the cols mat1 and mat2 must\n"; - std::cerr << " have the same number of rows!\n"; - Matrix m; - return m; - } - - if (mat1.get_shel() != mat2.get_shel()) { - std::cerr << "ERROR to concatenate the rows mat1 and mat2 must\n"; - std::cerr << " have the same number of shelves!\n"; - Matrix m; - return m; - } - - int totalcols; - int colsMat1 = mat1.get_cols(); - totalcols = colsMat1 + mat2.get_cols(); - Matrix mat3(mat1.get_rows(), totalcols, mat1.get_shel()); - - int i; - int j; - int k; - double val; - - for (i = 1; i <= mat1.get_rows(); i++) { - for (j = 1; j <= mat1.get_cols(); j++) { - for (k = 1; k <= mat1.get_shel(); k++) { - val = mat1.get_elem(i, j, k); - mat3.set_elem(val, i, j, k); - } - } - } - - for (i = 1; i <= mat2.get_rows(); i++) { - for (j = 1; j <= mat2.get_cols(); j++) { - for (k = 1; k <= mat2.get_shel(); k++) { - val = mat2.get_elem(i, j, k); - mat3.set_elem(val, i, j + colsMat1, k); - } - } - } - - return mat3; -} - -string double_tos(double f, int nd) { - ostringstream ostr; - int tens = stod("1" + string(nd, '0')); - ostr << round(f * tens) / tens; - return ostr.str(); -} - -std::ostream &operator<<(std::ostream &out, Matrix &mat) { - out << "Matrix Attributes\n"; - out << "rows " << mat.get_rows(); - out << "\ncols " << mat.get_cols(); - out << "\nshel " << mat.get_shel(); - int i; - int j; - int k; - for (k = 1; k <= mat.get_shel(); k++) { - out << "\nShelf " << k << "\n\t"; - - for (j = 1; j <= mat.get_cols(); j++) { - out << "Col " << j << "\t"; - } - out << "\n"; - for (i = 1; i <= mat.get_rows(); i++) { - out << "Row " << i << "\t"; - for (j = 1; j <= mat.get_cols(); j++) { - out << mat.get_elem(i, j) << "\t"; - } - out << "\n"; - } - } - return out; -} - -Matrix &operator*(const Matrix &mat1, const Matrix &mat2) { - - if (mat1.get_shel() != 1 || mat2.get_shel() != 1) { - printf( - "ERROR Matrix_Multiply only allowed for 2d nxm matrix not 3d nxmxl\n"); - exit(1); - } - if (mat1.get_cols() != mat2.get_rows()) { - printf("ERROR Matrix_Multiply only allowed for nxm by lxn matrices\n"); - printf(" second matrix must have same number of colums as first\n"); - printf(" matrix has number of rows\n"); - exit(1); - } - - Matrix *mat3 = new Matrix(mat1.get_rows(), mat2.get_cols()); - - int i; - int j; - int k; - double sum; - - for (i = 1; i <= mat1.get_rows(); i++) { - for (j = 1; j <= mat2.get_cols(); j++) { - sum = 0; - for (k = 1; k <= mat1.get_cols(); k++) { - sum += (mat1.get_elem(i, k)) * (mat2.get_elem(k, j)); - } - (*mat3).set_elem(sum, i, j); - } - } - return *mat3; -} - -} // namespace catnip - -using namespace catnip; - -Matrix::Matrix() { - rows = 1; - cols = 1; - shel = 1; - elem = new double[rows * cols]; - elem[0] = 0; -} - -Matrix::Matrix(vector v_data) { - rows = v_data.size(); - cols = 1; - shel = 1; - elem = new double[rows * cols]; - - int r = 1; - int c = 1; - for (auto val : v_data) { - elem[(r - 1) * cols + c - 1] = val; - ++r; - } -} - -Matrix::Matrix(vector v_data) { - rows = v_data.size(); - cols = 1; - shel = 1; - elem = new double[rows * cols]; - - int r = 1; - int c = 1; - for (auto val : v_data) { - elem[(r - 1) * cols + c - 1] = static_cast(val); - ++r; - } -} - -Matrix::Matrix(vector> vv_data) { - rows = vv_data.size(); - cols = vv_data.at(0).size(); - shel = 1; - elem = new double[rows * cols]; - elem = new double[rows * cols]; - - int r = 1; - for (auto v : vv_data) { - int c = 1; - if (static_cast(v.size()) != cols) { - throw invalid_argument( - "vector> not consistent " - "in matrix constructor "); - } - for (auto val : v) { - elem[(r - 1) * cols + c - 1] = val; - ++c; - } - ++r; - } -} - -Matrix::Matrix(const int r) { - if (r < 0) { - cerr << "ERROR rows of matrix must be greater than or equal to 0" << endl; - cerr << " you have r " << r << endl; - exit(1); - } - if (r == 0) { - rows = 0; - cols = 0; - shel = 0; - elem = nullptr; - } else { - rows = r; - cols = 1; - shel = 1; - - elem = new double[rows]; - for (int i = 1; i <= rows; i++) { - elem[i - 1] = 0; - } - } -} - -Matrix::Matrix(const int r, const int c) { - if (r < 1) { - printf("ERROR negative number of rows submitted to Matrix\n"); - exit(1); - } else if (c < 1) { - printf("ERROR negative number of cols submitted to Matrix\n"); - exit(1); - } - rows = r; - cols = c; - shel = 1; - elem = new double[rows * cols]; - for (int i = 1; i <= rows; i++) { - for (int j = 1; j <= cols; j++) { - elem[(i - 1) * cols + j - 1] = 0; - } - } -} - -Matrix::Matrix(const int r, const int c, const int s) { - if (r < 1) { - printf("ERROR negative number of rows submitted to Matrix\n"); - exit(1); - } else if (c < 1) { - printf("ERROR negative number of cols submitted to Matrix\n"); - exit(1); - } else if (s < 1) { - printf("ERROR negative number of shelves submitted to Matrix\n"); - exit(1); - } - rows = r; - cols = c; - shel = s; - elem = new double[rows * cols * shel]; - for (int i = 1; i <= rows; i++) { - for (int j = 1; j <= cols; j++) { - for (int k = 1; k <= shel; k++) { - elem[(i - 1) * cols * shel + (j - 1) * shel + k - 1] = 0; - } - } - } -} - -int Matrix::resize(int r, int c) { - - if (r < 1) { - printf("ERROR must resize row to a value of 1 or greater\n"); - exit(1); - } - if (c < 1) { - printf("ERROR must resize column to a value of 1 or greater\n"); - exit(1); - } - - double *temp; - temp = new double[r * c]; - - // adding values from old matrix to new - if (r <= rows) { - for (int i = 1; i <= r; i++) { - if (c <= cols) { - for (int j = 1; j <= c; j++) { - temp[(i - 1) * c * 1 + (j - 1) * 1 + 1 - 1] = elem[index(i, j, 1)]; - } - } else { - for (int j = 1; j <= c; j++) { - if (j <= cols) { - temp[(i - 1) * c * 1 + (j - 1) * 1 + 1 - 1] = elem[index(i, j, 1)]; - } else { - temp[(i - 1) * c * 1 + (j - 1) * 1 + 1 - 1] = 0; - } - } - } - } - } else { - for (int i = 1; i <= r; i++) { - if (c <= cols) { - for (int j = 1; j <= c; j++) { - if (i <= rows) { - temp[(i - 1) * c * 1 + (j - 1) * 1 + 1 - 1] = elem[index(i, j, 1)]; - } else { - temp[(i - 1) * c * 1 + (j - 1) * 1 + 1 - 1] = 0; - } - } - } else { - for (int j = 1; j <= c; j++) { - if (i <= rows && j <= cols) { - temp[(i - 1) * c * 1 + (j - 1) * 1 + 1 - 1] = elem[index(i, j, 1)]; - } else { - temp[(i - 1) * c * 1 + (j - 1) * 1 + 1 - 1] = 0; - } - } - } - } - } - - delete elem; - rows = r; - cols = c; - shel = 1; - elem = temp; - - return 0; -} - -Matrix &Matrix::operator=(const Matrix &m) { - this->resize(m.get_rows(), m.get_cols()); - - for (int i = 1; i <= m.get_rows(); ++i) { - for (int j = 1; j <= m.get_cols(); ++j) { - this->set_elem(m.get_elem(i, j), i, j); - } - } - return *this; -} - -int Matrix::index(const int r, const int c, const int s) const { - return (r - 1) * cols * shel + (c - 1) * shel + s - 1; -} - -void Matrix::set_row(vector row, int r) { - - if (get_cols() != static_cast(row.size())) { - throw invalid_argument("vector is not the same size as matrix"); - } - - for (int j = 1; j <= get_cols(); j++) { - if (r <= rows) { - elem[index(r, j, 1)] = row.at(j - 1); - } else { - elem[index(r, j, 1)] = 0; - } - } -} - -void Matrix::set_col(vector col, int c) { - - if (get_cols() != static_cast(col.size())) { - throw invalid_argument("vector is not the same size as matrix"); - } - for (int i = 1; i <= get_rows(); ++i) { - if (c <= cols) { - elem[index(i, c, 1)] = col.at(i - 1); - } else { - elem[index(i, c, 1)] = 0; - } - } -} - -void Matrix::set_rows(int r) { - if (r < 0) { - printf("ERROR negative number submitted to set_rows\n"); - exit(1); - } - if (r > rows) { - - double *temp = new double[r * cols * shel]; - for (int i = 1; i <= r; i++) { - for (int j = 1; j <= cols; j++) { - for (int k = 1; k <= shel; k++) { - if (r <= rows) { - temp[index(i, j, k)] = elem[index(i, j, k)]; - } else { - temp[index(i, j, k)] = 0; - } - } - } - } - delete elem; - rows = r; - elem = temp; - } else if (r < rows) { - - double *temp = new double[r * cols * shel]; - printf("WARNING reducing matrix rows below previous value\n"); - printf("could lose data in the process\n"); - for (int i = 1; i <= r; i++) { - for (int j = 1; j <= cols; j++) { - for (int k = 1; k <= shel; k++) { - temp[index(i, j, k)] = elem[index(i, j, k)]; - } - } - } - delete elem; - rows = r; - elem = temp; - } -} - -vector Matrix::get_col(int c) const{ - vector col_data; - for (int i = 1; i <= rows; i++) { - col_data.push_back(elem[index(i, c, 1)]); - } - return col_data; -} - -vector Matrix::get_row(int r) const { - vector row_data; - for (int i = 1; i <= cols; i++) { - row_data.push_back(elem[index(r, i, 1)]); - } - return row_data; -} - -void Matrix::set_cols(int c) { - if (c < 0) { - printf("ERROR negative number submitted to set_cols\n"); - exit(1); - } - - if (c > cols) { - - double *temp = new double[rows * c * shel]; - for (int i = 1; i <= rows; i++) { - for (int j = 1; j <= c; j++) { - for (int k = 1; k <= shel; k++) { - if (c <= cols) { - temp[index(i, j, k)] = elem[index(i, j, k)]; - } else { - temp[index(i, j, k)] = 0; - } - } - } - } - delete elem; - cols = c; - elem = temp; - } else if (c < cols) { - - double *temp = new double[rows * c * shel]; - printf("WARNING reducing matrix cols below previous value\n"); - printf("could lose data in the process\n"); - for (int i = 1; i <= rows; i++) { - for (int j = 1; j <= c; j++) { - for (int k = 1; k <= shel; k++) { - temp[index(i, j, k)] = elem[index(i, j, k)]; - } - } - } - delete elem; - cols = c; - elem = temp; - } -} - -void Matrix::set_shel(int s) { - if (s < 0) { - printf("ERROR negative number submitted to set_shel\n"); - exit(1); - } - if (s > shel) { - - double *temp = new double[rows * cols * s]; - for (int i = 1; i <= rows; i++) { - for (int j = 1; j <= cols; j++) { - for (int k = 1; k <= s; k++) { - if (s <= shel) { - temp[index(i, j, k)] = elem[index(i, j, k)]; - } else { - temp[index(i, j, k)] = 0; - } - } - } - } - delete elem; - shel = s; - elem = temp; - } else if (s < shel) { - - double *temp = new double[rows * cols * s]; - printf("WARNING reducing matrix shel below previous value\n"); - printf("could lose data in the process\n"); - for (int i = 1; i <= rows; i++) { - for (int j = 1; j <= cols; j++) { - for (int k = 1; k <= s; k++) { - temp[index(i, j, k)] = elem[index(i, j, k)]; - } - } - } - delete elem; - shel = s; - elem = temp; - } -} - -void Matrix::set_elem(double val) { elem[0] = val; } - -void Matrix::set_elem(double val, int r) { - if (r > rows) { - printf( - "ERROR r value is greater than rows in set_elem(double val, int r)\n"); - exit(1); - } else if (r < 1) { - printf( - "ERROR r value is less than or equal to 0 in set_elem(double val, int " - "r)\n"); - exit(1); - }; - - elem[index(r, 1, 1)] = val; -} - -void Matrix::set_elem(double val, int r, int c) { - if (r > rows) { - printf( - "ERROR r value is greater than rows in set_elem(double val, int r, int " - "c)\n"); - exit(1); - } else if (r < 1) { - printf( - "ERROR r value is less than or equal to 0 in set_elem(double val, int " - "r, int c)\n"); - exit(1); - }; - if (c > cols) { - printf( - "ERROR c value is greater than rows in set_elem(double val, int r, int " - "c)\n"); - exit(1); - } else if (c < 1) { - printf( - "ERROR c value is less than or equal to 0 in set_elem(double val, int " - "r, int c)\n"); - exit(1); - }; - - elem[index(r, c, 1)] = val; -} - -void Matrix::set_elem(double val, int r, int c, int s) { - if (r > rows) { - printf( - "ERROR r value is greater than rows in set_elem(double val, int r, int " - "c, int s)\n"); - exit(1); - } else if (r < 1) { - printf( - "ERROR r value is less than or equal to 0 in set_elem(double val, int " - "r, int c, int s)\n"); - exit(1); - }; - if (c > cols) { - printf( - "ERROR c value is greater than rows in set_elem(double val, int r, int " - "c, int s)\n"); - exit(1); - } else if (c < 1) { - printf( - "ERROR c value is less than or equal to 0 in set_elem(double val, int " - "r, int c, int s)\n"); - exit(1); - }; - if (s > shel) { - printf( - "ERROR s value is greater than rows in set_elem(double val, int r, int " - "c, int s)\n"); - exit(1); - } else if (s < 1) { - printf( - "ERROR s value is less than or equal to 0 in set_elem(double val, int " - "r, int c, int s)\n"); - exit(1); - }; - - elem[index(r, c, s)] = val; -} - -int Matrix::get_rows() const { return rows; } - -int Matrix::get_cols() const { return cols; } - -int Matrix::get_shel() const { return shel; } - -int Matrix::total_elem() { return rows * cols * shel; } - -double Matrix::get_elem() const { return elem[0]; } - -double Matrix::get_elem(const int r) const { - if (r < 1) { - printf("ERROR get_elem(int r): 0 or negative row submitted\n"); - exit(1); - } else if (r > rows) { - printf( - "ERROR get_elem(int r): row value larger than the scope of the " - "Matrix\n"); - exit(1); - } - return elem[index(r, 1, 1)]; -} - -double Matrix::get_elem(const int r, const int c) const { - if (r < 1) { - printf("ERROR get_elem(int r, int c): 0 or negative row submitted\n"); - exit(1); - } else if (r > rows) { - printf( - "ERROR get_elem(int r, int c): row value larger than the scope of the " - "Matrix\n"); - exit(1); - } else if (c < 1) { - printf("ERROR get_elem(int r, int c): 0 or negative col submitted\n"); - exit(1); - } else if (c > cols) { - printf( - "ERROR get_elem(int r, int c): col value larger than the scope of the " - "Matrix\n"); - exit(1); - } - return elem[index(r, c, 1)]; -} - -double *Matrix::get_elem_ptr(const int r, const int c) const { - return &elem[index(r, c, 1)]; -} - -double Matrix::get_elem(const int r, const int c, const int s) const { - if (r < 1) { - printf( - "ERROR get_elem(int r, int c, int s): 0 or negative row submitted\n"); - exit(1); - } else if (r > rows) { - printf( - "ERROR get_elem(int r, int c, int s): row value larger than the scope " - "of the Matrix\n"); - exit(1); - } else if (c < 1) { - printf( - "ERROR get_elem(int r, int c, int s): 0 or negative col submitted\n"); - exit(1); - } else if (c > cols) { - printf( - "ERROR get_elem(int r, int c, int s): col value larger than the scope " - "of the Matrix\n"); - exit(1); - } else if (s < 1) { - printf( - "ERROR get_elem(int r, int c, int s): 0 or negative shelf submitted\n"); - exit(1); - } else if (s > shel) { - printf( - "ERROR get_elem(int r, int c, int s): shelf value larger than the " - "scope of the Matrix\n"); - exit(1); - } - return elem[index(r, c, s)]; -} - -void Matrix::swap_row(int r_from, int r_to) { - if (r_from == r_to) return; - - vector row_f = get_row(r_from); - vector row_t = get_row(r_to); - set_row(row_f, r_to); - set_row(row_t, r_from); -} - -void Matrix::swap_col(int c_from, int c_to) { - if (c_from == c_to) return; - - vector col_f = get_col(c_from); - vector col_t = get_col(c_to); - set_col(col_f, c_to); - set_col(col_t, c_from); -} - -void Matrix::move_row(int r_from, int r_to) { - - if (r_from == r_to) return; - - // Shift all rows down - vector row = get_row(r_from); - // Shift all values down - if (r_from < r_to) { - for (int r = r_from; r < r_to; r++) { - for (int c = 1; c <= get_cols(); c++) { - set_elem(get_elem(r + 1, c), r, c); - } - } - } else { - for (int r = r_from; r >= (r_to + 1); r--) { - for (int c = 1; c <= get_cols(); c++) { - set_elem(get_elem(r - 1, c), r, c); - } - } - } - // Insert the row we took out - this->set_row(row, r_to); -} - -void Matrix::move_col(int c_from, int c_to) { - - if (c_from == c_to) return; - - // Shift all rows down - vector col = get_col(c_from); - // Shift all values down - if (c_from < c_to) { - for (int c = c_from; c < c_to; c++) { - for (int r = 1; r <= get_rows(); r++) { - set_elem(get_elem(r, c + 1), r, c); - } - } - } else { - for (int c = c_from; c >= (c_to + 1); c--) { - for (int r = 1; r <= get_rows(); r++) { - set_elem(get_elem(r, c - 1), r, c); - } - } - } - // Insert the row we took out - set_col(col, c_to); -} - -vector Matrix::matchRow(const Matrix & mat, int sf) { - if (mat.get_shel() != 1 || this->get_shel() != 1) { - cerr << "ERROR shel should be 1" << endl; - exit(1); - } - if (mat.get_cols() != this->get_cols()) { - throw invalid_argument( - "match function only works when matrices have same number of columns"); - } - vector m_vec(this->get_rows(), -1); - - for (int i = 1; i <= get_rows(); ++i) { - for (int ii = 1; ii <= mat.get_rows(); ++ii) { - bool match = true; - for (int j = 1; j <= get_cols(); ++j) { - string val1 = double_tos(get_elem(i, j), sf); - string val2 = double_tos(mat.get_elem(ii, j), sf); - if (val1.compare(val2) != 0) { - match = false; - break; - } - } - if (match) m_vec.at(i - 1) = ii; - } - } - return m_vec; -} - -vector Matrix::matchCol(const Matrix &mat, const int sf) const { - if (mat.get_shel() != 1 || this->get_shel() != 1) { - cerr << "ERROR shel should be 1" << endl; - exit(1); - } - if (mat.get_rows() != this->get_rows()) { - throw invalid_argument( - "match function only works when matrices have same number of rows"); - } - vector m_vec(this->get_cols(), -1); - - for (int i = 1; i <= get_cols(); ++i) { - for (int ii = 1; ii <= mat.get_cols(); ++ii) { - bool match = true; - for (int j = 1; j <= get_rows(); ++j) { - string val1 = double_tos(get_elem(j, i), sf); - string val2 = double_tos(mat.get_elem(j, ii), sf); - if (val1.compare(val2) != 0) { - match = false; - break; - } - } - if (match) m_vec.at(i - 1) = ii; - } - } - return m_vec; -} - -Matrix Matrix::invert() const{ - - if (this->get_shel() != 1) { - printf("ERROR Matrix_Invert only allowed for 1d and 2d arrays not 3d\n"); - exit(1); - } - - Matrix *mat2 = new Matrix(this->get_cols(), this->get_rows()); - - for (int i = 1; i <= this->get_rows(); i++) { - for (int j = 1; j <= this->get_cols(); j++) { - double val = this->get_elem(i, j); - (*mat2).set_elem(val, j, i); - } - } - return *mat2; -} - -Matrix Matrix::getRow(int R) const{ - - if (this->get_rows() < R) { - printf("ERROR Matrix_getRow cannot return R %d", R); - printf(" because mat has only %d rows\n.", this->get_rows()); - exit(1); - } - - Matrix mat2(1, this->get_cols(), this->get_shel()); - - for (int j = 1; j <= this->get_cols(); j++) { - for (int k = 1; k <= this->get_shel(); k++) { - double val = this->get_elem(R, j, k); - mat2.set_elem(val, 1, j, k); - } - } - return mat2; -} - -Matrix Matrix::getCol(int C) const { - - if (this->get_cols() < C) { - printf("ERROR Matrix_getCol cannot return C %d", C); - printf(" because mat has only %d cols\n.", this->get_cols()); - exit(1); - } - Matrix mat2(this->get_cols(), 1, this->get_shel()); - - for (int i = 1; i <= this->get_rows(); i++) { - for (int k = 1; k <= this->get_shel(); k++) { - double val = this->get_elem(i, C, k); - mat2.set_elem(val, i, 1, k); - } - } - return mat2; -} diff --git a/src/libcatnip/matrix.hpp b/src/libcatnip/matrix.hpp deleted file mode 100644 index cce1c3e..0000000 --- a/src/libcatnip/matrix.hpp +++ /dev/null @@ -1,100 +0,0 @@ -#ifndef _CATNIP_Matrix_HPP -#define _CATNIP_Matrix_HPP -#include -#include -#include - -namespace catnip { - -class Matrix { - private: - int rows; - int cols; - int shel; - double *elem; - - public: - // constructors - explicit Matrix(void); - explicit Matrix(std::vector); - explicit Matrix(std::vector); - explicit Matrix(std::vector>); - explicit Matrix(const int r); - Matrix(const int r, const int c); - Matrix(const int r, const int c, const int s); - - Matrix &operator=(const Matrix &m); - // manipulators - void set_rows(int r); - void set_cols(int c); - void set_shel(int s); - void set_row(std::vector row, int r); - void set_col(std::vector col, int c); - int resize(int r, int c); - void set_elem(double val); - void set_elem(double val, int r); - void set_elem(double val, int r, int c); - void set_elem(double val, int r, int c, int s); - // accessors - int index(const int r, const int c, const int s) const; - int get_rows() const; - int get_cols() const; - int get_shel() const; - int total_elem(); - double get_elem() const; - double get_elem(const int r) const; - double get_elem(const int r, const int c) const; - double get_elem(const int r, const int c, const int s) const; - double *get_elem_ptr(const int r, const int c) const; - std::vector get_col(int c) const; - std::vector get_row(int r) const; - - // WARNING This is not a swap row operation - // All rows are shifted to make way - // for the new row/col. 'r_from' is moved to 'r_to' while - // all rows are appropriately shifted to make this happen. - void move_row(int r_from, int r_to); - void move_col(int c_from, int c_to); - - // The intial and final row/col simply change places - // none of the rows and cols other than the ones swapped - // are affected - void swap_row(int r_from, int r_to); - void swap_col(int c_from, int c_to); - - Matrix getCol(int c) const; - Matrix getRow(int r) const; - // Basically switches the rows and columns - Matrix invert(void) const; - // Responsible for matching the rows between two matrices they do not need - // Returns which row in the current matrix matches which row in the one - // passed in, -1 means there is no match - // sf is the number of significant figures that will be checked to ensure - // the same value - std::vector matchRow(const Matrix & mat, int sf); - std::vector matchCol(const Matrix &mat, const int sf) const; -}; - -std::ostream &operator<<(std::ostream &out, Matrix &mat); - -Matrix &operator*(const Matrix &mat1, const Matrix &mat2); - -// Takes a vector and diagonalized the -// vector in a 2 dimensional matrix where -// everything but the diagonal is assigned -// a 0 -Matrix Matrix_diag(const Matrix &mat); - -// Copies a matrix and returns the new -// matrix -Matrix Matrix_copy(const Matrix &mat); - -// Add two matrices together to create a third -// mat1 will always appear above mat2 in the rows -// of the matrix that is returned. -Matrix Matrix_concatenate_rows(Matrix mat1,const Matrix & mat2); -Matrix Matrix_concatenate_cols(const Matrix &mat1, const Matrix &mat2); - -} // namespace catnip - -#endif // _CATNIP_Matrix_HPP From e7f15641ab8473ebd5ac0dc8a7e258e95b3b46a6 Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Sat, 27 Apr 2019 13:42:47 -0600 Subject: [PATCH 02/68] Switched file readers to using eigen matrices as opposed to local matrix type --- src/libcatnip/io/file_readers/logreader.cpp | 46 +++++++++++++-------- src/libcatnip/io/file_readers/logreader.hpp | 9 ++-- src/libcatnip/io/file_readers/punreader.cpp | 17 ++++++-- src/libcatnip/io/file_readers/punreader.hpp | 8 ++-- 4 files changed, 53 insertions(+), 27 deletions(-) diff --git a/src/libcatnip/io/file_readers/logreader.cpp b/src/libcatnip/io/file_readers/logreader.cpp index f55ffdf..b3624be 100644 --- a/src/libcatnip/io/file_readers/logreader.cpp +++ b/src/libcatnip/io/file_readers/logreader.cpp @@ -7,6 +7,7 @@ #include #include +#include #include "../../log.hpp" #include "../../string_support.hpp" #include "logreader.hpp" @@ -164,18 +165,25 @@ void LogReader::OverlapSectionReader(void *ptr) { } // Create a matrix and place all the current values in there - Matrix *mat_S = new Matrix(countCoef, countCoef); + + //Matrix *mat_S = new Matrix(countCoef, countCoef); + Eigen::MatrixXd matrix_S(countCoef,countCoef); for (size_t row_ind = 0; row_ind < first_coefs.size(); ++row_ind) { - vector row = first_coefs.at(row_ind); - size_t col_ind = 1; - for (auto val : row) { - mat_S->set_elem(val, row_ind + 1, col_ind); +// vector row = first_coefs.at(row_ind); + matrix_S.row(row_ind) << first_coefs.at(row_ind); + // size_t col_ind = 1; +// size_t col_ind = 0; + // for (double & val : row) { + // mat_S->set_elem(val, row_ind + 1, col_ind); + // matrix_S(row_ind,col_ind) = val; // Because diagonally symetric - if (row_ind + 1 != col_ind) { - mat_S->set_elem(val, col_ind, row_ind + 1); - } - ++col_ind; - } +// if (row_ind + 1 != col_ind) { + // if (row_ind != col_ind) { + //mat_S->set_elem(val, col_ind, row_ind + 1); + // matrix_S(col_ind,row_ind) = val; + // } + // ++col_ind; + //} } int sectionReads = countCoef / 5; @@ -193,19 +201,23 @@ void LogReader::OverlapSectionReader(void *ptr) { istringstream iss(line); string dummy; iss >> dummy; - int localCoefCount = 1; + //int localCoefCount = 1; + int localCoefCount = 0; while (!iss.eof()) { string s_coef; iss >> s_coef; string val = grabStrBeforeFirstOccurance(s_coef, "D"); string expon = grabStrAfterFirstOccurance(s_coef, "D"); double value = stod(val) * pow(10.0, stod(expon)); - mat_S->set_elem(value, sectionCoef + 1, - currentSectionStart + localCoefCount); - if ((sectionCoef + 1) != (currentSectionStart + localCoefCount)) { - - mat_S->set_elem(value, currentSectionStart + localCoefCount, - sectionCoef + 1); + + //mat_S->set_elem(value, sectionCoef + 1, + // currentSectionStart + localCoefCount); + matrix_S(sectionCoef,currentSectionStart + localCoefCount) = value; + //if ((sectionCoef + 1) != (currentSectionStart + localCoefCount)) { + if ((sectionCoef) != (currentSectionStart + localCoefCount)) { + matrix_S(currentSectionStart + localCoefCount,sectionCoef) = value; + //mat_S->set_elem(value, currentSectionStart + localCoefCount, + // sectionCoef + 1); } ++localCoefCount; } diff --git a/src/libcatnip/io/file_readers/logreader.hpp b/src/libcatnip/io/file_readers/logreader.hpp index 46cde5d..4583ed3 100644 --- a/src/libcatnip/io/file_readers/logreader.hpp +++ b/src/libcatnip/io/file_readers/logreader.hpp @@ -4,8 +4,10 @@ #include -#include "../../matrix.hpp" +//#include "../../matrix.hpp" #include "filereader.hpp" + +#include // Gaussian log file reader namespace catnip { @@ -18,7 +20,7 @@ class LogReader : public FileReader { public: explicit LogReader(const std::string &str); orb_cont getOrbitalInfo() const { return orb_; } - Matrix *getOverlapMatrix() const { return S_; } + Eigen::MatrixXd getOverlapMatrix() const { return S_; } std::vector getOE(const std::string &orb_type) const { return OREnergies.at(orb_type); } @@ -48,7 +50,8 @@ class LogReader : public FileReader { std::map homoLevel; orb_cont orb_; // Overlap matrix - Matrix *S_; + //Matrix *S_; + Eigen::MatrixXd S_; std::map> OREnergies; std::vector> xyz; diff --git a/src/libcatnip/io/file_readers/punreader.cpp b/src/libcatnip/io/file_readers/punreader.cpp index 0b5a92c..669693b 100644 --- a/src/libcatnip/io/file_readers/punreader.cpp +++ b/src/libcatnip/io/file_readers/punreader.cpp @@ -11,6 +11,8 @@ #include "../../string_support.hpp" #include "punreader.hpp" +#include + using namespace catnip; using namespace std; @@ -29,12 +31,12 @@ void PunReader::registerSections_() { FileReader::registerSections_(); } -Matrix *PunReader::getCoefsMatrix(const string &orb_type) { +MatrixXd PunReader::getCoefsMatrix(const string &orb_type) { if (coefs.count(orb_type) != 1) { throw invalid_argument("Coefficients for spin " + orb_type + " were not found"); } - return coefs[orb_type]; + return *(coefs[orb_type]); } void PunReader::validFileName_() { @@ -93,8 +95,15 @@ void PunReader::ReadCoef(const string &orb_type) { allCoefsRead = !(foundSubStrInStr(line, orb_type)); } - Matrix *Coefs = new Matrix(v_vec); - coefs[orb_type] = Coefs; + //Matrix *Coefs = new Matrix(v_vec); + coefs[orb_type] = unique_ptr(Eigen::MatrixXd Coefs(v_vec.size(),v_vec.at(0).size())); + + size_t row_count = 0; + for( vector & row : v_vec) { + coefs[orb_type]->row(row_count) = row; + ++row_count; + } + //coefs[orb_type] = Coefs; LOG("Success reading atomic orbital coefficients from .pun file.", 2); } diff --git a/src/libcatnip/io/file_readers/punreader.hpp b/src/libcatnip/io/file_readers/punreader.hpp index 73f8846..2bc4b0b 100644 --- a/src/libcatnip/io/file_readers/punreader.hpp +++ b/src/libcatnip/io/file_readers/punreader.hpp @@ -2,17 +2,19 @@ #ifndef _CATNIP_PUNREADER_HPP_ #define _CATNIP_PUNREADER_HPP_ +#include #include -#include "../../matrix.hpp" +//#include "../../matrix.hpp" #include "filereader.hpp" +#include // Gaussian fort.7/.pun file reader namespace catnip { class PunReader : public FileReader { public: explicit PunReader(const std::string &str); - Matrix *getCoefsMatrix(const std::string &orb_type); + Eigen::MatrixXd getCoefsMatrix(const std::string &orb_type); bool restrictedShell() { return coefs.size() == 1; } private: @@ -25,7 +27,7 @@ class PunReader : public FileReader { void ReadCoef(const std::string &orb_type); std::vector readGausCoefLine(const std::string &line); - std::map coefs; + std::map> coefs; }; } // namespace catnip From 094177e9c27ce07cce8604f57437d36d801e9d07 Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Sat, 27 Apr 2019 13:54:31 -0600 Subject: [PATCH 03/68] Switched to eigen matrices in main --- src/tools/main.cpp | 50 +++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/src/tools/main.cpp b/src/tools/main.cpp index be9d395..0455c80 100644 --- a/src/tools/main.cpp +++ b/src/tools/main.cpp @@ -17,12 +17,14 @@ #include "../libcatnip/io/file_readers/punreader.hpp" #include "../libcatnip/io/io.hpp" #include "../libcatnip/log.hpp" -#include "../libcatnip/matrix.hpp" +//#include "../libcatnip/matrix.hpp" #include "../libcatnip/parameters.hpp" #include "../libcatnip/qc_functions.hpp" #include "../libcatnip/calcJconfig.hpp" +#include + using namespace catnip; using namespace std; @@ -77,23 +79,31 @@ int main(int argc, const char *argv[]) { // No need to worry about beta orbitals { - Matrix *mat_S = lr_P.getOverlapMatrix(); + //Matrix *mat_S = lr_P.getOverlapMatrix(); + Eigen::MatrixXd mat_S = lr_P.getOverlapMatrix(); - Matrix *mat_P_Coef = pr_P.getCoefsMatrix(par->getSpinP()); - auto vec_P_OE = lr_P.getOE(par->getSpinP()); - Matrix *mat_P_OE = new Matrix(vec_P_OE); + //Matrix *mat_P_Coef = pr_P.getCoefsMatrix(par->getSpinP()); + Eigen::MatrixXd mat_P_Coef = pr_P.getCoefsMatrix(par->getSpinP()); + + //auto vec_P_OE = lr_P.getOE(par->getSpinP()); + Eigen::MatrixXd mat_P_OE = Eigen::MatrixXd(lr_P.getOE(par->getSpinP())); + //Matrix *mat_P_OE = new Matrix(vec_P_OE); int HOMO1 = lr_1.getHOMOLevel(par->getSpin1()); LOG("Getting " + par->getSpin1() + " of monomer 1", 2); - Matrix *mat_1_Coef = pr_1.getCoefsMatrix(par->getSpin1()); - auto vec_1_OE = lr_1.getOE(par->getSpin1()); - Matrix *mat_1_OE = new Matrix(vec_1_OE); + Eigen::MatrixXd mat_1_Coef = pr_1.getCoefsMatrix(par->getSpin1()); + //Matrix *mat_1_Coef = pr_1.getCoefsMatrix(par->getSpin1()); + //auto vec_1_OE = lr_1.getOE(par->getSpin1()); + //Matrix *mat_1_OE = new Matrix(vec_1_OE); + Eigen::MatrixXd mat_1_OE = Eigen::MatrixXd(vec_1_OE); int HOMO2 = lr_2.getHOMOLevel(par->getSpin2()); LOG("Getting " + par->getSpin2() + " of monomer 2", 2); - Matrix *mat_2_Coef = pr_2.getCoefsMatrix(par->getSpin2()); - auto vec_2_OE = lr_2.getOE(par->getSpin2()); - Matrix *mat_2_OE = new Matrix(vec_2_OE); + //Matrix *mat_2_Coef = pr_2.getCoefsMatrix(par->getSpin2()); + Eigen::MatrixXd mat_2_Coef = pr_2.getCoefsMatrix(par->getSpin2()); + //auto vec_2_OE = lr_2.getOE(par->getSpin2()); + //Matrix *mat_2_OE = new Matrix(vec_2_OE); + Eigen::MatrixXd mat_2_OE = Eigen::MatrixXd(vec_2_OE); // Unscramble dimer coef and energies first need to see how the dimer // and monomer coefficients line up. To determine how the ceofficients @@ -103,18 +113,18 @@ int main(int argc, const char *argv[]) { // the position of the atoms in the monomer unit and the positions of // the atoms in the dimer we can determine how the coefficients need // to be rearranged. - auto coord_P = lr_P.getCoords(); - auto coord_1 = lr_1.getCoords(); - auto coord_2 = lr_2.getCoords(); + vector> coord_P = lr_P.getCoords(); + vector> coord_1 = lr_1.getCoords(); + vector> coord_2 = lr_2.getCoords(); // Convert coords to matrices - Matrix coord_P_mat(coord_P); - Matrix coord_1_mat(coord_1); - Matrix coord_2_mat(coord_2); + MatrixXd coord_P_mat(coord_P); + MatrixXd coord_1_mat(coord_1); + MatrixXd coord_2_mat(coord_2); - auto basis_P = lr_P.getBasisFuncCount(); - auto basis_1 = lr_1.getBasisFuncCount(); - auto basis_2 = lr_2.getBasisFuncCount(); + int basis_P = lr_P.getBasisFuncCount(); + int basis_1 = lr_1.getBasisFuncCount(); + int basis_2 = lr_2.getBasisFuncCount(); int MO1 = mat_1_OE->get_rows(); int MO2 = mat_2_OE->get_rows(); From 47257b00c4f12363b7a763cbecc165099fc7b8d8 Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Sat, 27 Apr 2019 18:21:18 -0600 Subject: [PATCH 04/68] Removed matrix tests --- src/tests/CMakeLists.txt | 1 - src/tests/test_matrix.cpp | 298 -------------------------------------- 2 files changed, 299 deletions(-) delete mode 100644 src/tests/test_matrix.cpp diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 0b88df6..bf8fc4b 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -6,7 +6,6 @@ list( APPEND UNIT_TEST_SOURCE_FILES test_argumentstring test_argumentswitch test_log - test_matrix test_parameters test_propertydouble test_propertyfileexist diff --git a/src/tests/test_matrix.cpp b/src/tests/test_matrix.cpp deleted file mode 100644 index db78067..0000000 --- a/src/tests/test_matrix.cpp +++ /dev/null @@ -1,298 +0,0 @@ -#include "../libcatnip/matrix.hpp" -#include -#include - -using namespace catnip; -using namespace std; - -int main() { - - cout << "Testing Constructors\n" << endl; - - cout << "Testing: Matrix::Matrix()\n" << endl; - { - Matrix mat0; - cout << mat0 << endl; - } - - cout << "Testing: Matrix::Matrix(int r)\n" << endl; - { - Matrix mat1(3); - cout << mat1 << endl; - } - - cout << "Testing: Matrix::Matrix(int r, int c)\n" << endl; - { - Matrix mat2(2, 3); - cout << mat2 << endl; - } - - cout << "Testing: Matrix::Matrix(int r, int c, int s)\n" << endl; - { - Matrix mat3(3, 1, 2); - cout << mat3 << endl; - } - - cout << "Testing: Matrix::Matrix(vector v_data)\n" << endl; - { - vector v = {1.2, 324.4, 23}; - Matrix mat3(v); - } - - cout << "Testing: Matrix::Matrix(vector> vv_data)\n" << endl; - { - vector> vv_data; - vector v = {1.2, 324.4, 23}; - vv_data.push_back(v); - v.at(1) = -12.5; - vv_data.push_back(v); - Matrix mat3(vv_data); - } - - cout << "\nTesting: Matrix::set_rows(int r)\n" << endl; - { - Matrix mat0; - mat0.set_rows(3); - cout << mat0 << endl; - } - - cout << "\nTesting: Matrix::set_cols(int c)\n" << endl; - { - Matrix mat0; - mat0.set_cols(4); - cout << mat0 << endl; - } - - cout << "\nTesting: Matrix::set_shel(int s)\n" << endl; - { - Matrix mat0; - mat0.set_shel(2); - cout << mat0 << endl; - } - - cout << "\nTesting: Matrix::operator=(const Matrix mat)\n" << endl; - { - vector> vv_data; - vector v = {1.2, 324.4, 23}; - vv_data.push_back(v); - v.at(1) = -12.5; - vv_data.push_back(v); - Matrix mat3(vv_data); - Matrix mat1; - mat1 = mat3; - assert(static_cast(mat1.get_elem(1, 1) * 10) == 12); - assert(static_cast(mat1.get_elem(1, 2) * 10) == 3244); - assert(static_cast(mat1.get_elem(1, 3)) == 23); - assert(static_cast(mat1.get_elem(2, 1) * 10) == 12); - assert(static_cast(mat1.get_elem(2, 2) * 10) == -125); - assert(static_cast(mat1.get_elem(2, 3)) == 23); - } - cout << "\nTesting: Matrix::set_elem(double val)\n" << endl; - { - Matrix mat0; - mat0.set_elem(5.4); - cout << mat0 << endl; - } - - cout << "\nTesting: Matrix::set_elem(double val, int r)\n" << endl; - { - Matrix mat0; - mat0.set_rows(3); - mat0.set_elem(4.4, 3); - cout << mat0 << endl; - } - - cout << "\nTesting: Matrix::set_elem(double val, int r, int c)\n" << endl; - { - Matrix mat0; - mat0.set_rows(3); - mat0.set_cols(4); - mat0.set_elem(4.2, 3, 4); - cout << mat0 << endl; - } - - cout << "\nTesting: Matrix::set_elem(double val, int r, int c)\n" << endl; - { - Matrix mat0; - mat0.set_rows(3); - mat0.set_cols(4); - mat0.set_shel(2); - mat0.set_elem(0.3, 3, 4, 2); - cout << mat0 << endl; - } - - { - Matrix mat4(2, 3); - Matrix mat5(3, 2); - - mat4.set_elem(5, 1, 1); - mat4.set_elem(3, 1, 2); - mat4.set_elem(1, 1, 3); - mat4.set_elem(2, 2, 2); - mat4.set_elem(1, 2, 3); - - mat5.set_elem(2, 1, 1); - mat5.set_elem(1, 1, 2); - mat5.set_elem(1, 2, 1); - mat5.set_elem(3, 3, 1); - mat5.set_elem(4, 3, 2); - - cout << mat4 << endl; - cout << mat5 << endl; - - Matrix mat6 = mat4 * mat5; - cout << mat6 << endl; - - cout << "\nResizing matrix 6" << endl; - mat6.resize(3, 3); - cout << mat6 << endl; - } - - cerr << "Testing: matchRow" << endl; - { - Matrix mat4(2, 3); - Matrix mat5(3, 3); - - // mat4 - // 5 3 1 - // 0 2 1 - - mat4.set_elem(5, 1, 1); - mat4.set_elem(3, 1, 2); - mat4.set_elem(1, 1, 3); - mat4.set_elem(2, 2, 2); - mat4.set_elem(1, 2, 3); - - // mat5 - // 2 1 0 - // 1 0 0 - // 5 3 1 - mat5.set_elem(2, 1, 1); - mat5.set_elem(1, 1, 2); - mat5.set_elem(1, 2, 1); - mat5.set_elem(5, 3, 1); - mat5.set_elem(3, 3, 2); - mat5.set_elem(1, 3, 3); - - auto m_vec = mat4.matchRow(mat5, 4); - assert(m_vec.at(0) == 3); - } - - cerr << "Testing: set_row & set_col" << endl; - { - // mat5 - // 2 1 0 - // 1 0 0 - // 5 3 1 - Matrix mat5(3, 3); - mat5.set_elem(2, 1, 1); - mat5.set_elem(1, 1, 2); - mat5.set_elem(0, 1, 3); - mat5.set_elem(1, 2, 1); - mat5.set_elem(0, 2, 2); - mat5.set_elem(0, 2, 3); - mat5.set_elem(5, 3, 1); - mat5.set_elem(3, 3, 2); - mat5.set_elem(1, 3, 3); - - vector values{9, 12, 13}; - mat5.set_row(values, 1); - assert(mat5.get_elem(1, 1) == 9); - assert(mat5.get_elem(1, 2) == 12); - assert(mat5.get_elem(1, 3) == 13); - assert(mat5.get_elem(2, 1) == 1); - assert(mat5.get_elem(2, 2) == 0); - assert(mat5.get_elem(2, 3) == 0); - assert(mat5.get_elem(3, 1) == 5); - assert(mat5.get_elem(3, 2) == 3); - assert(mat5.get_elem(3, 3) == 1); - - vector values2{-12, 23, 101}; - mat5.set_col(values2, 2); - assert(mat5.get_elem(1, 1) == 9); - assert(mat5.get_elem(1, 2) == -12); - assert(mat5.get_elem(1, 3) == 13); - assert(mat5.get_elem(2, 1) == 1); - assert(mat5.get_elem(2, 2) == 23); - assert(mat5.get_elem(2, 3) == 0); - assert(mat5.get_elem(3, 1) == 5); - assert(mat5.get_elem(3, 2) == 101); - assert(mat5.get_elem(3, 3) == 1); - } - - cerr << "Testing: move_row & move_col" << endl; - { - // mat5 - // 2 1 0 - // 1 0 0 - // 5 3 1 - Matrix mat5(3, 3); - mat5.set_elem(2, 1, 1); - mat5.set_elem(1, 1, 2); - mat5.set_elem(0, 1, 3); - mat5.set_elem(1, 2, 1); - mat5.set_elem(0, 2, 2); - mat5.set_elem(0, 2, 3); - mat5.set_elem(5, 3, 1); - mat5.set_elem(3, 3, 2); - mat5.set_elem(1, 3, 3); - - // 5 3 1 - // 2 1 0 - // 1 0 0 - mat5.move_row(3, 1); - assert(mat5.get_elem(1, 1) == 5); - assert(mat5.get_elem(1, 2) == 3); - assert(mat5.get_elem(1, 3) == 1); - assert(mat5.get_elem(2, 1) == 2); - assert(mat5.get_elem(2, 2) == 1); - assert(mat5.get_elem(2, 3) == 0); - assert(mat5.get_elem(3, 1) == 1); - assert(mat5.get_elem(3, 2) == 0); - assert(mat5.get_elem(3, 3) == 0); - - // 1 5 3 - // 0 2 1 - // 0 1 0 - mat5.move_col(3, 1); - cerr << mat5 << endl; - assert(mat5.get_elem(1, 1) == 1); - assert(mat5.get_elem(1, 2) == 5); - assert(mat5.get_elem(1, 3) == 3); - assert(mat5.get_elem(2, 1) == 0); - assert(mat5.get_elem(2, 2) == 2); - assert(mat5.get_elem(2, 3) == 1); - assert(mat5.get_elem(3, 1) == 0); - assert(mat5.get_elem(3, 2) == 1); - assert(mat5.get_elem(3, 3) == 0); - - // 0 2 1 - // 0 1 0 - // 1 5 3 - mat5.move_row(1, 3); - assert(mat5.get_elem(1, 1) == 0); - assert(mat5.get_elem(1, 2) == 2); - assert(mat5.get_elem(1, 3) == 1); - assert(mat5.get_elem(2, 1) == 0); - assert(mat5.get_elem(2, 2) == 1); - assert(mat5.get_elem(2, 3) == 0); - assert(mat5.get_elem(3, 1) == 1); - assert(mat5.get_elem(3, 2) == 5); - assert(mat5.get_elem(3, 3) == 3); - - // 2 1 0 - // 1 0 0 - // 5 3 1 - mat5.move_col(1, 3); - assert(mat5.get_elem(1, 1) == 2); - assert(mat5.get_elem(1, 2) == 1); - assert(mat5.get_elem(1, 3) == 0); - assert(mat5.get_elem(2, 1) == 1); - assert(mat5.get_elem(2, 2) == 0); - assert(mat5.get_elem(2, 3) == 0); - assert(mat5.get_elem(3, 1) == 5); - assert(mat5.get_elem(3, 2) == 3); - assert(mat5.get_elem(3, 3) == 1); - } - return 0; -} From 0ad1283890453be82eb6b4ffd982280c2fb39468 Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Sat, 27 Apr 2019 19:34:23 -0600 Subject: [PATCH 05/68] Updated main and qc_functions to use Eigen matrix and vector classes --- src/libcatnip/qc_functions.cpp | 428 +++++++++++++++++++++------------ src/libcatnip/qc_functions.hpp | 157 ++++++++---- src/tools/main.cpp | 10 +- 3 files changed, 384 insertions(+), 211 deletions(-) diff --git a/src/libcatnip/qc_functions.cpp b/src/libcatnip/qc_functions.cpp index 963c6fd..3cb76b8 100644 --- a/src/libcatnip/qc_functions.cpp +++ b/src/libcatnip/qc_functions.cpp @@ -18,28 +18,33 @@ using namespace std; namespace catnip { -unordered_map> findRank(Matrix &Orb_E_Alpha, - Matrix &Orb_E_Beta) { +unordered_map> findRank(Eigen::VectorXd &Orb_E_Alpha, + Eigen::VectorXd &Orb_E_Beta) { vector> all; - auto m_a = Orb_E_Alpha.getCol(1); + //auto m_a = Orb_E_Alpha.getCol(1); - for (int ind = 1; ind <= m_a.get_rows(); ind++) { + /*for (int ind = 1; ind <= m_a.get_rows(); ind++) { auto val = m_a.get_elem(ind); pair pr(val, "Alpha"); all.push_back(pr); + }*/ + for( double & val : Orb_E_Alpha){ + all.push_back(pair(val,"Alpha")); } - if (Orb_E_Beta.get_cols() > 0) { - auto m_b = Orb_E_Beta.getCol(1); - - for (int ind = 1; ind <= m_b.get_rows(); ind++) { - auto val = m_b.get_elem(ind); - pair pr(val, "Beta"); - all.push_back(pr); + //if (Orb_E_Beta.get_cols() > 0) { + // auto m_b = Orb_E_Beta.getCol(1); + + // for (int ind = 1; ind <= m_b.get_rows(); ind++) { + for( double & val : Orb_E_Beta ){ + //auto val = m_b.get_elem(ind); + //pair pr(val, "Beta"); + //all.push_back(pr); + all.push_back(pair(val, "Beta")); } - } + // } // Sort the vectors sort(all.begin(), all.end(), [](const pair &P1, const pair &P2) @@ -57,45 +62,61 @@ unordered_map> findRank(Matrix &Orb_E_Alpha, } // Essentially calculates the transfer integral -double calculate_transfer_integral(const Matrix & mat_1_Coef, const Matrix & mat_2_Coef, - Matrix mat_P_Coef,const Matrix & mat_S, - const Matrix &mat_P_OE, bool counterPoise_) { +void TransferComplex::calculate_transfer_integral_() { - Matrix mat_1_Coefinv = mat_1_Coef.invert(); - Matrix mat_2_Coefinv = mat_2_Coef.invert(); - Matrix mat_P_Coefinv = mat_P_Coef.invert(); + //Matrix mat_1_Coefinv = mat_1_Coef.invert(); + //Matrix mat_2_Coefinv = mat_2_Coef.invert(); + //Matrix mat_P_Coefinv = mat_P_Coef.invert(); - Matrix zetaA; - Matrix zetaB; + auto dimension = mat_1_Coef.rows()+mat_2_Coef.rows(); + Eigen::MatrixXd zetaA(dimension,dimension); + Eigen::MatrixXd zetaB(dimension,dimension); if (counterPoise_) { LOG("Creating zeta matrices from coefficients assuming counterpoise", 2); - zetaA = (mat_1_Coefinv); - zetaB = (mat_2_Coefinv); + //zetaA = (mat_1_Coefinv); + //zetaB = (mat_2_Coefinv); + zetaA = mat_1_Coef(); + zetaB = mat_2_Coef(); } else { LOG("Creating zeta matrices from coefficients", 2); - Matrix zerosA(mat_1_Coefinv.get_rows(), 1, mat_1_Coefinv.get_shel()); - Matrix zerosB(mat_2_Coefinv.get_rows(), 1, mat_2_Coefinv.get_shel()); - zetaA = Matrix_concatenate_rows(mat_1_Coefinv, zerosB); - zetaB = Matrix_concatenate_rows(zerosA, mat_2_Coefinv); + // Matrix zerosA(mat_1_Coefinv.get_rows(), 1, mat_1_Coefinv.get_shel()); + //Matrix zerosB(mat_2_Coefinv.get_rows(), 1, mat_2_Coefinv.get_shel()); + //zetaA = Matrix_concatenate_rows(mat_1_Coefinv, zerosB); + //zetaB = Matrix_concatenate_rows(zerosA, mat_2_Coefinv); + //zetaA.resize(mat_1_Coef.rows()+mat_2_Coef.rows(),1); + //zetaB.resize(mat_1_Coef.rows()+mat_2_Coef.rows(),1); + zetaA << mat_1_Coef(), Eigen::MatrixXd.Zeros(mat_1_Coef.rows(),mat_2_Coef.cols()); + zetaA << Eigen::MatrixXd.Zeros(mat_2_Coef.rows(),mat_1_Coef.cols()), mat_2_Coef(); } - Matrix zetaAinv = zetaA.invert(); - Matrix zetaBinv = zetaB.invert(); + //Matrix zetaAinv = zetaA.invert(); + //Matrix zetaBinv = zetaB.invert(); - LOG("Creating intermediate matrix", 3); - Matrix Inter = mat_S * mat_P_Coefinv; + //LOG("Creating intermediate matrix", 3); + //Matrix Inter = mat_S * mat_P_Coefinv; + //MatrixXd Inter = mat_S * mat_P_Coefinv; LOG("Creating gamma and beta matrices", 2); - Matrix gammaA = zetaAinv * Inter; - Matrix gammaB = zetaBinv * Inter; + //Matrix gammaA = zetaAinv * Inter; + //Matrix gammaB = zetaBinv * Inter; + Eigen::MatrixXd gammaA = zetaA * mat_S * mat_P_Coef.transpose(); + Eigen::MatrixXd gammaB = zetaB * mat_S * mat_P_Coef.transpose(); - Matrix gammaA_inv = gammaA.invert(); - Matrix gammaB_inv = gammaB.invert(); + //Matrix gammaA_inv = gammaA.invert(); + //Matrix gammaB_inv = gammaB.invert(); LOG("Calculating S_AB", 2); - Matrix S_AB = gammaB * gammaA_inv; + //Matrix S_AB = gammaB * gammaA_inv; + Eigen::MatrixXd S_AB = gammaB * gammaA.transpose(); + Eigen::MatrixXd S_AB_inv_sqrt = S_AB.operatorInverseSqrt(); - Matrix Energy = Matrix_diag(mat_P_OE); - Matrix J_AB = gammaB * (Energy * gammaA_inv); + //Matrix Energy = Matrix_diag(mat_P_OE); + Eigen::MatrixXd Energy = vec_P_OE.asDiagona(); + + Eigen::MatrixXd Hamiltonian = mat_P_Coef * mat_S * mat_P_Coef.transpose(); + + Eigen::MatrixXd Hamiltonian_eff = S_AB_inv_sqrt * Hamiltonian * S_AB_inv_sqrt.transpose(); + +/* Matrix J_AB = gammaB * (Energy * gammaA_inv); Matrix e_B = gammaB * (Energy * gammaB_inv); Matrix e_A = gammaA * (Energy * gammaA_inv); @@ -113,11 +134,184 @@ double calculate_transfer_integral(const Matrix & mat_1_Coef, const Matrix & mat cout << "e_b " << e_b * hartreeToeV << " eV\n"; cout << "S_ab " << S_ab << "\n"; cout << "J_eff " << J_eff * hartreeToeV << " eV\n"; - return J_eff; +*/ +} + +void TransferComplex::printTransferIntegral( + const map &orbitaltype, + const map &orbnum) const { + + //Matrix mat1coef; + //Matrix mat2coef; + + string HOMO_OR_LUMO_A = orbitaltype.at("mon1"); + int MO_A = orbnum.at("mon1"); + if (HOMO_OR_LUMO_A.compare("HOMO") == 0) { + if (MO_A > 0) { + throw invalid_argument( + "Having specified HOMO the MO_A" + " value is in reference to the HOMO and must be a negative number"); + } + // Number of orbitals that are choices + if (MO_A <= (-1 * Orbs1.second)) { + string err = "You are trying to access HOMO" + to_string(MO_A) + + " but there " + "are only " + + to_string(Orbs1.second) + " HOMO orbitals"; + throw invalid_argument(err); + } + //mat1coef = mat_1_Coef->getRow(Orbs1.second + MO_A); + } else if (HOMO_OR_LUMO_A.compare("LUMO") == 0) { + if (MO_A < 0) { + throw invalid_argument( + "Having specified LUMO the MO_A" + " value is in reference to the LUMO and must be a positive number"); + } + int allowed_LUMO = Orbs1.first - Orbs1.second; + if (MO_A >= allowed_LUMO) { + string err = "You are trying to access LUMO+" + to_string(MO_A) + + " but there " + "are only " + + to_string(allowed_LUMO) + " LUMO orbitals"; + throw invalid_argument(err); + } + //mat1coef = mat_1_Coef->getRow(Orbs1.second + MO + 1); + } else { + throw invalid_argument("orbitals must be referred to as HOMO or LUMO"); + } + + string HOMO_OR_LUMO_B = orbitaltype.at("mon2"); + int MO_B = orbnum.at("mon2"); + if (HOMO_OR_LUMO_B.compare("HOMO") == 0) { + if (MO_B > 0) { + throw invalid_argument( + "Having specified HOMO the MO_B" + " value is in reference to the HOMO and must be a negative number"); + } + if (MO_B <= (-1 * Orbs2.second)) { + string err = "You are trying to access HOMO" + to_string(MO_B) + + " but there " + "are only " + + to_string(Orbs2.second) + " HOMO orbitals"; + throw invalid_argument(err); + } + //mat2coef = mat_2_Coef->getRow(Orbs2.second + MO_B); + } else if (HOMO_OR_LUMO_B.compare("LUMO") == 0) { + if (MO_B < 0) { + throw invalid_argument( + "Having specified LUMO the MO_B" + " value is in reference to the LUMO and must be a positive number"); + } + int allowed_LUMO = Orbs2.first - Orbs2.second; + if (MO_B >= allowed_LUMO) { + string err = "You are trying to access LUMO+" + to_string(MO_B) + + " but there " + "are only " + + to_string(allowed_LUMO) + " LUMO orbitals"; + throw invalid_argument(err); + } + //mat2coef = mat_2_Coef->getRow(Orbs2.second + MO_B + 1); + } else { + throw invalid_argument("orbitals must be referred to as HOMO or LUMO"); + } + + printTransferIntegral_( + pair(HOMO_OR_LUMO_A,MO_A), + pair(HOMO_OR_LUMO_B,MO_B)); +} +// Find the transfer integral between two orbitals. +// pair string - Either HOMO or LUMO +// int - is the orbital number HOMO-3 LUMO+5 +void TransferComplex::printTransferIntegral_(pair Orbital1, pair Orbital2) const { + + int obrital1_num = 0; + int obrital2_num = 0; + if(orbital1.first.compare("HOMO")==0){ + assert(orbitalValid_(Orbital1)==true); + orbital1_num = Orbital1.second; + }else if(orbital2.first.compare("LUMO")==0){ + assert(orbitalValid_(Orbital2)==true); + orbital2_num = Orbital2.second; + } + double J_ab = Hamiltonian(orbital1_num,orbital2_num); + double e_a = Hamiltonaian(orbital1_num,orbital1_num); + double e_b = Hamiltonaian(orbital2_num,orbital2_num); + double S_ab = S_AB(orbital1_num,orbital2_num); + double J_eff = Hamiltonaian_eff(orbital1_num,orbital2_num); + cout << "J_ab " << J_ab * hartreeToeV << " eV\n"; + cout << "e_a " << e_a * hartreeToeV << " eV\n"; + cout << "e_b " << e_b * hartreeToeV << " eV\n"; + cout << "S_ab " << S_ab << "\n"; + cout << "J_eff " << J_eff * hartreeToeV << " eV\n"; +} + +void TransferComplex::printAll() const { + + int column_width = 8; + cout << "Effective Hamiltonian" << endl; + cout << setw(column_width+2) << ""; + for(int orbital_num = 0;orbital_num & orbital) const{ + if(orbital.first.compare("HOMO")==0){ + if(orbital.second>0){ + cerr << "HOMO orbital number is not negative or 0" << endl; + return false; + } + if(orbital.second<=(-1*HOMO_Orb_)){ + cerr << "HOMO orbital does not exst " << orbital.second << endl; + return false; + } + }else if(orbital.first.compare("LUMO")==0){ + if(orbital.second<0){ + cerr << "LUMO orbital number is not positive or 0" << endl; return false; + } + if(orbital.second>(Hamiltonian_eff.rows()-LUMO_Orb_)){ + cerr << "LUMO orbital does not exst " << orbital.second << endl; + return false; + } + } + return true; +} +// Split a matrix up into a list of smaller matrices. The matrix can be split // in columns or in rows. The number of rows/cols in each smaller matrix is // held in the vector subMatrixDimension // @@ -136,36 +330,34 @@ double calculate_transfer_integral(const Matrix & mat_1_Coef, const Matrix & mat // 1 2 3 // 3 4 5 // -list splitMatrixIntoList(const vector &subMatrixDimension, - const Matrix *const mat, +list splitMatrixIntoList(const vector &subMatrixDimension, + const MatrixXd const mat, const string &ColRowSplit) { - list list_matrix; + list list_matrix; int num_sub_matrices = subMatrixDimension.size(); if (ColRowSplit.compare("Columns") == 0) { int col = 0; - for (auto i = 1; i <= num_sub_matrices; ++i) { - Matrix *mat_new = - new Matrix(mat->get_rows(), subMatrixDimension.at(i - 1)); - for (auto k = 1; k <= mat->get_rows(); ++k) { - for (auto j = 1; j <= subMatrixDimension.at(i - 1); ++j) { - mat_new->set_elem(mat->get_elem(k, col + j), k, j); + for (int i = 0; i < num_sub_matrices; ++i) { + MatrixXd mat_new(mat.rows(), subMatrixDimension.at(i)); + for (auto k = 0; k < mat.rows(); ++k) { + for (auto j = 0; j < subMatrixDimension.at(i); ++j) { + mat_new(k,j) = mat(k, col + j); } } - col += subMatrixDimension.at(i - 1); + col += subMatrixDimension.at(i); list_matrix.push_back(mat_new); } } else if (ColRowSplit.compare("Rows") == 0) { int row = 0; - for (auto i = 1; i <= num_sub_matrices; ++i) { - Matrix *mat_new = - new Matrix(subMatrixDimension.at(i - 1), mat->get_cols()); - for (auto k = 1; k <= mat->get_cols(); ++k) { - for (auto j = 1; j <= subMatrixDimension.at(i - 1); ++j) { - mat_new->set_elem(mat->get_elem(row + j, k), j, k); + for (auto i = 0; i < num_sub_matrices; ++i) { + MatrixXd mat_new(subMatrixDimension.at(i), mat.cols()); + for (auto k = 0; k < mat->get_cols(); ++k) { + for (auto j = 0; j < subMatrixDimension.at(i); ++j) { + mat_new(j,k) = mat(row + j, k); } } - row += subMatrixDimension.at(i - 1); + row += subMatrixDimension.at(i); list_matrix.push_back(mat_new); } } else { @@ -174,7 +366,7 @@ list splitMatrixIntoList(const vector &subMatrixDimension, return list_matrix; } -list splitCoefsUpByAtoms(const vector & basisFuncP, Matrix *Coefs, +list splitCoefsUpByAtoms(const vector & basisFuncP, MatrixXd Coefs, const string & ColRow) { return splitMatrixIntoList(basisFuncP, Coefs, ColRow); } @@ -483,13 +675,13 @@ Matrix *unscramble_Coef(const std::vector &matchDimerB, // Similar to the above function but we will be moving both the rows // and columns -Matrix *unscramble_S(const std::vector &matchDimerA, +Eigen::MatrixXd unscramble_S(const std::vector &matchDimerA, const std::vector &matchDimerB, - const std::vector &basisFuncP, Matrix *S) { + const std::vector &basisFuncP, const MatrixXd & S) { - Matrix *S_new; + Eigen::MatrixXd S_new(S.rows(),S.cols()); { - list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Columns"); + list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Columns"); vector> monAmatch; for (unsigned i = 1; i <= matchDimerA.size(); ++i) { @@ -511,7 +703,7 @@ Matrix *unscramble_S(const std::vector &matchDimerA, S = S_new; { - list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Rows"); + list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Rows"); vector> monAmatch; for (unsigned i = 1; i <= matchDimerA.size(); ++i) { @@ -541,7 +733,7 @@ Matrix *unscramble_S(const std::vector &matchDimerA, Matrix *S_new; { - list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Columns"); + list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Columns"); vector> monAmatch; for (unsigned i = 1; i <= matchDimerA.size(); ++i) { @@ -557,7 +749,7 @@ Matrix *unscramble_S(const std::vector &matchDimerA, S = S_new; { - list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Rows"); + list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Rows"); vector> monAmatch; for (unsigned i = 1; i <= matchDimerA.size(); ++i) { @@ -574,16 +766,12 @@ Matrix *unscramble_S(const std::vector &matchDimerA, return S_new; } -} // namespace catnip - -using namespace catnip; - -TransferComplex::TransferComplex(Matrix *mat1Coef, Matrix *mat2Coef, - Matrix *matPCoef, std::pair MOs1, - std::pair MOs2, Matrix *matS, - Matrix *matPOE, bool cp) { +TransferComplex::TransferComplex(Eigen::MatrixXd mat1Coef, Eigen::MatrixXd mat2Coef, + Eigen::MatrixXd matPCoef, std::pair MOs1, + std::pair MOs2, Eigen::MatrixXd matS, + Eigen::VectorXd vecPOE, bool cp) { - unscrambled = false; + unscrambled_ = false; counterPoise_ = cp; // Consistency check if (matS->get_cols() != matPCoef->get_cols()) { @@ -620,16 +808,16 @@ TransferComplex::TransferComplex(Matrix *mat1Coef, Matrix *mat2Coef, Orbs1 = MOs1; Orbs2 = MOs2; mat_S = matS; - mat_P_OE = matPOE; + vec_P_OE = vecPOE; } -void TransferComplex::unscramble(const Matrix &coord_1_mat, - const Matrix &coord_2_mat, - const Matrix &coord_P_mat, +void TransferComplex::unscramble(const Eigen::MatrixXd &coord_1_mat, + const Eigen::MatrixXd &coord_2_mat, + const Eigen::MatrixXd &coord_P_mat, const std::vector &basisP, const std::vector &basis2) { - unscrambled = true; + unscrambled_ = true; const int sig_fig = 4; @@ -673,10 +861,9 @@ void TransferComplex::unscramble(const Matrix &coord_1_mat, } } -double TransferComplex::calcJ(const map &orbitaltype, - const map &orbnum) { +double TransferComplex::calcJ() { - if (unscrambled == false) { + if (unscrambled_ == false) { cerr << "WARNING unable to automatically line up basis functions of" " monomers with dimers, you better make sure they correctly" " line up or run the calculations again with the correct " @@ -684,80 +871,7 @@ double TransferComplex::calcJ(const map &orbitaltype, << endl; } - Matrix mat1coef; - Matrix mat2coef; - - string HOMO_OR_LUMO = orbitaltype.at("mon1"); - int MO = orbnum.at("mon1"); - if (HOMO_OR_LUMO.compare("HOMO") == 0) { - if (MO > 0) { - throw invalid_argument( - "Having specified HOMO the MO" - " value is in reference to the HOMO and must be a negative number"); - } - // Number of orbitals that are choices - if (MO <= (-1 * Orbs1.second)) { - string err = "You are trying to access HOMO" + to_string(MO) + - " but there " - "are only " + - to_string(Orbs1.second) + " HOMO orbitals"; - throw invalid_argument(err); - } - mat1coef = mat_1_Coef->getRow(Orbs1.second + MO); - } else if (HOMO_OR_LUMO.compare("LUMO") == 0) { - if (MO < 0) { - throw invalid_argument( - "Having specified LUMO the MO" - " value is in reference to the LUMO and must be a positive number"); - } - int allowed_LUMO = Orbs1.first - Orbs1.second; - if (MO >= allowed_LUMO) { - string err = "You are trying to access LUMO+" + to_string(MO) + - " but there " - "are only " + - to_string(allowed_LUMO) + " LUMO orbitals"; - throw invalid_argument(err); - } - mat1coef = mat_1_Coef->getRow(Orbs1.second + MO + 1); - } else { - throw invalid_argument("orbitals must be referred to as HOMO or LUMO"); - } - - HOMO_OR_LUMO = orbitaltype.at("mon2"); - MO = orbnum.at("mon2"); - if (HOMO_OR_LUMO.compare("HOMO") == 0) { - if (MO > 0) { - throw invalid_argument( - "Having specified HOMO the MO" - " value is in reference to the HOMO and must be a negative number"); - } - if (MO <= (-1 * Orbs2.second)) { - string err = "You are trying to access HOMO" + to_string(MO) + - " but there " - "are only " + - to_string(Orbs2.second) + " HOMO orbitals"; - throw invalid_argument(err); - } - mat2coef = mat_2_Coef->getRow(Orbs2.second + MO); - } else if (HOMO_OR_LUMO.compare("LUMO") == 0) { - if (MO < 0) { - throw invalid_argument( - "Having specified LUMO the MO" - " value is in reference to the LUMO and must be a positive number"); - } - int allowed_LUMO = Orbs2.first - Orbs2.second; - if (MO >= allowed_LUMO) { - string err = "You are trying to access LUMO+" + to_string(MO) + - " but there " - "are only " + - to_string(allowed_LUMO) + " LUMO orbitals"; - throw invalid_argument(err); - } - mat2coef = mat_2_Coef->getRow(Orbs2.second + MO + 1); - } else { - throw invalid_argument("orbitals must be referred to as HOMO or LUMO"); - } - - return calculate_transfer_integral(mat1coef, mat2coef, *mat_P_Coef, *mat_S, - *mat_P_OE, counterPoise_); + return calculate_transfer_integral_(); } + +} // namespace catnip diff --git a/src/libcatnip/qc_functions.hpp b/src/libcatnip/qc_functions.hpp index e8bc1a6..11bc0b8 100644 --- a/src/libcatnip/qc_functions.hpp +++ b/src/libcatnip/qc_functions.hpp @@ -7,82 +7,139 @@ #include #include -#include "matrix.hpp" +//#include "matrix.hpp" +#include namespace catnip { class TransferComplex { - private: - Matrix* mat_1_Coef; - Matrix* mat_2_Coef; - Matrix* mat_P_Coef; - // Stores the number of Molecular orbitals - // and the HOMO for both monomer 1 and 2 - std::pair Orbs1; - std::pair Orbs2; - Matrix* mat_S; - Matrix* mat_P_OE; - // If unscrambaling is required - bool unscrambled; - bool counterPoise_; - - public: - TransferComplex(Matrix* mat1Coef, Matrix* mat2Coef, Matrix* matPCoef, - std::pair MOs1, std::pair MOs2, - Matrix* matS, Matrix* matPOE, bool cp); - - void unscramble(const Matrix& coord_1_mat, const Matrix& coord_2_mat, - const Matrix& coord_P_mat, const std::vector& basisP, - const std::vector& basis2); - - // Orbital type and a map of the corresponding number - // E.g. - // orbital type orbital number - // "mon1" "LUMO" "mon1" -3 - // "mon2" "HOMO" "mon2" 0 - // - // monomer1 LUMO-3 - // monomer2 HOMO - double calcJ(const std::map& orbitaltype, - const std::map& orbitalnum); + private: + Eigen::MatrixXd mat_1_Coef; + Eigen::MatrixXd mat_2_Coef; + Eigen::MatrixXd mat_P_Coef; + // Stores the number of Molecular orbitals + // and the HOMO for both monomer 1 and 2 + std::pair Orbs1; + std::pair Orbs2; + + /** + * \brief basis function overlap matrix + **/ + Eigen::MatrixXd mat_S; + /** + * \brief Molecular orbital overlap matrix + **/ + Eigen::MatrixXd S_AB; + + /** + * \brief Non orthonormalized Hamiltonian matrix + **/ + Eigen::MatrixXd Hamiltonian; + + /** + * \brief Orthonormalized Hamiltonian Matrix + **/ + Eigen::MatrixXd Hamiltonian_eff; + + int HOMO_Orb_; + int LUMO_Orb_; + Eigen::VectorXd vec_P_OE; + // If unscrambaling is required + bool unscrambled_; + bool counterPoise_; + + /* + * \brief Determine if the provided orbital is valid + **/ + bool orbitalValid_(const std::pair & orbital) const; + + void calculate_transfer_integral_( + const Eigen::MatrixXd & mat_1_Coef, + const Eigen::MatrixXd & mat_2_Coef, + Eigen::MatrixXd mat_P_Coef, + const Eigen::MatrixXd & mat_S, + const Eigen::VectorXd& vec_P_OE, + bool counterPoise_); + + void printTransferIntegral_(std::pair Orbital1, + std::pair Orbital2) const; + public: + TransferComplex( + Eigen::MatrixXd mat1Coef, + Eigen::MatrixXd mat2Coef, + Eigen::MatrixXd matPCoef, + std::pair MOs1, + std::pair MOs2, + Eigen::MatrixXd matS, + Eigen::VectorXd vecPOE, + bool cp); + + void unscramble( + const Eigen::MatrixXd& coord_1_mat, + const Eigen::MatrixXd& coord_2_mat, + const Eigen::MatrixXd& coord_P_mat, + const std::vector& basisP, + const std::vector& basis2); + + // Orbital type and a map of the corresponding number + // E.g. + // orbital type orbital number + // "mon1" "LUMO" "mon1" -3 + // "mon2" "HOMO" "mon2" 0 + // + // monomer1 LUMO-3 + // monomer2 HOMO + double calcJ(const std::map& orbitaltype, + const std::map& orbitalnum); + + /** + * \brief Print the transfer integral specified + **/ + void printTransferIntegral(std::pair Orbital1, + std::pair Orbital2) const; + + /** + * \brief Print All info in matrix form + **/ + void printAll() const; }; std::unordered_map> findRank( - Matrix& Orb_E_Alpha, Matrix& Orb_E_Beta); + Eigen::VectorXd& Orb_E_Alpha, Eigen::VectorXd& Orb_E_Beta); -double calculate_transfer_integral(const Matrix & mat_1_Coef, const Matrix & mat_2_Coef, - Matrix mat_P_Coef,const Matrix & mat_S, - const Matrix& mat_P_OE, bool counterPoise_); +/*double calculate_transfer_integral(const Eigen::MatrixXd & mat_1_Coef, const Eigen::MatrixXd & mat_2_Coef, + Eigen::MatrixXd mat_P_Coef,const Eigen::MatrixXd & mat_S, + const Eigen::VectorXd& vec_P_OE, bool counterPoise_);*/ // Reorganize the dimer coefficients to match up with the monomers -Matrix organize_P_Coef(std::vector matchDimerA, +Eigen::MatrixXd organize_P_Coef(std::vector matchDimerA, std::vector matchDimerB, std::vector basisFuncA, std::vector basisFuncB, - std::vector basisFuncDimer, Matrix dimerCoef); + std::vector basisFuncDimer, Eigen::MatrixXd dimerCoef); // Unscramble the coefficients of the dimer matrix // Assumes that the match vectors describe swaps looking at a single // instance of the dimerCoef matrix -Matrix* unscramble_Coef(const std::vector& matchDimerA, +Eigen::MatrixXd unscramble_Coef(const std::vector& matchDimerA, const std::vector& matchDimerB, const std::vector& basisFuncDimer, - Matrix* dimerCoef); + Eigen::MatrixXd dimerCoef); -Matrix* unscramble_Coef(const std::vector& matchDimerA, - const std::vector& basisFuncDimer, Matrix* dimerCoef); +Eigen::MatrixXd unscramble_Coef(const std::vector& matchDimerA, + const std::vector& basisFuncDimer, Eigen::MatrixXd dimerCoef); // Reorganize the dimer overlap matrix to line up with the monomer // coefficients. -Matrix* unscramble_S(const std::vector& matchDimerA, +Eigen::MatrixXd unscramble_S(const std::vector& matchDimerA, const std::vector& matchDimerB, - const std::vector& basisFuncDimer, Matrix* S); + const std::vector& basisFuncDimer, Eigen::MatrixXd S); -Matrix* unscramble_S(const std::vector& matchDimerA, - const std::vector& basisFuncDimer, Matrix* S); +Eigen::MatrixXd unscramble_S(const std::vector& matchDimerA, + const std::vector& basisFuncDimer, Eigen::MatrixXd S); -Matrix* unscramble_OE(std::vector matchDimerA, +Eigen::MatrixXd unscramble_OE(std::vector matchDimerA, std::vector matchDimerB, - std::vector basisFuncDimer, Matrix* OE); + std::vector basisFuncDimer, Eigen::VectorXd OE); } // namespace catnip #endif // _CATNIP_QC_FUNCTIONS_HPP diff --git a/src/tools/main.cpp b/src/tools/main.cpp index 0455c80..580c84e 100644 --- a/src/tools/main.cpp +++ b/src/tools/main.cpp @@ -86,8 +86,8 @@ int main(int argc, const char *argv[]) { Eigen::MatrixXd mat_P_Coef = pr_P.getCoefsMatrix(par->getSpinP()); //auto vec_P_OE = lr_P.getOE(par->getSpinP()); - Eigen::MatrixXd mat_P_OE = Eigen::MatrixXd(lr_P.getOE(par->getSpinP())); - //Matrix *mat_P_OE = new Matrix(vec_P_OE); + Eigen::VectorXd vec_P_OE = Eigen::VectorXd(lr_P.getOE(par->getSpinP())); + //Matrix *vec_P_OE = new Matrix(vec_P_OE); int HOMO1 = lr_1.getHOMOLevel(par->getSpin1()); LOG("Getting " + par->getSpin1() + " of monomer 1", 2); @@ -134,7 +134,7 @@ int main(int argc, const char *argv[]) { LOG("Creating transfercomplex", 1); TransferComplex TC(mat_1_Coef, mat_2_Coef, mat_P_Coef, Orbs1, Orbs2, mat_S, - mat_P_OE, par->getCounterPoise()); + vec_P_OE, par->getCounterPoise()); // Set the transfer complex to counterpoise if it is the case. @@ -178,7 +178,9 @@ int main(int argc, const char *argv[]) { orbitalnums["mon2"] = par->getOrbNum2(); LOG("Calculating transfer integral", 1); - TC.calcJ(orbitaltypes, orbitalnums); + TC.calcJ(); + TC.printTransferIntegral(orbitaltypes, orbitalnums); + } return 0; From f99db21aaa596b69ec2a08065547f78ed20a4ef8 Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Sun, 28 Apr 2019 16:37:32 -0600 Subject: [PATCH 06/68] Added matrix helper functions --- src/libcatnip/matrix.cpp | 80 ++++++++++++++++++++++++++++++++++++++++ src/libcatnip/matrix.hpp | 49 ++++++++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 src/libcatnip/matrix.cpp create mode 100644 src/libcatnip/matrix.hpp diff --git a/src/libcatnip/matrix.cpp b/src/libcatnip/matrix.cpp new file mode 100644 index 0000000..14f2af0 --- /dev/null +++ b/src/libcatnip/matrix.cpp @@ -0,0 +1,80 @@ + +#include +#include +#include +#include +#include + +#include "matrix.hpp" + +using namespace std; + +namespace catnip { + +string double_tos(double f, int nd) { + ostringstream ostr; + int tens = stod("1" + string(nd, '0')); + ostr << round(f * tens) / tens; + return ostr.str(); +} + +vector matchRow(const Matrix & mat1, const Matrix & mat2, const int sf) { + + if (mat1.cols() != mat2.cols()) { + throw invalid_argument( + "match function only works when matrices have same number of columns"); + } + vector m_vec(mat1.rows(), -1); + + for (int i = 0; i < mat1.rows(); ++i) { + for (int ii = 0; ii < mat2.rows(); ++ii) { + bool match = true; + for (int j = 0; j < mat1.cols(); ++j) { + string val1 = double_tos(mat1(i, j), sf); + string val2 = double_tos(mat2(ii, j), sf); + if (val1.compare(val2) != 0) { + match = false; + break; + } + } + if (match) m_vec.at(i) = ii; + } + } + return m_vec; +} + +vector matchCol(const Eigen::MatrixXd & mat1, + const Eigen::MatrixXd &mat2, + const int sf) { + + if (mat1.rows() != mat2.rows()) { + throw invalid_argument( + "match function only works when matrices have same number of rows"); + } + vector m_vec(mat1.cols(), -1); + + for (int i = 0; i < mat1.cols(); ++i) { + for (int ii = 0; ii < mat2.cols(); ++ii) { + bool match = true; + for (int j = 0; j < mat1.rows(); ++j) { + string val1 = double_tos(mat1(j, i), sf); + string val2 = double_tos(mat2(j, ii), sf); + if (val1.compare(val2) != 0) { + match = false; + break; + } + } + if (match) m_vec.at(i) = ii; + } + } + return m_vec; +} + + + + + + + + +} diff --git a/src/libcatnip/matrix.hpp b/src/libcatnip/matrix.hpp new file mode 100644 index 0000000..903327a --- /dev/null +++ b/src/libcatnip/matrix.hpp @@ -0,0 +1,49 @@ + +#ifndef MATRIX_HELPER_HPP +#define MATRIX_HELPER_HPP + +namespace catnip { +#include +#include + + /** + * Responsible for matching the rows between two matrices Returns which row + * in matrix 1 matches which row in matrix 2, -1 means there is no match sf + * is the number of significant figures that will be checked to ensure the + * same value. + * + * E.g. + * + * Matrix 1 + * + * 1.0 0.0 0.0 + * 0.0 3.0 0.0 + * 0.0 2.5 1.0 + * 0.0 0.0 5.0 + * 6.0 0.0 0.0 + * + * Matrix 2 + * + * 1.0 0.0 0.0 + * 8.0 8.0 8.0 + * 0.0 0.0 5.0 + * + * The vector returned would return + * + * vector matched rows + * 0 + * -1 // indicates no match + * 3 + **/ + std::vector matchRow( + const Eigen::MatrixXd &mat1, + const Eigen::MatrixXd &mat2, + const int sig_fig); + + std::vector matchCol( + const Eigen::MatrixXd &mat1, + const Eigen::MatrixXd &mat2, + const int sig_fig); + +} // namespace catnip +#endif // MATRIX_HELPER_HPP From e77984a944b0ec9a209f768ec3e254cb75941c91 Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Sun, 28 Apr 2019 16:37:57 -0600 Subject: [PATCH 07/68] Updated tests and qc_functions.cpp --- src/libcatnip/qc_functions.cpp | 248 ++++++++++++-------------------- src/tests/test_logreader.cpp | 2 +- src/tests/test_qc_functions.cpp | 228 +++++++++++++++-------------- 3 files changed, 208 insertions(+), 270 deletions(-) diff --git a/src/libcatnip/qc_functions.cpp b/src/libcatnip/qc_functions.cpp index 3cb76b8..be8bbdb 100644 --- a/src/libcatnip/qc_functions.cpp +++ b/src/libcatnip/qc_functions.cpp @@ -23,32 +23,16 @@ unordered_map> findRank(Eigen::VectorXd &Orb_E_Alpha, vector> all; - //auto m_a = Orb_E_Alpha.getCol(1); - - /*for (int ind = 1; ind <= m_a.get_rows(); ind++) { - auto val = m_a.get_elem(ind); - pair pr(val, "Alpha"); - all.push_back(pr); - }*/ for( double & val : Orb_E_Alpha){ all.push_back(pair(val,"Alpha")); } - //if (Orb_E_Beta.get_cols() > 0) { - // auto m_b = Orb_E_Beta.getCol(1); - - // for (int ind = 1; ind <= m_b.get_rows(); ind++) { - for( double & val : Orb_E_Beta ){ - //auto val = m_b.get_elem(ind); - //pair pr(val, "Beta"); - //all.push_back(pr); - all.push_back(pair(val, "Beta")); - } - // } - // Sort the vectors + for( double & val : Orb_E_Beta ){ + all.push_back(pair(val, "Beta")); + } sort(all.begin(), all.end(), - [](const pair &P1, const pair &P2) - -> bool { return P1.first < P2.first; }); + [](const pair &P1, const pair &P2) + -> bool { return P1.first < P2.first; }); // Now that they are sorted we are going to update the ranks int rank = 1; @@ -64,87 +48,40 @@ unordered_map> findRank(Eigen::VectorXd &Orb_E_Alpha, // Essentially calculates the transfer integral void TransferComplex::calculate_transfer_integral_() { - //Matrix mat_1_Coefinv = mat_1_Coef.invert(); - //Matrix mat_2_Coefinv = mat_2_Coef.invert(); - //Matrix mat_P_Coefinv = mat_P_Coef.invert(); - auto dimension = mat_1_Coef.rows()+mat_2_Coef.rows(); Eigen::MatrixXd zetaA(dimension,dimension); Eigen::MatrixXd zetaB(dimension,dimension); if (counterPoise_) { LOG("Creating zeta matrices from coefficients assuming counterpoise", 2); - //zetaA = (mat_1_Coefinv); - //zetaB = (mat_2_Coefinv); zetaA = mat_1_Coef(); zetaB = mat_2_Coef(); } else { LOG("Creating zeta matrices from coefficients", 2); - // Matrix zerosA(mat_1_Coefinv.get_rows(), 1, mat_1_Coefinv.get_shel()); - //Matrix zerosB(mat_2_Coefinv.get_rows(), 1, mat_2_Coefinv.get_shel()); - //zetaA = Matrix_concatenate_rows(mat_1_Coefinv, zerosB); - //zetaB = Matrix_concatenate_rows(zerosA, mat_2_Coefinv); - //zetaA.resize(mat_1_Coef.rows()+mat_2_Coef.rows(),1); - //zetaB.resize(mat_1_Coef.rows()+mat_2_Coef.rows(),1); - zetaA << mat_1_Coef(), Eigen::MatrixXd.Zeros(mat_1_Coef.rows(),mat_2_Coef.cols()); - zetaA << Eigen::MatrixXd.Zeros(mat_2_Coef.rows(),mat_1_Coef.cols()), mat_2_Coef(); + zetaA << mat_1_Coef(), Eigen::MatrixXd::Zeros(mat_1_Coef.rows(),mat_2_Coef.cols()); + zetaA << Eigen::MatrixXd::Zeros(mat_2_Coef.rows(),mat_1_Coef.cols()), mat_2_Coef(); } - //Matrix zetaAinv = zetaA.invert(); - //Matrix zetaBinv = zetaB.invert(); - - //LOG("Creating intermediate matrix", 3); - //Matrix Inter = mat_S * mat_P_Coefinv; - //MatrixXd Inter = mat_S * mat_P_Coefinv; LOG("Creating gamma and beta matrices", 2); - //Matrix gammaA = zetaAinv * Inter; - //Matrix gammaB = zetaBinv * Inter; Eigen::MatrixXd gammaA = zetaA * mat_S * mat_P_Coef.transpose(); Eigen::MatrixXd gammaB = zetaB * mat_S * mat_P_Coef.transpose(); - //Matrix gammaA_inv = gammaA.invert(); - //Matrix gammaB_inv = gammaB.invert(); LOG("Calculating S_AB", 2); - //Matrix S_AB = gammaB * gammaA_inv; Eigen::MatrixXd S_AB = gammaB * gammaA.transpose(); Eigen::MatrixXd S_AB_inv_sqrt = S_AB.operatorInverseSqrt(); - //Matrix Energy = Matrix_diag(mat_P_OE); Eigen::MatrixXd Energy = vec_P_OE.asDiagona(); Eigen::MatrixXd Hamiltonian = mat_P_Coef * mat_S * mat_P_Coef.transpose(); Eigen::MatrixXd Hamiltonian_eff = S_AB_inv_sqrt * Hamiltonian * S_AB_inv_sqrt.transpose(); -/* Matrix J_AB = gammaB * (Energy * gammaA_inv); - - Matrix e_B = gammaB * (Energy * gammaB_inv); - Matrix e_A = gammaA * (Energy * gammaA_inv); - - double J_ab = J_AB.get_elem(1, 1); - double e_b = e_B.get_elem(1, 1); - double e_a = e_A.get_elem(1, 1); - double S_ab = S_AB.get_elem(1, 1); - - double J_eff = (J_ab - 1 / ((double)2) * (e_b + e_a) * S_ab); - J_eff = J_eff / ((double)(1 - pow(S_ab, 2))); - - cout << "J_ab " << J_ab * hartreeToeV << " eV\n"; - cout << "e_a " << e_a * hartreeToeV << " eV\n"; - cout << "e_b " << e_b * hartreeToeV << " eV\n"; - cout << "S_ab " << S_ab << "\n"; - cout << "J_eff " << J_eff * hartreeToeV << " eV\n"; - return J_eff; -*/ } void TransferComplex::printTransferIntegral( const map &orbitaltype, const map &orbnum) const { - //Matrix mat1coef; - //Matrix mat2coef; - string HOMO_OR_LUMO_A = orbitaltype.at("mon1"); int MO_A = orbnum.at("mon1"); if (HOMO_OR_LUMO_A.compare("HOMO") == 0) { @@ -161,7 +98,6 @@ void TransferComplex::printTransferIntegral( to_string(Orbs1.second) + " HOMO orbitals"; throw invalid_argument(err); } - //mat1coef = mat_1_Coef->getRow(Orbs1.second + MO_A); } else if (HOMO_OR_LUMO_A.compare("LUMO") == 0) { if (MO_A < 0) { throw invalid_argument( @@ -176,7 +112,6 @@ void TransferComplex::printTransferIntegral( to_string(allowed_LUMO) + " LUMO orbitals"; throw invalid_argument(err); } - //mat1coef = mat_1_Coef->getRow(Orbs1.second + MO + 1); } else { throw invalid_argument("orbitals must be referred to as HOMO or LUMO"); } @@ -196,7 +131,6 @@ void TransferComplex::printTransferIntegral( to_string(Orbs2.second) + " HOMO orbitals"; throw invalid_argument(err); } - //mat2coef = mat_2_Coef->getRow(Orbs2.second + MO_B); } else if (HOMO_OR_LUMO_B.compare("LUMO") == 0) { if (MO_B < 0) { throw invalid_argument( @@ -211,7 +145,6 @@ void TransferComplex::printTransferIntegral( to_string(allowed_LUMO) + " LUMO orbitals"; throw invalid_argument(err); } - //mat2coef = mat_2_Coef->getRow(Orbs2.second + MO_B + 1); } else { throw invalid_argument("orbitals must be referred to as HOMO or LUMO"); } @@ -330,16 +263,17 @@ bool TransferComplex::orbitalValid_(const std::pair & orbital) // 1 2 3 // 3 4 5 // -list splitMatrixIntoList(const vector &subMatrixDimension, - const MatrixXd const mat, - const string &ColRowSplit) { +list splitMatrixIntoList( + const vector &subMatrixDimension, + const Eigen::MatrixXd const mat, + const string &ColRowSplit) { - list list_matrix; + list list_matrix; int num_sub_matrices = subMatrixDimension.size(); if (ColRowSplit.compare("Columns") == 0) { int col = 0; for (int i = 0; i < num_sub_matrices; ++i) { - MatrixXd mat_new(mat.rows(), subMatrixDimension.at(i)); + Eigen::MatrixXd mat_new(mat.rows(), subMatrixDimension.at(i)); for (auto k = 0; k < mat.rows(); ++k) { for (auto j = 0; j < subMatrixDimension.at(i); ++j) { mat_new(k,j) = mat(k, col + j); @@ -351,8 +285,8 @@ list splitMatrixIntoList(const vector &subMatrixDimension, } else if (ColRowSplit.compare("Rows") == 0) { int row = 0; for (auto i = 0; i < num_sub_matrices; ++i) { - MatrixXd mat_new(subMatrixDimension.at(i), mat.cols()); - for (auto k = 0; k < mat->get_cols(); ++k) { + Eigen::MatrixXd mat_new(subMatrixDimension.at(i), mat.cols()); + for (auto k = 0; k < mat.cols(); ++k) { for (auto j = 0; j < subMatrixDimension.at(i); ++j) { mat_new(j,k) = mat(row + j, k); } @@ -366,7 +300,7 @@ list splitMatrixIntoList(const vector &subMatrixDimension, return list_matrix; } -list splitCoefsUpByAtoms(const vector & basisFuncP, MatrixXd Coefs, +list splitCoefsUpByAtoms(const vector & basisFuncP, Eigen::MatrixXd Coefs, const string & ColRow) { return splitMatrixIntoList(basisFuncP, Coefs, ColRow); } @@ -521,77 +455,77 @@ void refreshSwapOrder(vector> &monAmatch) { // then actually implements the swaps by exchanging the matrices in the list. void updateSwapLists(vector> &monBmatch, vector> &monAmatch, - list &p_atom_mat_coef) { + list &p_atom_mat_coef) { for (auto p : monBmatch) { if (p.first != p.second) { auto it = p_atom_mat_coef.begin(); - Matrix *temp = *(next(it, p.first - 1)); - *(next(it, p.first - 1)) = *(next(it, p.second - 1)); - *(next(it, p.second - 1)) = temp; + Eigen::MatrixXd & temp = *(next(it, p.first)); + *(next(it, p.first)) = *(next(it, p.second)); + *(next(it, p.second)) = temp; } } for (auto p : monAmatch) { if (p.first != p.second) { auto it = p_atom_mat_coef.begin(); - Matrix *temp = *(next(it, p.first - 1)); - *(next(it, p.first - 1)) = *(next(it, p.second - 1)); - *(next(it, p.second - 1)) = temp; + Eigen::MatrixXd & temp = *(next(it, p.first)); + *(next(it, p.first)) = *(next(it, p.second)); + *(next(it, p.second)) = temp; } } return; } void updateSwapLists(vector> &monAmatch, - list &atom_mat_coef) { + list &atom_mat_coef) { for (auto p : monAmatch) { if (p.first != p.second) { auto it = atom_mat_coef.begin(); - Matrix *temp = *(next(it, p.first - 1)); - *(next(it, p.first - 1)) = *(next(it, p.second - 1)); - *(next(it, p.second - 1)) = temp; + Eigen::MatrixXd & temp = *(next(it, p.first)); + *(next(it, p.first)) = *(next(it, p.second)); + *(next(it, p.second)) = temp; } } return; } -Matrix *mergeListOfMatrices(list &matrix_list, const int rows, +Eigen::MatrixXd mergeListOfMatrices(list &matrix_list, const int rows, const int cols, const string &ColRowMerge) { - Matrix *full_matrix = new Matrix(rows, cols); + Eigen::MatrixXd full_matrix(rows, cols); if (ColRowMerge.compare("Columns") == 0) { int col = 0; for (auto it = matrix_list.begin(); it != matrix_list.end(); ++it) { - Matrix *mat_ptr = *it; - int row = 1; + Eigen::MatrixXd & mat = *it; + int row = 0; if (col > cols) throw runtime_error("Your new matrix is not large enough"); - for (auto i = 1; i <= mat_ptr->get_rows(); ++i) { + for (auto i = 0; i < mat.rows(); ++i) { if (row > rows) throw runtime_error("Your new matrix is not large enough"); - for (auto j = 1; j <= mat_ptr->get_cols(); ++j) { - full_matrix->set_elem(mat_ptr->get_elem(i, j), row, j + col); + for (auto j = 0; j < mat.cols(); ++j) { + full_matrix(row,j+col) = mat(i, j); } ++row; } - col += mat_ptr->get_cols(); + col += mat.cols(); } } else if (ColRowMerge.compare("Rows") == 0) { int row = 0; for (auto it = matrix_list.begin(); it != matrix_list.end(); ++it) { - Matrix *mat_ptr = *it; - int col = 1; + Matrix *mat = *it; + int col = 0; if (row > rows) throw runtime_error("Your new matrix is not large enough"); - for (auto j = 1; j <= mat_ptr->get_cols(); ++j) { + for (auto j = 0; j < mat.cols(); ++j) { if (col > cols) throw runtime_error("Your new matrix is not large enough"); - for (auto i = 1; i <= mat_ptr->get_rows(); ++i) { - full_matrix->set_elem(mat_ptr->get_elem(i, j), row + i, col); + for (auto i = 0; i < mat.rows(); ++i) { + full_matrix(row + i, col) = mat(i, j); } ++col; } - row += mat_ptr->get_rows(); + row += mat.rows(); } } else { throw invalid_argument("Unrecognized merge type for list of matrices"); @@ -600,22 +534,24 @@ Matrix *mergeListOfMatrices(list &matrix_list, const int rows, } // This function -Matrix *createNewMatrix(list &p_atom_mat_coef, int rows, int cols, +Eigen::MatrixXd createNewMatrix(list &p_atom_mat_coef, int rows, int cols, const string &ColRow) { return mergeListOfMatrices(p_atom_mat_coef, rows, cols, ColRow); } // unscramble the coefficients -Matrix *unscramble_Coef(const std::vector &matchDimerA, - const std::vector &matchDimerB, - const std::vector &basisFuncP, Matrix *dimerCoef) { +Eigen::MatrixXd unscramble_Coef( + const std::vector &matchDimerA, + const std::vector &matchDimerB, + const std::vector &basisFuncP, + const Eigen::MatrixXd & dimerCoef) { // Let's reduce the complexity of the problem by instead of working // with the basis functions lets just work with the atoms. We can do // this by treating all the basis functions associated with a single // atom as a block. - list p_atom_mat_coef = + list p_atom_mat_coef = splitCoefsUpByAtoms(basisFuncP, dimerCoef, "Columns"); // Place all of monomer A atom basis functions on the left side of the @@ -625,33 +561,36 @@ Matrix *unscramble_Coef(const std::vector &matchDimerA, // Second int is the col in the dimer the atom is presently at vector> monAmatch; - for (unsigned i = 1; i <= matchDimerA.size(); ++i) { - pair pr(i, matchDimerA.at(i - 1)); + for (unsigned i = 0; i < matchDimerA.size(); ++i) { + pair pr(i, matchDimerA.at(i)); monAmatch.push_back(pr); } vector> monBmatch; - for (unsigned i = 1; i <= matchDimerB.size(); ++i) { - pair pr(i + monAmatch.size(), matchDimerB.at(i - 1)); + for (unsigned i = 0; i < matchDimerB.size(); ++i) { + pair pr(i + monAmatch.size(), matchDimerB.at(i)); monBmatch.push_back(pr); } refreshSwapOrder(monBmatch, monAmatch); updateSwapLists(monBmatch, monAmatch, p_atom_mat_coef); - Matrix *dimerCoef_new = createNewMatrix( - p_atom_mat_coef, dimerCoef->get_rows(), dimerCoef->get_cols(), "Columns"); + Eigen::MatrixXd dimerCoef_new = createNewMatrix( + p_atom_mat_coef, dimerCoef.rows(), dimerCoef.cols(), "Columns"); + return dimerCoef_new; } // unscramble the coefficients -Matrix *unscramble_Coef(const std::vector &matchDimerB, - const std::vector &basisFuncB, Matrix *Coef) { +Eigen::MatrixXd unscramble_Coef( + const std::vector &matchDimerB, + const std::vector &basisFuncB, + const Eigen::MatrixXd & Coef) { // Let's reduce the complexity of the problem by instead of working // with the basis functions lets just work with the atoms. We can do // this by treating all the basis functions associated with a single // atom as a block. - list atom_mat_coef = + list atom_mat_coef = splitCoefsUpByAtoms(basisFuncB, Coef, "Columns"); // Place all of monomer A atom basis functions on the left side of the @@ -661,15 +600,15 @@ Matrix *unscramble_Coef(const std::vector &matchDimerB, // Second int is the col in the dimer the atom is presently at vector> monBmatch; - for (unsigned i = 1; i <= matchDimerB.size(); ++i) { - pair pr(i, matchDimerB.at(i - 1)); + for (unsigned i = 0; i < matchDimerB.size(); ++i) { + pair pr(i, matchDimerB.at(i)); monBmatch.push_back(pr); } refreshSwapOrder(monBmatch); updateSwapLists(monBmatch, atom_mat_coef); - Matrix *Coef_new = createNewMatrix(atom_mat_coef, Coef->get_rows(), - Coef->get_cols(), "Columns"); + Eigen::MatrixXd Coef_new = createNewMatrix(atom_mat_coef, Coef.rows(), + Coef.cols(), "Columns"); return Coef_new; } @@ -677,48 +616,49 @@ Matrix *unscramble_Coef(const std::vector &matchDimerB, // and columns Eigen::MatrixXd unscramble_S(const std::vector &matchDimerA, const std::vector &matchDimerB, - const std::vector &basisFuncP, const MatrixXd & S) { + const std::vector &basisFuncP, + const Eigen::MatrixXd & S) { Eigen::MatrixXd S_new(S.rows(),S.cols()); { - list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Columns"); + list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Columns"); vector> monAmatch; - for (unsigned i = 1; i <= matchDimerA.size(); ++i) { - pair pr(i, matchDimerA.at(i - 1)); + for (unsigned i = 0; i < matchDimerA.size(); ++i) { + pair pr(i, matchDimerA.at(i)); monAmatch.push_back(pr); } vector> monBmatch; - for (unsigned i = 1; i <= matchDimerB.size(); ++i) { - pair pr(i + monAmatch.size(), matchDimerB.at(i - 1)); + for (unsigned i = 0; i < matchDimerB.size(); ++i) { + pair pr(i + monAmatch.size(), matchDimerB.at(i)); monBmatch.push_back(pr); } refreshSwapOrder(monBmatch, monAmatch); updateSwapLists(monBmatch, monAmatch, p_atom_mat_S); S_new = - createNewMatrix(p_atom_mat_S, S->get_rows(), S->get_cols(), "Columns"); + createNewMatrix(p_atom_mat_S, S.rows(), S.cols(), "Columns"); } S = S_new; { - list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Rows"); + list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Rows"); vector> monAmatch; - for (unsigned i = 1; i <= matchDimerA.size(); ++i) { - pair pr(i, matchDimerA.at(i - 1)); + for (unsigned i = 0; i < matchDimerA.size(); ++i) { + pair pr(i, matchDimerA.at(i)); monAmatch.push_back(pr); } vector> monBmatch; - for (unsigned i = 1; i <= matchDimerB.size(); ++i) { - pair pr(i + monAmatch.size(), matchDimerB.at(i - 1)); + for (unsigned i = 0; i < matchDimerB.size(); ++i) { + pair pr(i + monAmatch.size(), matchDimerB.at(i)); monBmatch.push_back(pr); } refreshSwapOrder(monBmatch, monAmatch); updateSwapLists(monBmatch, monAmatch, p_atom_mat_S); - S_new = createNewMatrix(p_atom_mat_S, S->get_rows(), S->get_cols(), "Rows"); + S_new = createNewMatrix(p_atom_mat_S, S.rows(), S.cols(), "Rows"); } // Return the correctly swapped dimerCoef @@ -728,38 +668,38 @@ Eigen::MatrixXd unscramble_S(const std::vector &matchDimerA, // Same as the above function but here we are assuming counterpoise correction // is being used and thus we do not need to match with both monomer A and // monomer B but only need to match with A. -Matrix *unscramble_S(const std::vector &matchDimerA, - const std::vector &basisFuncP, Matrix *S) { +Eigen::MatrixXd unscramble_S(const std::vector &matchDimerA, + const std::vector &basisFuncP, Eigen::MatrixXd & S) { - Matrix *S_new; + MatrixXd & S_new(S.rows(),S.cols()); { - list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Columns"); + list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Columns"); vector> monAmatch; - for (unsigned i = 1; i <= matchDimerA.size(); ++i) { - pair pr(i, matchDimerA.at(i - 1)); + for (unsigned i = 0; i < matchDimerA.size(); ++i) { + pair pr(i, matchDimerA.at(i)); monAmatch.push_back(pr); } refreshSwapOrder(monAmatch); updateSwapLists(monAmatch, p_atom_mat_S); S_new = - createNewMatrix(p_atom_mat_S, S->get_rows(), S->get_cols(), "Columns"); + createNewMatrix(p_atom_mat_S, S.rows(), S.cols(), "Columns"); } S = S_new; { - list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Rows"); + list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Rows"); vector> monAmatch; - for (unsigned i = 1; i <= matchDimerA.size(); ++i) { - pair pr(i, matchDimerA.at(i - 1)); + for (unsigned i = 0; i < matchDimerA.size(); ++i) { + pair pr(i, matchDimerA.at(i)); monAmatch.push_back(pr); } refreshSwapOrder(monAmatch); updateSwapLists(monAmatch, p_atom_mat_S); - S_new = createNewMatrix(p_atom_mat_S, S->get_rows(), S->get_cols(), "Rows"); + S_new = createNewMatrix(p_atom_mat_S, S.rows(), S.cols(), "Rows"); } // Return the correctly swapped dimerCoef @@ -774,28 +714,28 @@ TransferComplex::TransferComplex(Eigen::MatrixXd mat1Coef, Eigen::MatrixXd mat2C unscrambled_ = false; counterPoise_ = cp; // Consistency check - if (matS->get_cols() != matPCoef->get_cols()) { + if (matS.cols() != matPCoef.cols()) { throw invalid_argument( "The overlap matrix must have the same number " "of basis functions as the dimer"); } if (cp) { - if (mat1Coef->get_cols() != matPCoef->get_cols()) { + if (mat1Coef.cols() != matPCoef.cols()) { throw invalid_argument( "Counter poise correction requires that the" " monomers have the same number of coefficients as the dimer. " "Your monomer 1 does not"); } - if (mat2Coef->get_cols() != matPCoef->get_cols()) { + if (mat2Coef.cols() != matPCoef.cols()) { throw invalid_argument( "Counter poise correction requires that the" " monomers have the same number of coefficients as the dimer. " "Your monomer 2 does not"); } } else { - int total_cols = mat1Coef->get_cols() + mat2Coef->get_cols(); + int total_cols = mat1Coef.cols() + mat2Coef.cols(); - if (total_cols > matPCoef->get_cols()) { + if (total_cols > matPCoef.cols()) { throw invalid_argument( "Counter poise has not been specified and your " "monomers have more basis function cols than your dimer"); diff --git a/src/tests/test_logreader.cpp b/src/tests/test_logreader.cpp index dfca2cc..be908eb 100644 --- a/src/tests/test_logreader.cpp +++ b/src/tests/test_logreader.cpp @@ -25,7 +25,7 @@ int main(void) { auto orb_info = lr.getOrbitalInfo(); auto Soverlap = lr.getOverlapMatrix(); - cout << Soverlap->get_rows() << endl; + cout << Soverlap.rows() << endl; auto Alpha = lr.getOE("Alpha"); auto basisFuncCount = lr.getBasisFuncCount(); diff --git a/src/tests/test_qc_functions.cpp b/src/tests/test_qc_functions.cpp index 0f94b9a..237901e 100644 --- a/src/tests/test_qc_functions.cpp +++ b/src/tests/test_qc_functions.cpp @@ -1,9 +1,9 @@ -#include "../libcatnip/matrix.hpp" +//#include "../libcatnip/matrix.hpp" #include "../libcatnip/qc_functions.hpp" #include #include #include - +#include using namespace catnip; using namespace std; @@ -11,20 +11,21 @@ int main(void) { cout << "Testing: unscramble_Coef" << endl; { - Matrix* dimerCoef = new Matrix(8, 8); - for (int i = 1; i <= 8; ++i) { - dimerCoef->set_elem(1.3, i, 1); - dimerCoef->set_elem(0.2, i, 3); - dimerCoef->set_elem(82.4, i, 4); - dimerCoef->set_elem(9.4, i, 5); - dimerCoef->set_elem(3.4, i, 6); - dimerCoef->set_elem(-3.0, i, 8); + Eigen::MatrixXd dimerCoef = Eigen::MatrixXd::Zero(8, 8); + for (int i = 0; i < 8; ++i) { + dimerCoef(i, 0) = 1.3; + dimerCoef(i, 2) = 0.2; + dimerCoef(i, 3) = 82.4; + dimerCoef(i, 4) = 9.4; + dimerCoef(i, 5) = 3.4; + dimerCoef(i, 7) = -3.0; } // Our coefficient matrix should look like this // - // col 1 col 2 col 3 col 4 col 5 col 6 col 7 col 8 + // col 0 col 1 col 2 col 3 col 4 col 5 col 6 col 7 // _______________________________________________________ + // row 0 | 1.3 0.0 0.2 82.4 9.4 3.4 0.0 -3.0 // row 1 | 1.3 0.0 0.2 82.4 9.4 3.4 0.0 -3.0 // row 2 | 1.3 0.0 0.2 82.4 9.4 3.4 0.0 -3.0 // row 3 | 1.3 0.0 0.2 82.4 9.4 3.4 0.0 -3.0 @@ -32,51 +33,49 @@ int main(void) { // row 5 | 1.3 0.0 0.2 82.4 9.4 3.4 0.0 -3.0 // row 6 | 1.3 0.0 0.2 82.4 9.4 3.4 0.0 -3.0 // row 7 | 1.3 0.0 0.2 82.4 9.4 3.4 0.0 -3.0 - // row 8 | 1.3 0.0 0.2 82.4 9.4 3.4 0.0 -3.0 // atm3 atm1 atm1 atm5 atm4 atm4 atm2 atm2 // Contains the x y and z position of atoms in monomer A - Matrix* coordA = new Matrix(2, 3); + Eigen::MatrixXd coordA(2, 3); // Atom 1 at (1.0,1.0,1.0) // Atom 2 at (0.0,0.0,0.0) - coordA->set_elem(1.0, 1, 1); - coordA->set_elem(1.0, 1, 2); - coordA->set_elem(1.0, 1, 3); + coordA << 1.0, 1.0, 1.0, + 0.0, 0.0, 0.0; // Contains the x y and z position of atoms in monomer B - Matrix* coordB = new Matrix(3, 3); + Eigen::MatrixXd coordB(3, 3); // Atom 3 at (1.0,0.0,0.0) // Atom 4 at (2.0,0.0,0.0) // Atom 5 at (3.0,0.0,0.0) - coordB->set_elem(1.0, 1, 1); - coordB->set_elem(2.0, 2, 1); - coordB->set_elem(3.0, 3, 1); + coordB << 1.0, 0.0, 0.0, + 2.0, 0.0, 0.0, + 3.0, 0.0, 0.0; - Matrix* coordDimer = new Matrix(5, 3); + Eigen::MatrixXd coordDimer(5, 3); // Arrange atoms in the dimer so they do not appear in the // same order as the monomers - // row1 Atom 3 - coordDimer->set_elem(1.0, 1, 1); - // row2 Atom 1 - coordDimer->set_elem(1.0, 2, 1); - coordDimer->set_elem(1.0, 2, 2); - coordDimer->set_elem(1.0, 2, 3); - // row3 Atom 5 - coordDimer->set_elem(3.0, 3, 1); - // row4 Atom 4 - coordDimer->set_elem(2.0, 4, 1); - // row5 Atom 2 (0.0,0.0,0.0) + // Atom 3 1.0, 0.0, 0.0 + // Atom 1 1.0, 1.0, 1.0 + // Atom 5 3.0, 0.0, 0.0 + // Atom 4 2.0, 0.0, 0.0 + // Atom 2 0.0, 0.0, 0.0 - vector matchA = coordA->matchRow(*coordDimer, 2); - vector matchB = coordB->matchRow(*coordDimer, 2); + coordDimer << 1.0, 0.0, 0.0, + 1.0, 1.0, 1.0, + 3.0, 0.0, 0.0, + 2.0, 0.0, 0.0, + 0.0, 0.0, 0.0; - assert(matchA.at(0) == 2); - assert(matchA.at(1) == 5); + vector matchA = matchRow(coordA,coordDimer, 2); + vector matchB = matchRow(coordB,coordDimer, 2); - assert(matchB.at(0) == 1); + assert(matchA.at(0) == 1); + assert(matchA.at(1) == 4); + + assert(matchB.at(0) == 0); assert(matchB.at(1) == 4); - assert(matchB.at(2) == 3); + assert(matchB.at(2) == 2); vector basisFuncDimer; // Basis functions per atom @@ -103,8 +102,9 @@ int main(void) { // According to the basis functions and the atom positions the current // coef table for monomer A should look like this - // col 1 col 2 col 3 col 4 + // col 0 col 1 col 2 col 3 // ____________________________ + // row 0 | 0.0 0.2 0.0 -3.0 // row 1 | 0.0 0.2 0.0 -3.0 // row 2 | 0.0 0.2 0.0 -3.0 // row 3 | 0.0 0.2 0.0 -3.0 @@ -112,7 +112,6 @@ int main(void) { // row 5 | 0.0 0.2 0.0 -3.0 // row 6 | 0.0 0.2 0.0 -3.0 // row 7 | 0.0 0.2 0.0 -3.0 - // row 8 | 0.0 0.2 0.0 -3.0 // atm1 atm1 atm2 atm2 cerr << "Before passing in" << endl; @@ -122,7 +121,8 @@ int main(void) { // If we correct the dimer coefficient matrix to line up with the // coefficients of the monomers it should look like this // - // Col 1 Col 2 Col 3 Col 4 Col 5 Col 6 Col 7 Col 8 + // Col 0 Col 1 Col 2 Col 3 Col 4 Col 5 Col 6 Col 7 + // Row 0 1.3 9.4 3.4 82.4 0 0.2 0 -3 // Row 1 1.3 9.4 3.4 82.4 0 0.2 0 -3 // Row 2 1.3 9.4 3.4 82.4 0 0.2 0 -3 // Row 3 1.3 9.4 3.4 82.4 0 0.2 0 -3 @@ -130,101 +130,99 @@ int main(void) { // Row 5 1.3 9.4 3.4 82.4 0 0.2 0 -3 // Row 6 1.3 9.4 3.4 82.4 0 0.2 0 -3 // Row 7 1.3 9.4 3.4 82.4 0 0.2 0 -3 - // Row 8 1.3 9.4 3.4 82.4 0 0.2 0 -3 cerr << "Calling unscramble" << endl; - auto NewCoef = unscramble_Coef(matchB, matchA, basisFuncDimer, dimerCoef); - - cerr << *NewCoef << endl; - - for (int i = 1; i <= 8; ++i) { - assert(static_cast(NewCoef->get_elem(i, 1) * 10) == 13); - assert(static_cast(NewCoef->get_elem(i, 2) * 10) == 94); - assert(static_cast(NewCoef->get_elem(i, 3) * 10) == 34); - assert(static_cast(NewCoef->get_elem(i, 4) * 10) == 824); - assert(static_cast(NewCoef->get_elem(i, 5)) == 0); - assert(static_cast(NewCoef->get_elem(i, 6) * 10) == 2); - assert(static_cast(NewCoef->get_elem(i, 7)) == 0); - assert(static_cast(NewCoef->get_elem(i, 8)) == -3); + Eigen::MatrixXd NewCoef = unscramble_Coef(matchB, matchA, basisFuncDimer, dimerCoef); + + cerr << NewCoef << endl; + + for (int i = 0; i < 8; ++i) { + assert(static_cast(NewCoef(i, 0) * 10) == 13); + assert(static_cast(NewCoef(i, 1) * 10) == 94); + assert(static_cast(NewCoef(i, 2) * 10) == 34); + assert(static_cast(NewCoef(i, 3) * 10) == 824); + assert(static_cast(NewCoef(i, 4)) == 0); + assert(static_cast(NewCoef(i, 5) * 10) == 2); + assert(static_cast(NewCoef(i, 6)) == 0); + assert(static_cast(NewCoef(i, 7)) == -3); } } cout << "Testing: unscramble_S_Coef" << endl; { - Matrix* SCoef = new Matrix(8, 8); - for (int i = 1; i <= 8; ++i) { - SCoef->set_elem(1.3, i, 2); - SCoef->set_elem(1.3, i, 3); - SCoef->set_elem(4.0, i, 4); + Eigen::MatrixXd SCoef = Eigen::MatrixXd::Zero(8, 8); + for (int i = 0; i < 8; ++i) { + SCoef(i, 1) = 1.3; + SCoef(i, 2) = 1.3; + SCoef(i, 3) = 4.0; } - for (int i = 1; i <= 8; ++i) { - SCoef->set_elem(1.3, 2, i); - SCoef->set_elem(1.3, 3, i); - SCoef->set_elem(4.0, 4, i); + for (int i = 0; i < 8; ++i) { + SCoef(1, i) = 1.3; + SCoef(2, i) = 1.3; + SCoef(3, i) = 4.0; } - SCoef->set_elem(6.0, 2, 4); - SCoef->set_elem(6.0, 3, 4); - SCoef->set_elem(6.0, 4, 2); - SCoef->set_elem(6.0, 4, 3); + SCoef(1, 3) = 6.0; + SCoef(2, 3) = 6.0; + SCoef(3, 1) = 6.0; + SCoef(3, 2) = 6.0; // Our coefficient matrix should look like this // - // col 1 col 2 col 3 col 4 col 5 col 6 col 7 col 8 + // col 0 col 1 col 2 col 3 col 4 col 5 col 6 col 7 // _______________________________________________________ - // atm 3 row 1 | 0.0 1.3 1.3 4.0 0.0 0.0 0.0 0.0 + // atm 3 row 0 | 0.0 1.3 1.3 4.0 0.0 0.0 0.0 0.0 + // atm 1 row 1 | 1.3 1.3 1.3 6.0 1.3 1.3 1.3 1.3 // atm 1 row 2 | 1.3 1.3 1.3 6.0 1.3 1.3 1.3 1.3 - // atm 1 row 3 | 1.3 1.3 1.3 6.0 1.3 1.3 1.3 1.3 - // atm 5 row 4 | 4.0 6.0 6.0 4.0 4.0 4.0 4.0 4.0 + // atm 5 row 3 | 4.0 6.0 6.0 4.0 4.0 4.0 4.0 4.0 + // atm 4 row 4 | 0.0 1.3 1.3 4.0 0.0 0.0 0.0 0.0 // atm 4 row 5 | 0.0 1.3 1.3 4.0 0.0 0.0 0.0 0.0 - // atm 4 row 6 | 0.0 1.3 1.3 4.0 0.0 0.0 0.0 0.0 + // atm 2 row 6 | 0.0 1.3 1.3 4.0 0.0 0.0 0.0 0.0 // atm 2 row 7 | 0.0 1.3 1.3 4.0 0.0 0.0 0.0 0.0 - // atm 2 row 8 | 0.0 1.3 1.3 4.0 0.0 0.0 0.0 0.0 // atm3 atm1 atm1 atm5 atm4 atm4 atm2 atm2 // Contains the x y and z position of atoms in monomer A - Matrix* coordA = new Matrix(2, 3); + Eigen::MatrixXd coordA(2, 3); // Atom 1 at (1.0,1.0,1.0) // Atom 2 at (0.0,0.0,0.0) - coordA->set_elem(1.0, 1, 1); - coordA->set_elem(1.0, 1, 2); - coordA->set_elem(1.0, 1, 3); + coordA << 1.0, 1.0, 1.0, + 0.0, 0.0, 0.0; // Contains the x y and z position of atoms in monomer B - Matrix* coordB = new Matrix(3, 3); + Eigen::MatrixXd coordB(3, 3); // Atom 3 at (1.0,0.0,0.0) // Atom 4 at (2.0,0.0,0.0) // Atom 5 at (3.0,0.0,0.0) - coordB->set_elem(1.0, 1, 1); - coordB->set_elem(2.0, 2, 1); - coordB->set_elem(3.0, 3, 1); + coordB << 1.0, 0.0, 0.0, + 2.0, 0.0, 0.0, + 3.0, 0.0, 0.0; - Matrix* coordDimer = new Matrix(5, 3); + Eigen::MatrixXd coordDimer = Eigen::MatrixXd::Zero(5, 3); // Arrange atoms in the dimer so they do not appear in the // same order as the monomers // row1 Atom 3 - coordDimer->set_elem(1.0, 1, 1); + coordDimer(0, 0) = 1.0; // row2 Atom 1 - coordDimer->set_elem(1.0, 2, 1); - coordDimer->set_elem(1.0, 2, 2); - coordDimer->set_elem(1.0, 2, 3); + coordDimer(1, 0) = 1.0; + coordDimer(1, 1) = 1.0; + coordDimer(1, 2) = 1.0; // row3 Atom 5 - coordDimer->set_elem(3.0, 3, 1); + coordDimer(2, 0) = 3.0; // row4 Atom 4 - coordDimer->set_elem(2.0, 4, 1); + coordDimer(3, 0) = 2.0; // row5 Atom 2 (0.0,0.0,0.0) - vector matchA = coordA->matchRow(*coordDimer, 2); - vector matchB = coordB->matchRow(*coordDimer, 2); + vector matchA = matchRow(coordA,coordDimer, 2); + vector matchB = matchRow(coordB,coordDimer, 2); - assert(matchA.at(0) == 2); - assert(matchA.at(1) == 5); + assert(matchA.at(0) == 1); + assert(matchA.at(1) == 4); - assert(matchB.at(0) == 1); - assert(matchB.at(1) == 4); - assert(matchB.at(2) == 3); + assert(matchB.at(0) == 0); + assert(matchB.at(1) == 3); + assert(matchB.at(2) == 2); vector basisFuncDimer; // Basis functions per atom @@ -256,37 +254,37 @@ int main(void) { // If we correct the dimer coefficient matrix to line up with the // coefficients of the monomers it should look like this // - // Col 1 Col 2 Col 3 Col 4 Col 5 Col 6 Col 7 Col 8 + // Col 0 Col 1 Col 2 Col 3 Col 4 Col 5 Col 6 Col 7 + // Row 0 0 0 0 4 1.3 1.3 0 0 // Row 1 0 0 0 4 1.3 1.3 0 0 // Row 2 0 0 0 4 1.3 1.3 0 0 - // Row 3 0 0 0 4 1.3 1.3 0 0 - // Row 4 4 4 4 4 6 6 4 4 + // Row 3 4 4 4 4 6 6 4 4 + // Row 4 1.3 1.3 1.3 6 1.3 1.3 1.3 1.3 // Row 5 1.3 1.3 1.3 6 1.3 1.3 1.3 1.3 - // Row 6 1.3 1.3 1.3 6 1.3 1.3 1.3 1.3 + // Row 6 0 0 0 4 1.3 1.3 0 0 // Row 7 0 0 0 4 1.3 1.3 0 0 - // Row 8 0 0 0 4 1.3 1.3 0 0 cerr << "Calling unscramble" << endl; - auto NewCoef = unscramble_S(matchB, matchA, basisFuncDimer, SCoef); + Eigen::MatrixXd NewCoef = unscramble_S(matchB, matchA, basisFuncDimer, SCoef); - cerr << *NewCoef << endl; + cerr << NewCoef << endl; - for (int i = 1; i <= 8; ++i) { - if (i != 4) { - assert(static_cast(NewCoef->get_elem(i, 5) * 10) == 13); - assert(static_cast(NewCoef->get_elem(i, 6) * 10) == 13); + for (int i = 0; i < 8; ++i) { + if (i != 3) { + assert(static_cast(NewCoef(i, 4) * 10) == 13); + assert(static_cast(NewCoef(i, 5) * 10) == 13); - assert(static_cast(NewCoef->get_elem(5, i) * 10) == 13); - assert(static_cast(NewCoef->get_elem(6, i) * 10) == 13); + assert(static_cast(NewCoef(4, i) * 10) == 13); + assert(static_cast(NewCoef(5, i) * 10) == 13); } } - for (int i = 1; i <= 8; ++i) { - if (i == 5 || i == 6) { - assert(static_cast(NewCoef->get_elem(i, 4)) == 6); - assert(static_cast(NewCoef->get_elem(4, i)) == 6); + for (int i = 0; i < 8; ++i) { + if (i == 4 || i == 5) { + assert(static_cast(NewCoef(i, 3)) == 6); + assert(static_cast(NewCoef(3, i)) == 6); } else { - assert(static_cast(NewCoef->get_elem(4, i)) == 4); - assert(static_cast(NewCoef->get_elem(i, 4)) == 4); + assert(static_cast(NewCoef(3, i)) == 4); + assert(static_cast(NewCoef(i, 3)) == 4); } } } From 8239b144a2bc48a00f7bc410c9477ae13dfd712d Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Sun, 28 Apr 2019 19:51:10 -0600 Subject: [PATCH 08/68] Fixing compiler errors --- CMakeLists.txt | 6 +++- src/libcatnip/io/io.hpp | 1 - src/libcatnip/matrix.cpp | 4 +-- src/libcatnip/matrix.hpp | 5 +-- src/libcatnip/qc_functions.cpp | 56 +++++++++++++++++++++------------- src/libcatnip/qc_functions.hpp | 20 +++++------- src/tests/CMakeLists.txt | 6 ++-- src/tools/main.cpp | 3 +- 8 files changed, 56 insertions(+), 45 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 858a1bd..bfdae7d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,10 @@ configure_file( # Find bash it is important for testing using scripts find_program (BASH_PROGRAM bash) find_library (GCOV gcov) +find_package (Eigen3 3.3 REQUIRED NO_MODULE) +if (TARGET Eigen3::Eigen) + message("-- Eigen found") +endif(TARGET Eigen3::Eigen) add_definitions(-DLOG_LEVEL=${LOG_LEVEL}) ############################################################################## @@ -116,5 +120,5 @@ if(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") target_link_libraries(calc_J gcov) set_source_files_properties( src/tools/main.cpp PROPERTIES COMPILE_FLAGS ${COVERAGE_FLAGS}) endif(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") -target_link_libraries(calc_J libcatnip ${COMMON_LIBRARIES}) +target_link_libraries(calc_J libcatnip ${COMMON_LIBRARIES} Eigen3::Eigen) install( TARGETS calc_J DESTINATION bin) diff --git a/src/libcatnip/io/io.hpp b/src/libcatnip/io/io.hpp index ce57b8e..f38cf5d 100644 --- a/src/libcatnip/io/io.hpp +++ b/src/libcatnip/io/io.hpp @@ -1,6 +1,5 @@ #ifndef _CATNIP_IO_HPP #define _CATNIP_IO_HPP -#include "../matrix.hpp" #include "../parameters.hpp" #include "argumentparser.hpp" #include diff --git a/src/libcatnip/matrix.cpp b/src/libcatnip/matrix.cpp index 14f2af0..d84c54d 100644 --- a/src/libcatnip/matrix.cpp +++ b/src/libcatnip/matrix.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include "matrix.hpp" @@ -18,7 +18,7 @@ string double_tos(double f, int nd) { return ostr.str(); } -vector matchRow(const Matrix & mat1, const Matrix & mat2, const int sf) { +vector matchRow(const Eigen::MatrixXd & mat1, const Eigen::MatrixXd & mat2, const int sf) { if (mat1.cols() != mat2.cols()) { throw invalid_argument( diff --git a/src/libcatnip/matrix.hpp b/src/libcatnip/matrix.hpp index 903327a..36529f6 100644 --- a/src/libcatnip/matrix.hpp +++ b/src/libcatnip/matrix.hpp @@ -2,9 +2,10 @@ #ifndef MATRIX_HELPER_HPP #define MATRIX_HELPER_HPP -namespace catnip { #include -#include +#include + +namespace catnip { /** * Responsible for matching the rows between two matrices Returns which row diff --git a/src/libcatnip/qc_functions.cpp b/src/libcatnip/qc_functions.cpp index be8bbdb..eb681a2 100644 --- a/src/libcatnip/qc_functions.cpp +++ b/src/libcatnip/qc_functions.cpp @@ -14,21 +14,23 @@ #include "matrix.hpp" #include "qc_functions.hpp" -using namespace std; - +#include +#include namespace catnip { + using namespace std; + unordered_map> findRank(Eigen::VectorXd &Orb_E_Alpha, Eigen::VectorXd &Orb_E_Beta) { vector> all; - for( double & val : Orb_E_Alpha){ - all.push_back(pair(val,"Alpha")); + for( int i = 0; i(Orb_E_Alpha(i),"Alpha")); } - for( double & val : Orb_E_Beta ){ - all.push_back(pair(val, "Beta")); + for( int i = 0; i(Orb_E_Beta(i), "Beta")); } sort(all.begin(), all.end(), [](const pair &P1, const pair &P2) @@ -53,12 +55,12 @@ void TransferComplex::calculate_transfer_integral_() { Eigen::MatrixXd zetaB(dimension,dimension); if (counterPoise_) { LOG("Creating zeta matrices from coefficients assuming counterpoise", 2); - zetaA = mat_1_Coef(); - zetaB = mat_2_Coef(); + zetaA = mat_1_Coef; + zetaB = mat_2_Coef; } else { LOG("Creating zeta matrices from coefficients", 2); - zetaA << mat_1_Coef(), Eigen::MatrixXd::Zeros(mat_1_Coef.rows(),mat_2_Coef.cols()); - zetaA << Eigen::MatrixXd::Zeros(mat_2_Coef.rows(),mat_1_Coef.cols()), mat_2_Coef(); + zetaA << mat_1_Coef, Eigen::MatrixXd::Zero(mat_1_Coef.rows(),mat_2_Coef.cols()); + zetaA << Eigen::MatrixXd::Zero(mat_2_Coef.rows(),mat_1_Coef.cols()), mat_2_Coef; } LOG("Creating gamma and beta matrices", 2); @@ -67,14 +69,19 @@ void TransferComplex::calculate_transfer_integral_() { LOG("Calculating S_AB", 2); - Eigen::MatrixXd S_AB = gammaB * gammaA.transpose(); - Eigen::MatrixXd S_AB_inv_sqrt = S_AB.operatorInverseSqrt(); + S_AB.resize(gammaB.rows(),gammaA.cols()); + S_AB = gammaB * gammaA.transpose(); + Eigen::SelfAdjointEigenSolver eigen_solver(S_AB); + Eigen::MatrixXd S_AB_inv_sqrt = eigen_solver.operatorInverseSqrt(); - Eigen::MatrixXd Energy = vec_P_OE.asDiagona(); + auto Energy = Eigen::MatrixXd::Identity(vec_P_OE.size(),vec_P_OE.size()); + Energy *= vec_P_OE.transpose(); - Eigen::MatrixXd Hamiltonian = mat_P_Coef * mat_S * mat_P_Coef.transpose(); - - Eigen::MatrixXd Hamiltonian_eff = S_AB_inv_sqrt * Hamiltonian * S_AB_inv_sqrt.transpose(); + Hamiltonian.resize(mat_S.rows(),mat_S.cols()); + Hamiltonian = mat_P_Coef * mat_S * mat_P_Coef.transpose(); + + Hamiltonian_eff.resize(Hamiltonian.rows(),Hamiltonian.cols()); + Hamiltonian_eff = S_AB_inv_sqrt * Hamiltonian * S_AB_inv_sqrt.transpose(); } @@ -156,7 +163,9 @@ void TransferComplex::printTransferIntegral( // Find the transfer integral between two orbitals. // pair string - Either HOMO or LUMO // int - is the orbital number HOMO-3 LUMO+5 -void TransferComplex::printTransferIntegral_(pair Orbital1, pair Orbital2) const { +void TransferComplex::printTransferIntegral_( + const pair Orbital1, + const pair Orbital2) const { int obrital1_num = 0; int obrital2_num = 0; @@ -168,8 +177,8 @@ void TransferComplex::printTransferIntegral_(pair Orbital1, pair //#include "matrix.hpp" -#include +#include namespace catnip { @@ -53,16 +53,10 @@ class TransferComplex { **/ bool orbitalValid_(const std::pair & orbital) const; - void calculate_transfer_integral_( - const Eigen::MatrixXd & mat_1_Coef, - const Eigen::MatrixXd & mat_2_Coef, - Eigen::MatrixXd mat_P_Coef, - const Eigen::MatrixXd & mat_S, - const Eigen::VectorXd& vec_P_OE, - bool counterPoise_); + void calculate_transfer_integral_(); - void printTransferIntegral_(std::pair Orbital1, - std::pair Orbital2) const; + void printTransferIntegral_(const std::pair & Orbital1, + const std::pair & Orbital2) const; public: TransferComplex( Eigen::MatrixXd mat1Coef, @@ -89,14 +83,14 @@ class TransferComplex { // // monomer1 LUMO-3 // monomer2 HOMO - double calcJ(const std::map& orbitaltype, + void calcJ(const std::map& orbitaltype, const std::map& orbitalnum); /** * \brief Print the transfer integral specified **/ - void printTransferIntegral(std::pair Orbital1, - std::pair Orbital2) const; + void printTransferIntegral(const std::pair & Orbital1, + const std::pair & Orbital2) const; /** * \brief Print All info in matrix form diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index bf8fc4b..134ca4b 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -28,7 +28,7 @@ if(ENABLE_TESTS) if(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") set_source_files_properties( ${PROG}.cpp PROPERTIES COMPILE_FLAGS ${COVERAGE_FLAGS} ) endif(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") - target_link_libraries(unit_${PROG} libcatnip) + target_link_libraries(unit_${PROG} libcatnip Eigen3::Eigen) add_test(unit_${PROG} unit_${PROG}) endforeach(PROG) endif(ENABLE_TESTS) @@ -44,7 +44,7 @@ if(ENABLE_INTEGRATION_TESTS) set_source_files_properties( ${PROG}.cpp PROPERTIES COMPILE_FLAGS ${COVERAGE_FLAGS}) endif(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") - target_link_libraries(integration${PROG} libcatnip) + target_link_libraries(integration${PROG} libcatnip Eigen3::Eigen) add_test(integration${PROG} integration${PROG}) endforeach(PROG) @@ -53,7 +53,7 @@ if(ENABLE_INTEGRATION_TESTS) if(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") set_source_files_properties( test_io.cpp PROPERTIES COMPILE_FLAGS ${COVERAGE_FLAGS}) endif(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") - target_link_libraries(test_io libcatnip) + target_link_libraries(test_io libcatnip Eigen3::Eigen) add_test(regression_test_io test_io -p_P "${PROJECT_SOURCE_DIR}/GAUSSIANFILES/30/30_pair.pun" -p_1 "${PROJECT_SOURCE_DIR}/GAUSSIANFILES/30/ref.pun" -p_2 "${PROJECT_SOURCE_DIR}/GAUSSIANFILES/30/30_2.pun") add_custom_command(TARGET test_io diff --git a/src/tools/main.cpp b/src/tools/main.cpp index 580c84e..890797e 100644 --- a/src/tools/main.cpp +++ b/src/tools/main.cpp @@ -17,13 +17,12 @@ #include "../libcatnip/io/file_readers/punreader.hpp" #include "../libcatnip/io/io.hpp" #include "../libcatnip/log.hpp" -//#include "../libcatnip/matrix.hpp" #include "../libcatnip/parameters.hpp" #include "../libcatnip/qc_functions.hpp" #include "../libcatnip/calcJconfig.hpp" -#include +#include using namespace catnip; using namespace std; From 23f393fd21a37acd47d9fc5e210e8962ea64445b Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Mon, 29 Apr 2019 13:25:26 -0600 Subject: [PATCH 09/68] First successful compile --- src/libcatnip/io/file_readers/filereader.hpp | 2 +- src/libcatnip/io/file_readers/logreader.cpp | 29 ++------- src/libcatnip/io/file_readers/logreader.hpp | 11 ++-- src/libcatnip/io/file_readers/punreader.cpp | 18 +++--- src/libcatnip/io/file_readers/punreader.hpp | 5 +- src/libcatnip/matrix.cpp | 18 +++--- src/libcatnip/matrix.hpp | 1 + src/libcatnip/qc_functions.cpp | 67 ++++++++++---------- src/libcatnip/qc_functions.hpp | 52 +++++++++------ src/tests/test_qc_functions.cpp | 2 +- src/tools/main.cpp | 28 ++++---- 11 files changed, 115 insertions(+), 118 deletions(-) diff --git a/src/libcatnip/io/file_readers/filereader.hpp b/src/libcatnip/io/file_readers/filereader.hpp index 91d374d..55d2f1d 100644 --- a/src/libcatnip/io/file_readers/filereader.hpp +++ b/src/libcatnip/io/file_readers/filereader.hpp @@ -1,4 +1,4 @@ - +#pragma once #ifndef _CATNIP_FILEREADER_HPP_ #define _CATNIP_FILEREADER_HPP_ diff --git a/src/libcatnip/io/file_readers/logreader.cpp b/src/libcatnip/io/file_readers/logreader.cpp index b3624be..1657492 100644 --- a/src/libcatnip/io/file_readers/logreader.cpp +++ b/src/libcatnip/io/file_readers/logreader.cpp @@ -7,7 +7,7 @@ #include #include -#include +#include #include "../../log.hpp" #include "../../string_support.hpp" #include "logreader.hpp" @@ -168,22 +168,10 @@ void LogReader::OverlapSectionReader(void *ptr) { //Matrix *mat_S = new Matrix(countCoef, countCoef); Eigen::MatrixXd matrix_S(countCoef,countCoef); + for (size_t row_ind = 0; row_ind < first_coefs.size(); ++row_ind) { -// vector row = first_coefs.at(row_ind); - matrix_S.row(row_ind) << first_coefs.at(row_ind); - // size_t col_ind = 1; -// size_t col_ind = 0; - // for (double & val : row) { - // mat_S->set_elem(val, row_ind + 1, col_ind); - // matrix_S(row_ind,col_ind) = val; - // Because diagonally symetric -// if (row_ind + 1 != col_ind) { - // if (row_ind != col_ind) { - //mat_S->set_elem(val, col_ind, row_ind + 1); - // matrix_S(col_ind,row_ind) = val; - // } - // ++col_ind; - //} + Eigen::Map eigen_vec((first_coefs.at(row_ind).data()),first_coefs.at(row_ind).size()); + matrix_S.row(row_ind) = eigen_vec; } int sectionReads = countCoef / 5; @@ -210,14 +198,9 @@ void LogReader::OverlapSectionReader(void *ptr) { string expon = grabStrAfterFirstOccurance(s_coef, "D"); double value = stod(val) * pow(10.0, stod(expon)); - //mat_S->set_elem(value, sectionCoef + 1, - // currentSectionStart + localCoefCount); matrix_S(sectionCoef,currentSectionStart + localCoefCount) = value; - //if ((sectionCoef + 1) != (currentSectionStart + localCoefCount)) { if ((sectionCoef) != (currentSectionStart + localCoefCount)) { matrix_S(currentSectionStart + localCoefCount,sectionCoef) = value; - //mat_S->set_elem(value, currentSectionStart + localCoefCount, - // sectionCoef + 1); } ++localCoefCount; } @@ -227,7 +210,7 @@ void LogReader::OverlapSectionReader(void *ptr) { currentSectionStart += 5; getline(LR_ptr->fid_, line); } - LR_ptr->S_ = mat_S; + LR_ptr->S_ = matrix_S; LOG("Success reading Overlap coefficients from .log file", 2); return; } @@ -253,7 +236,7 @@ void LogReader::ReadOrbEnergies(const string &orb_type) { auto vec_str = splitSt(line); for (size_t inc = 4; inc < vec_str.size(); inc++) { - OREnergies[orb_type].push_back((double)atof(vec_str.at(inc).c_str())); + OREnergies[orb_type].push_back(stod(vec_str.at(inc))); if (occFound) homoLevel[orb_type]++; } } else { diff --git a/src/libcatnip/io/file_readers/logreader.hpp b/src/libcatnip/io/file_readers/logreader.hpp index 4583ed3..4ec11a4 100644 --- a/src/libcatnip/io/file_readers/logreader.hpp +++ b/src/libcatnip/io/file_readers/logreader.hpp @@ -1,13 +1,14 @@ - +#pragma once #ifndef _CATNIP_LOGREADER_HPP_ #define _CATNIP_LOGREADER_HPP_ +#include +#include #include -//#include "../../matrix.hpp" #include "filereader.hpp" -#include +#include // Gaussian log file reader namespace catnip { @@ -21,8 +22,8 @@ class LogReader : public FileReader { explicit LogReader(const std::string &str); orb_cont getOrbitalInfo() const { return orb_; } Eigen::MatrixXd getOverlapMatrix() const { return S_; } - std::vector getOE(const std::string &orb_type) const { - return OREnergies.at(orb_type); + Eigen::VectorXd getOE(const std::string &orb_type) { + return Eigen::Map(OREnergies.at(orb_type).data(),OREnergies.at(orb_type).size()); } int getHOMOLevel(const std::string &orb_type) const { return homoLevel.at(orb_type); diff --git a/src/libcatnip/io/file_readers/punreader.cpp b/src/libcatnip/io/file_readers/punreader.cpp index 669693b..0dee70d 100644 --- a/src/libcatnip/io/file_readers/punreader.cpp +++ b/src/libcatnip/io/file_readers/punreader.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -11,7 +12,7 @@ #include "../../string_support.hpp" #include "punreader.hpp" -#include +#include using namespace catnip; using namespace std; @@ -31,7 +32,7 @@ void PunReader::registerSections_() { FileReader::registerSections_(); } -MatrixXd PunReader::getCoefsMatrix(const string &orb_type) { +Eigen::MatrixXd PunReader::getCoefsMatrix(const string &orb_type) { if (coefs.count(orb_type) != 1) { throw invalid_argument("Coefficients for spin " + orb_type + " were not found"); @@ -95,15 +96,12 @@ void PunReader::ReadCoef(const string &orb_type) { allCoefsRead = !(foundSubStrInStr(line, orb_type)); } - //Matrix *Coefs = new Matrix(v_vec); - coefs[orb_type] = unique_ptr(Eigen::MatrixXd Coefs(v_vec.size(),v_vec.at(0).size())); - - size_t row_count = 0; - for( vector & row : v_vec) { - coefs[orb_type]->row(row_count) = row; - ++row_count; + coefs[orb_type] = unique_ptr(new Eigen::MatrixXd(v_vec.size(),v_vec.at(0).size())); + for( size_t row_ind=0; row_ind eigen_vec(v_vec.at(row_ind).data(),v_vec.at(row_ind).size()); + coefs[orb_type]->row(row_ind) = eigen_vec; } - //coefs[orb_type] = Coefs; + LOG("Success reading atomic orbital coefficients from .pun file.", 2); } diff --git a/src/libcatnip/io/file_readers/punreader.hpp b/src/libcatnip/io/file_readers/punreader.hpp index 2bc4b0b..af9128d 100644 --- a/src/libcatnip/io/file_readers/punreader.hpp +++ b/src/libcatnip/io/file_readers/punreader.hpp @@ -1,13 +1,12 @@ - +#pragma once #ifndef _CATNIP_PUNREADER_HPP_ #define _CATNIP_PUNREADER_HPP_ #include #include -//#include "../../matrix.hpp" #include "filereader.hpp" -#include +#include // Gaussian fort.7/.pun file reader namespace catnip { diff --git a/src/libcatnip/matrix.cpp b/src/libcatnip/matrix.cpp index d84c54d..cd000db 100644 --- a/src/libcatnip/matrix.cpp +++ b/src/libcatnip/matrix.cpp @@ -3,14 +3,12 @@ #include #include #include -#include +#include #include "matrix.hpp" using namespace std; - -namespace catnip { - +namespace catnip { string double_tos(double f, int nd) { ostringstream ostr; int tens = stod("1" + string(nd, '0')); @@ -70,11 +68,13 @@ vector matchCol(const Eigen::MatrixXd & mat1, return m_vec; } +Eigen::MatrixXd convert(vector> coords){ - - - - - + Eigen::MatrixXd coord_mat(coords.size(),coords.at(0).size()); + for ( size_t row_ind = 0; row_ind < coords.size();++row_ind){ + coord_mat.row(row_ind) = Eigen::Map(coords.at(row_ind).data(),coords.at(row_ind).size()); + } + return coord_mat; +} } diff --git a/src/libcatnip/matrix.hpp b/src/libcatnip/matrix.hpp index 36529f6..c236385 100644 --- a/src/libcatnip/matrix.hpp +++ b/src/libcatnip/matrix.hpp @@ -46,5 +46,6 @@ namespace catnip { const Eigen::MatrixXd &mat2, const int sig_fig); + Eigen::MatrixXd convert(std::vector> coords); } // namespace catnip #endif // MATRIX_HELPER_HPP diff --git a/src/libcatnip/qc_functions.cpp b/src/libcatnip/qc_functions.cpp index eb681a2..d40d2f7 100644 --- a/src/libcatnip/qc_functions.cpp +++ b/src/libcatnip/qc_functions.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -74,8 +75,7 @@ void TransferComplex::calculate_transfer_integral_() { Eigen::SelfAdjointEigenSolver eigen_solver(S_AB); Eigen::MatrixXd S_AB_inv_sqrt = eigen_solver.operatorInverseSqrt(); - auto Energy = Eigen::MatrixXd::Identity(vec_P_OE.size(),vec_P_OE.size()); - Energy *= vec_P_OE.transpose(); + Eigen::MatrixXd Energy = Eigen::MatrixXd::Identity(vec_P_OE.size(),vec_P_OE.size()); Hamiltonian.resize(mat_S.rows(),mat_S.cols()); Hamiltonian = mat_P_Coef * mat_S * mat_P_Coef.transpose(); @@ -164,23 +164,23 @@ void TransferComplex::printTransferIntegral( // pair string - Either HOMO or LUMO // int - is the orbital number HOMO-3 LUMO+5 void TransferComplex::printTransferIntegral_( - const pair Orbital1, - const pair Orbital2) const { + const pair& orbital1, + const pair& orbital2) const { - int obrital1_num = 0; - int obrital2_num = 0; + int orbital1_num = 0; + int orbital2_num = 0; if(orbital1.first.compare("HOMO")==0){ - assert(orbitalValid_(Orbital1)==true); - orbital1_num = Orbital1.second; + assert(orbitalValid_(orbital1)==true); + orbital1_num = orbital1.second; }else if(orbital2.first.compare("LUMO")==0){ - assert(orbitalValid_(Orbital2)==true); - orbital2_num = Orbital2.second; + assert(orbitalValid_(orbital2)==true); + orbital2_num = orbital2.second; } double J_ab = Hamiltonian(orbital1_num,orbital2_num); double e_a = Hamiltonian(orbital1_num,orbital1_num); double e_b = Hamiltonian(orbital2_num,orbital2_num); double S_ab = S_AB(orbital1_num,orbital2_num); - double J_eff = Hamiltonaian_eff(orbital1_num,orbital2_num); + double J_eff = Hamiltonian_eff(orbital1_num,orbital2_num); cout << "J_ab " << J_ab * hartreeToeV << " eV\n"; cout << "e_a " << e_a * hartreeToeV << " eV\n"; cout << "e_b " << e_b * hartreeToeV << " eV\n"; @@ -198,7 +198,7 @@ void TransferComplex::printAll() const { if(orbital_num & orbital) // list splitMatrixIntoList( const vector &subMatrixDimension, - const Eigen::MatrixXd const mat, + const Eigen::MatrixXd mat, const string &ColRowSplit) { list list_matrix; @@ -522,7 +522,7 @@ Eigen::MatrixXd mergeListOfMatrices(list &matrix_list, const in } else if (ColRowMerge.compare("Rows") == 0) { int row = 0; for (auto it = matrix_list.begin(); it != matrix_list.end(); ++it) { - Matrix *mat = *it; + Eigen::MatrixXd mat = *it; int col = 0; if (row > rows) throw runtime_error("Your new matrix is not large enough"); @@ -592,14 +592,14 @@ Eigen::MatrixXd unscramble_Coef( Eigen::MatrixXd unscramble_Coef( const std::vector &matchDimerB, const std::vector &basisFuncB, - const Eigen::MatrixXd & Coef) { + const Eigen::MatrixXd &Coef) { // Let's reduce the complexity of the problem by instead of working // with the basis functions lets just work with the atoms. We can do // this by treating all the basis functions associated with a single // atom as a block. - list atom_mat_coef = + list atom_mat_coef = splitCoefsUpByAtoms(basisFuncB, Coef, "Columns"); // Place all of monomer A atom basis functions on the left side of the @@ -623,10 +623,11 @@ Eigen::MatrixXd unscramble_Coef( // Similar to the above function but we will be moving both the rows // and columns -Eigen::MatrixXd unscramble_S(const std::vector &matchDimerA, - const std::vector &matchDimerB, - const std::vector &basisFuncP, - const Eigen::MatrixXd & S) { +Eigen::MatrixXd unscramble_S( + const std::vector &matchDimerA, + const std::vector &matchDimerB, + const std::vector &basisFuncP, + Eigen::MatrixXd S) { Eigen::MatrixXd S_new(S.rows(),S.cols()); { @@ -677,10 +678,12 @@ Eigen::MatrixXd unscramble_S(const std::vector &matchDimerA, // Same as the above function but here we are assuming counterpoise correction // is being used and thus we do not need to match with both monomer A and // monomer B but only need to match with A. -Eigen::MatrixXd unscramble_S(const std::vector &matchDimerA, - const std::vector &basisFuncP, Eigen::MatrixXd & S) { +Eigen::MatrixXd unscramble_S( + const std::vector &matchDimerA, + const std::vector &basisFuncP, + Eigen::MatrixXd S) { - MatrixXd & S_new(S.rows(),S.cols()); + Eigen::MatrixXd S_new(S.rows(),S.cols()); { list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Columns"); @@ -778,16 +781,16 @@ void TransferComplex::unscramble(const Eigen::MatrixXd &coord_1_mat, // If dealing with counter poise correction may also need to unscramble // the basis functions of the monomers if (counterPoise_) { - vector match_1_2 = coord_1_mat.matchCol(coord_2_mat, sig_fig); + vector match_1_2 = matchCol(coord_1_mat,coord_2_mat, sig_fig); LOG("Counter Poise unscrambling matrix 2 with respect to matrix 1", 2); - auto unscrambled_2_Coef = unscramble_Coef(match_1_2, basis2, mat_2_Coef); + Eigen::MatrixXd unscrambled_2_Coef = unscramble_Coef(match_1_2, basis2, mat_2_Coef); this->mat_2_Coef = unscrambled_2_Coef; - vector match_1_P = coord_1_mat.matchCol(coord_P_mat, sig_fig); + vector match_1_P = matchCol(coord_1_mat,coord_P_mat, sig_fig); - auto unscrambled_P_Coef = unscramble_Coef(match_1_P, basisP, mat_P_Coef); + Eigen::MatrixXd unscrambled_P_Coef = unscramble_Coef(match_1_P, basisP, mat_P_Coef); this->mat_P_Coef = unscrambled_P_Coef; @@ -798,13 +801,13 @@ void TransferComplex::unscramble(const Eigen::MatrixXd &coord_1_mat, } else { // Stores the rows in P that match 1 - vector match_1_P = coord_1_mat.matchCol(coord_P_mat, sig_fig); + vector match_1_P = matchCol(coord_1_mat,coord_P_mat, sig_fig); // Stores the rows in P that match 2 - vector match_2_P = coord_2_mat.matchCol(coord_P_mat, sig_fig); + vector match_2_P = matchCol(coord_2_mat,coord_P_mat, sig_fig); LOG("Unscrambling dimer matrix with respect to matrix 1 and 2", 2); - auto unscrambled_P_Coef = + Eigen::MatrixXd unscrambled_P_Coef = unscramble_Coef(match_1_P, match_2_P, basisP, mat_P_Coef); this->mat_P_Coef = unscrambled_P_Coef; diff --git a/src/libcatnip/qc_functions.hpp b/src/libcatnip/qc_functions.hpp index b78deeb..a84bfb1 100644 --- a/src/libcatnip/qc_functions.hpp +++ b/src/libcatnip/qc_functions.hpp @@ -1,3 +1,4 @@ +#pragma once #ifndef _CATNIP_QC_FUNCTIONS_HPP #define _CATNIP_QC_FUNCTIONS_HPP @@ -83,14 +84,14 @@ class TransferComplex { // // monomer1 LUMO-3 // monomer2 HOMO - void calcJ(const std::map& orbitaltype, - const std::map& orbitalnum); + void calcJ(); /** * \brief Print the transfer integral specified **/ - void printTransferIntegral(const std::pair & Orbital1, - const std::pair & Orbital2) const; + void printTransferIntegral( + const std::map & orbital_type, + const std::map & orbnum) const; /** * \brief Print All info in matrix form @@ -101,10 +102,6 @@ class TransferComplex { std::unordered_map> findRank( Eigen::VectorXd& Orb_E_Alpha, Eigen::VectorXd& Orb_E_Beta); -/*double calculate_transfer_integral(const Eigen::MatrixXd & mat_1_Coef, const Eigen::MatrixXd & mat_2_Coef, - Eigen::MatrixXd mat_P_Coef,const Eigen::MatrixXd & mat_S, - const Eigen::VectorXd& vec_P_OE, bool counterPoise_);*/ - // Reorganize the dimer coefficients to match up with the monomers Eigen::MatrixXd organize_P_Coef(std::vector matchDimerA, std::vector matchDimerB, @@ -114,22 +111,37 @@ Eigen::MatrixXd organize_P_Coef(std::vector matchDimerA, // Unscramble the coefficients of the dimer matrix // Assumes that the match vectors describe swaps looking at a single // instance of the dimerCoef matrix -Eigen::MatrixXd unscramble_Coef(const std::vector& matchDimerA, - const std::vector& matchDimerB, - const std::vector& basisFuncDimer, - Eigen::MatrixXd dimerCoef); +Eigen::MatrixXd unscramble_Coef( + const std::vector& matchDimerA, + const std::vector& matchDimerB, + const std::vector& basisFuncDimer, + const Eigen::MatrixXd & dimerCoef); -Eigen::MatrixXd unscramble_Coef(const std::vector& matchDimerA, - const std::vector& basisFuncDimer, Eigen::MatrixXd dimerCoef); +Eigen::MatrixXd unscramble_Coef( + const std::vector& matchDimerA, + const std::vector& basisFuncDimer, + const Eigen::MatrixXd & dimerCoef); // Reorganize the dimer overlap matrix to line up with the monomer // coefficients. -Eigen::MatrixXd unscramble_S(const std::vector& matchDimerA, - const std::vector& matchDimerB, - const std::vector& basisFuncDimer, Eigen::MatrixXd S); - -Eigen::MatrixXd unscramble_S(const std::vector& matchDimerA, - const std::vector& basisFuncDimer, Eigen::MatrixXd S); +/** + * + * Note S must not be a reference because it is altered during the unscrambling + **/ +Eigen::MatrixXd unscramble_S( + const std::vector& matchDimerA, + const std::vector& matchDimerB, + const std::vector& basisFuncDimer, + Eigen::MatrixXd S); + +/** + * + * Note S must not be a reference because it is altered during the unscrambling + **/ +Eigen::MatrixXd unscramble_S( + const std::vector& matchDimerA, + const std::vector& basisFuncDimer, + Eigen::MatrixXd S); Eigen::MatrixXd unscramble_OE(std::vector matchDimerA, std::vector matchDimerB, diff --git a/src/tests/test_qc_functions.cpp b/src/tests/test_qc_functions.cpp index 237901e..452e850 100644 --- a/src/tests/test_qc_functions.cpp +++ b/src/tests/test_qc_functions.cpp @@ -1,5 +1,5 @@ -//#include "../libcatnip/matrix.hpp" #include "../libcatnip/qc_functions.hpp" +#include "../libcatnip/matrix.hpp" #include #include #include diff --git a/src/tools/main.cpp b/src/tools/main.cpp index 890797e..2e4db86 100644 --- a/src/tools/main.cpp +++ b/src/tools/main.cpp @@ -19,10 +19,10 @@ #include "../libcatnip/log.hpp" #include "../libcatnip/parameters.hpp" #include "../libcatnip/qc_functions.hpp" - +#include "../libcatnip/matrix.hpp" #include "../libcatnip/calcJconfig.hpp" -#include +#include using namespace catnip; using namespace std; @@ -92,17 +92,17 @@ int main(int argc, const char *argv[]) { LOG("Getting " + par->getSpin1() + " of monomer 1", 2); Eigen::MatrixXd mat_1_Coef = pr_1.getCoefsMatrix(par->getSpin1()); //Matrix *mat_1_Coef = pr_1.getCoefsMatrix(par->getSpin1()); - //auto vec_1_OE = lr_1.getOE(par->getSpin1()); + Eigen::VectorXd vec_1_OE = lr_1.getOE(par->getSpin1()); //Matrix *mat_1_OE = new Matrix(vec_1_OE); - Eigen::MatrixXd mat_1_OE = Eigen::MatrixXd(vec_1_OE); + //Eigen::MatrixXd mat_1_OE = vec_1_OE.asDiagonal(); int HOMO2 = lr_2.getHOMOLevel(par->getSpin2()); LOG("Getting " + par->getSpin2() + " of monomer 2", 2); //Matrix *mat_2_Coef = pr_2.getCoefsMatrix(par->getSpin2()); Eigen::MatrixXd mat_2_Coef = pr_2.getCoefsMatrix(par->getSpin2()); - //auto vec_2_OE = lr_2.getOE(par->getSpin2()); + Eigen::VectorXd vec_2_OE = lr_2.getOE(par->getSpin2()); //Matrix *mat_2_OE = new Matrix(vec_2_OE); - Eigen::MatrixXd mat_2_OE = Eigen::MatrixXd(vec_2_OE); + //Eigen::MatrixXd mat_2_OE = vec_2_OE.asDiagonal(); // Unscramble dimer coef and energies first need to see how the dimer // and monomer coefficients line up. To determine how the ceofficients @@ -117,16 +117,16 @@ int main(int argc, const char *argv[]) { vector> coord_2 = lr_2.getCoords(); // Convert coords to matrices - MatrixXd coord_P_mat(coord_P); - MatrixXd coord_1_mat(coord_1); - MatrixXd coord_2_mat(coord_2); + Eigen::MatrixXd coord_P_mat = convert(coord_P); + Eigen::MatrixXd coord_1_mat = convert(coord_1); + Eigen::MatrixXd coord_2_mat = convert(coord_2); - int basis_P = lr_P.getBasisFuncCount(); - int basis_1 = lr_1.getBasisFuncCount(); - int basis_2 = lr_2.getBasisFuncCount(); + vector basis_P = lr_P.getBasisFuncCount(); + vector basis_1 = lr_1.getBasisFuncCount(); + vector basis_2 = lr_2.getBasisFuncCount(); - int MO1 = mat_1_OE->get_rows(); - int MO2 = mat_2_OE->get_rows(); + int MO1 = static_cast(vec_1_OE.size()); + int MO2 = static_cast(vec_2_OE.size()); pair Orbs1 = {MO1, HOMO1}; pair Orbs2 = {MO2, HOMO2}; From 47e30780ead5812ea16cf5f7788da7722a050b9a Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Mon, 29 Apr 2019 22:14:36 -0600 Subject: [PATCH 10/68] Add testing to log reader --- src/tests/test_logreader.cpp | 120 ++++++++++++++++++++++++++++++++++- 1 file changed, 118 insertions(+), 2 deletions(-) diff --git a/src/tests/test_logreader.cpp b/src/tests/test_logreader.cpp index be908eb..83702f3 100644 --- a/src/tests/test_logreader.cpp +++ b/src/tests/test_logreader.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -14,10 +15,125 @@ using namespace std; int main(void) { - cerr << "Testing: LogReader Constructor" << endl; + cout << "Testing: LogReader Constructor" << endl; { LogReader lr("file.log"); } - cerr << "Testing: LogReader read" << endl; + cout << "Testing: LogReader read energies" << endl; + { + + string test_file = "testfile_energies.log"; + { + ofstream fid; + fid.open(test_file); + fid << "Test log file contains sections that the log reader"; + fid << " will search and read from." << endl; + fid << " Alpha occ. eigenvalues -- -10.19871 -10.19791 -0.76206 -0.58448 -0.47269" << endl; + fid << " Alpha occ. eigenvalues -- -0.42268 -0.36322 -0.27597" << endl; + fid << " Alpha virt. eigenvalues -- -0.00988 0.02500 0.03257 0.04671 0.06946" << endl; + fid << " Alpha virt. eigenvalues -- 0.08668 0.08746 0.12753 0.15670 0.17639" << endl; + fid.close(); + } + + LogReader lr(test_file); + lr.read(); + + Eigen::VectorXd orbital_energies = lr.getOE("Alpha"); + + set correct_orbital_energies = { + -10.19871, -10.19791, -0.76206, -0.58448, -0.47269, + -0.42268, -0.36322, -0.27597, + -0.00988, 0.02500, 0.03257, 0.04671, 0.06946, + 0.08668, 0.08746, 0.12753, 0.15670, 0.17639}; + + vector found_energy(correct_orbital_energies.size(),false); + for( int index = 0; index < orbital_energies.size();++index){ + if( correct_orbital_energies.count(orbital_energies(index))){ + found_energy.at(index) = true; + } + cout << "Found Energy " << orbital_energies(index); + cout << " " << found_energy.at(index) << endl; + } + + for ( const bool & found : found_energy){ + assert(found); + } + } + + cout << "Testing: LogReader read coordinates" << endl; + { + string test_file = "testfile_coords.log"; + { + ofstream fid; + fid.open(test_file); + fid << "Center Atomic Atomic" << endl; + fid << " Number Number Type X Y Z" << endl; + fid << " ---------------------------------------------------------------------" << endl; + fid << " 1 6 0 0.672749 0.000000 5.000000" << endl; + fid << " 2 6 0 -0.672749 0.000000 5.000000" << endl; + fid << " 3 1 0 1.242623 0.162327 5.920604" << endl; + fid << " 4 1 0 1.242623 -0.162327 4.079396" << endl; + fid << " 5 1 0 -1.242623 0.162327 5.920604" << endl; + fid << " 6 1 0 -1.242623 -0.162327 4.079396" << endl; + fid << "-----------------------------------"; + fid << "----------------------------------" << endl; + fid.close(); + } + + LogReader lr(test_file); + lr.read(); + + vector> atomic_coords = lr.getCoords(); + + cout << atomic_coords.at(0).at(0) << " "; + cout << atomic_coords.at(1).at(0) << " "; + cout << atomic_coords.at(2).at(0) << " "; + assert(atomic_coords.at(0).at(0) == 0.672749); + assert(atomic_coords.at(1).at(0) == 0.000000); + assert(atomic_coords.at(2).at(0) == 5.000000); + cout << "Atom 1 coordinates correct" << endl; + + cout << atomic_coords.at(0).at(1) << " "; + cout << atomic_coords.at(1).at(1) << " "; + cout << atomic_coords.at(2).at(1) << " "; + assert(atomic_coords.at(0).at(1) == -0.672749); + assert(atomic_coords.at(1).at(1) == 0.0000000); + assert(atomic_coords.at(2).at(1) == 5.0000000); + cout << "Atom 2 coordinates correct" << endl; + + cout << atomic_coords.at(0).at(2) << " "; + cout << atomic_coords.at(1).at(2) << " "; + cout << atomic_coords.at(2).at(2) << " "; + assert(atomic_coords.at(0).at(2) == 1.242623); + assert(atomic_coords.at(1).at(2) == 0.162327); + assert(atomic_coords.at(2).at(2) == 5.920604); + cout << "Atom 3 coordinates correct" << endl; + + cout << atomic_coords.at(0).at(3) << " "; + cout << atomic_coords.at(1).at(3) << " "; + cout << atomic_coords.at(2).at(3) << " "; + assert(atomic_coords.at(0).at(3) == 1.242623); + assert(atomic_coords.at(1).at(3) == -0.162327); + assert(atomic_coords.at(2).at(3) == 4.079396); + cout << "Atom 4 coordinates correct" << endl; + + cout << atomic_coords.at(0).at(4) << " "; + cout << atomic_coords.at(1).at(4) << " "; + cout << atomic_coords.at(2).at(4) << " "; + assert(atomic_coords.at(0).at(4) == -1.242623); + assert(atomic_coords.at(1).at(4) == 0.162327); + assert(atomic_coords.at(2).at(4) == 5.920604); + cout << "Atom 5 coordinates correct" << endl; + + cout << atomic_coords.at(0).at(5) << " "; + cout << atomic_coords.at(1).at(5) << " "; + cout << atomic_coords.at(2).at(5) << " "; + assert(atomic_coords.at(0).at(5) == -1.242623); + assert(atomic_coords.at(1).at(5) == -0.162327); + assert(atomic_coords.at(2).at(5) == 4.079396); + cout << "Atom 6 coordinates correct" << endl; + + } + cout << "Testing: LogReader read" << endl; { LogReader lr("../../../GAUSSIANFILES/90_unordered/90_pair.log"); From 3bcf3296486fc7857dcb507c9e2ca6ed0a7d22fc Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Mon, 29 Apr 2019 22:32:16 -0600 Subject: [PATCH 11/68] Added test for overlap --- src/tests/test_logreader.cpp | 279 +++++++++++++++++++++++++++++++++++ 1 file changed, 279 insertions(+) diff --git a/src/tests/test_logreader.cpp b/src/tests/test_logreader.cpp index 83702f3..a663a2a 100644 --- a/src/tests/test_logreader.cpp +++ b/src/tests/test_logreader.cpp @@ -133,6 +133,285 @@ int main(void) { cout << "Atom 6 coordinates correct" << endl; } + + cout << "Testing: LogReader read overlap" << endl; + { + + string test_file = "testfile_overlap.log"; + { + ofstream fid; + fid.open(test_file); + fid << "*** Overlap *** " << endl; + fid << " 1 2 3 4 5 " << endl; + fid << " 1 0.100000D+01 " << endl; + fid << " 2 0.219059D+00 0.100000D+01 " << endl; + fid << " 3 0.000000D+00 0.000000D+00 0.100000D+01 " << endl; + fid << " 4 0.000000D+00 0.000000D+00 0.000000D+00 0.100000D+01 " << endl; + fid << " 5 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.100000D+01" << endl; + fid << " 6 0.184261D+00 0.812273D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 7 0.000000D+00 0.000000D+00 0.569754D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 8 0.000000D+00 0.000000D+00 0.000000D+00 0.569754D+00 0.000000D+00" << endl; + fid << " 9 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.569754D+00" << endl; + fid << " 10 0.697718D-01 0.402091D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 11 0.000000D+00 0.000000D+00 0.164679D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 12 0.000000D+00 0.000000D+00 0.000000D+00 0.164679D+00 0.000000D+00" << endl; + fid << " 13 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.164679D+00" << endl; + fid << " 14 0.791027D-01 0.710235D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 15 0.791027D-01 0.710235D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 16 0.791027D-01 0.710235D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 17 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 18 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 19 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 20 0.481399D-05 0.194904D-01 -0.426713D-01 0.000000D+00 0.000000D+00" << endl; + fid << " 21 0.194904D-01 0.203366D+00 -0.282219D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 22 0.426713D-01 0.282219D+00 -0.333594D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 23 0.000000D+00 0.000000D+00 0.000000D+00 0.115814D+00 0.000000D+00" << endl; + fid << " 24 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.115814D+00" << endl; + fid << " 25 0.643636D-01 0.359351D+00 -0.253511D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 26 0.129620D+00 0.562375D+00 -0.170740D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 27 0.000000D+00 0.000000D+00 0.000000D+00 0.242739D+00 0.000000D+00" << endl; + fid << " 28 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.242739D+00" << endl; + fid << " 29 0.527094D-01 0.309785D+00 -0.673317D-01 0.000000D+00 0.000000D+00" << endl; + fid << " 30 0.555561D-01 0.303665D+00 0.598522D-01 0.000000D+00 0.000000D+00" << endl; + fid << " 31 0.000000D+00 0.000000D+00 0.000000D+00 0.126532D+00 0.000000D+00" << endl; + fid << " 32 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.126532D+00" << endl; + fid << " 33 0.526767D-01 0.334402D+00 -0.413876D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 34 0.113280D-02 0.928256D-01 -0.142160D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 35 0.113280D-02 0.928256D-01 -0.142160D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 36 0.000000D+00 0.000000D+00 0.000000D+00 0.183392D+00 0.000000D+00" << endl; + fid << " 37 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.183392D+00" << endl; + fid << " 38 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 39 0.320525D-01 0.270664D+00 0.190666D+00 0.543105D-01 0.308011D+00" << endl; + fid << " 40 0.916644D-01 0.473962D+00 0.138280D+00 0.393885D-01 0.223384D+00" << endl; + fid << " 41 0.320525D-01 0.270664D+00 0.190666D+00 -0.543105D-01 -0.308011D+00" << endl; + fid << " 42 0.916644D-01 0.473962D+00 0.138280D+00 -0.393885D-01 -0.223384D+00" << endl; + fid << " 43 0.430533D-04 0.789567D-02 -0.152645D-01 0.129366D-02 0.733675D-02" << endl; + fid << " 44 0.142782D-01 0.109874D+00 -0.102097D+00 0.865264D-02 0.490716D-01" << endl; + fid << " 45 0.430533D-04 0.789567D-02 -0.152645D-01 -0.129366D-02 -0.733675D-02" << endl; + fid << " 46 0.142782D-01 0.109874D+00 -0.102097D+00 -0.865264D-02 -0.490716D-01" << endl; + fid << " 6 7 8 9 10" << endl; + fid << " 6 0.100000D+01" << endl; + fid << " 7 0.000000D+00 0.100000D+01" << endl; + fid << " 8 0.000000D+00 0.000000D+00 0.100000D+01" << endl; + fid << " 9 0.000000D+00 0.000000D+00 0.000000D+00 0.100000D+01" << endl; + fid << " 10 0.727666D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.100000D+01" << endl; + fid << " 11 0.000000D+00 0.588690D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 12 0.000000D+00 0.000000D+00 0.588690D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 13 0.000000D+00 0.000000D+00 0.000000D+00 0.588690D+00 0.000000D+00" << endl; + fid << " 14 0.629936D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.323540D+00" << endl; + fid << " 15 0.629936D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.323540D+00" << endl; + fid << " 16 0.629936D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.323540D+00" << endl; + fid << " 17 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 18 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 19 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 20 0.643636D-01 -0.129620D+00 0.000000D+00 0.000000D+00 0.527094D-01" << endl; + fid << " 21 0.359351D+00 -0.562375D+00 0.000000D+00 0.000000D+00 0.309785D+00" << endl; + fid << " 22 0.253511D+00 -0.170740D+00 0.000000D+00 0.000000D+00 0.673317D-01" << endl; + fid << " 23 0.000000D+00 0.000000D+00 0.242739D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 24 0.000000D+00 0.000000D+00 0.000000D+00 0.242739D+00 0.000000D+00" << endl; + fid << " 25 0.579631D+00 -0.605354D+00 0.000000D+00 0.000000D+00 0.581168D+00" << endl; + fid << " 26 0.605354D+00 -0.525884D-01 0.000000D+00 0.000000D+00 0.250193D+00" << endl; + fid << " 27 0.000000D+00 0.000000D+00 0.579631D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 28 0.000000D+00 0.000000D+00 0.000000D+00 0.579631D+00 0.000000D+00" << endl; + fid << " 29 0.581168D+00 -0.250193D+00 0.000000D+00 0.000000D+00 0.867984D+00" << endl; + fid << " 30 0.491037D+00 0.258780D+00 0.000000D+00 0.000000D+00 0.461882D+00" << endl; + fid << " 31 0.000000D+00 0.000000D+00 0.470171D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 32 0.000000D+00 0.000000D+00 0.000000D+00 0.470171D+00 0.000000D+00" << endl; + fid << " 33 0.353148D+00 -0.422973D+00 0.000000D+00 0.000000D+00 0.254635D+00" << endl; + fid << " 34 0.255918D+00 -0.441451D+00 0.000000D+00 0.000000D+00 0.247363D+00" << endl; + fid << " 35 0.255918D+00 -0.441451D+00 0.000000D+00 0.000000D+00 0.247363D+00" << endl; + fid << " 36 0.000000D+00 0.000000D+00 0.161252D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 37 0.000000D+00 0.000000D+00 0.000000D+00 0.161252D+00 0.000000D+00" << endl; + fid << " 38 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 39 0.375116D+00 0.267879D+00 0.763046D-01 0.432746D+00 0.258482D+00" << endl; + fid << " 40 0.702351D+00 0.303675D+00 0.865010D-01 0.490572D+00 0.640357D+00" << endl; + fid << " 41 0.375116D+00 0.267879D+00 -0.763046D-01 -0.432746D+00 0.258482D+00" << endl; + fid << " 42 0.702351D+00 0.303675D+00 -0.865010D-01 -0.490572D+00 0.640357D+00" << endl; + fid << " 43 0.740737D-01 -0.176934D+00 0.149950D-01 0.850413D-01 0.158045D+00" << endl; + fid << " 44 0.262382D+00 -0.381297D+00 0.323148D-01 0.183267D+00 0.424412D+00" << endl; + fid << " 45 0.740737D-01 -0.176934D+00 -0.149950D-01 -0.850413D-01 0.158045D+00" << endl; + fid << " 46 0.262382D+00 -0.381297D+00 -0.323148D-01 -0.183267D+00 0.424412D+00" << endl; + fid << " 11 12 13 14 15" << endl; + fid << " 11 0.100000D+01" << endl; + fid << " 12 0.000000D+00 0.100000D+01" << endl; + fid << " 13 0.000000D+00 0.000000D+00 0.100000D+01" << endl; + fid << " 14 0.000000D+00 0.000000D+00 0.000000D+00 0.100000D+01" << endl; + fid << " 15 0.000000D+00 0.000000D+00 0.000000D+00 0.333333D+00 0.100000D+01" << endl; + fid << " 16 0.000000D+00 0.000000D+00 0.000000D+00 0.333333D+00 0.333333D+00" << endl; + fid << " 17 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 18 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 19 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 20 -0.555561D-01 0.000000D+00 0.000000D+00 0.526767D-01 0.113280D-02" << endl; + fid << " 21 -0.303665D+00 0.000000D+00 0.000000D+00 0.334402D+00 0.928256D-01" << endl; + fid << " 22 0.598522D-01 0.000000D+00 0.000000D+00 0.413876D+00 0.142160D+00" << endl; + fid << " 23 0.000000D+00 0.126532D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 24 0.000000D+00 0.000000D+00 0.126532D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 25 -0.491037D+00 0.000000D+00 0.000000D+00 0.353148D+00 0.255918D+00" << endl; + fid << " 26 0.258780D+00 0.000000D+00 0.000000D+00 0.422973D+00 0.441451D+00" << endl; + fid << " 27 0.000000D+00 0.470171D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 28 0.000000D+00 0.000000D+00 0.470171D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 29 -0.461882D+00 0.000000D+00 0.000000D+00 0.254635D+00 0.247363D+00" << endl; + fid << " 30 0.622202D+00 0.000000D+00 0.000000D+00 0.229601D+00 0.249594D+00" << endl; + fid << " 31 0.000000D+00 0.867984D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 32 0.000000D+00 0.000000D+00 0.867984D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 33 -0.229601D+00 0.000000D+00 0.000000D+00 0.487216D+00 0.154963D+00" << endl; + fid << " 34 -0.249594D+00 0.000000D+00 0.000000D+00 0.154963D+00 0.753228D-01" << endl; + fid << " 35 -0.249594D+00 0.000000D+00 0.000000D+00 0.154963D+00 0.251076D-01" << endl; + fid << " 36 0.000000D+00 0.236690D-01 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 37 0.000000D+00 0.000000D+00 0.236690D-01 0.000000D+00 0.000000D+00" << endl; + fid << " 38 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 39 0.109596D+00 0.312180D-01 0.177046D+00 0.207130D+00 0.123414D+00" << endl; + fid << " 40 0.226998D+00 0.646599D-01 0.366705D+00 0.371459D+00 0.351303D+00" << endl; + fid << " 41 0.109596D+00 -0.312180D-01 -0.177046D+00 0.207130D+00 0.123414D+00" << endl; + fid << " 42 0.226998D+00 -0.646599D-01 -0.366705D+00 0.371459D+00 0.351303D+00" << endl; + fid << " 43 -0.225200D+00 0.190856D-01 0.108240D+00 0.137730D-01 0.170528D-02" << endl; + fid << " 44 -0.505665D+00 0.428549D-01 0.243043D+00 0.120267D+00 0.707321D-01" << endl; + fid << " 45 -0.225200D+00 -0.190856D-01 -0.108240D+00 0.137730D-01 0.170528D-02" << endl; + fid << " 46 -0.505665D+00 -0.428549D-01 -0.243043D+00 0.120267D+00 0.707321D-01" << endl; + fid << " 16 17 18 19 20" << endl; + fid << " 16 0.100000D+01" << endl; + fid << " 17 0.000000D+00 0.100000D+01" << endl; + fid << " 18 0.000000D+00 0.000000D+00 0.100000D+01" << endl; + fid << " 19 0.000000D+00 0.000000D+00 0.000000D+00 0.100000D+01" << endl; + fid << " 20 0.113280D-02 0.000000D+00 0.000000D+00 0.000000D+00 0.100000D+01" << endl; + fid << " 21 0.928256D-01 0.000000D+00 0.000000D+00 0.000000D+00 0.219059D+00" << endl; + fid << " 22 0.142160D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 23 0.000000D+00 -0.183392D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 24 0.000000D+00 0.000000D+00 -0.183392D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 25 0.255918D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.184261D+00" << endl; + fid << " 26 0.441451D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 27 0.000000D+00 -0.161252D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 28 0.000000D+00 0.000000D+00 -0.161252D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 29 0.247363D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.697718D-01" << endl; + fid << " 30 0.249594D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 31 0.000000D+00 -0.236690D-01 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 32 0.000000D+00 0.000000D+00 -0.236690D-01 0.000000D+00 0.000000D+00" << endl; + fid << " 33 0.154963D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.791027D-01" << endl; + fid << " 34 0.251076D-01 0.000000D+00 0.000000D+00 0.000000D+00 0.791027D-01" << endl; + fid << " 35 0.753228D-01 0.000000D+00 0.000000D+00 0.000000D+00 0.791027D-01" << endl; + fid << " 36 0.000000D+00 -0.314243D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 37 0.000000D+00 0.000000D+00 -0.314243D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 38 0.000000D+00 0.000000D+00 0.000000D+00 0.753228D-01 0.000000D+00" << endl; + fid << " 39 0.353785D+00 0.449500D-01 0.254925D+00 0.726146D-01 0.430533D-04" << endl; + fid << " 40 0.406770D+00 0.108227D-01 0.613785D-01 0.174835D-01 0.142782D-01" << endl; + fid << " 41 0.353785D+00 -0.449500D-01 -0.254925D+00 0.726146D-01 0.430533D-04" << endl; + fid << " 42 0.406770D+00 -0.108227D-01 -0.613785D-01 0.174835D-01 0.142782D-01" << endl; + fid << " 43 0.442596D-02 -0.178424D-02 -0.101190D-01 0.857578D-03 0.320525D-01" << endl; + fid << " 44 0.818999D-01 -0.732391D-02 -0.415360D-01 0.352016D-02 0.916644D-01" << endl; + fid << " 45 0.442596D-02 0.178424D-02 0.101190D-01 0.857578D-03 0.320525D-01" << endl; + fid << " 46 0.818999D-01 0.732391D-02 0.415360D-01 0.352016D-02 0.916644D-01" << endl; + fid << " 21 22 23 24 25" << endl; + fid << " 21 0.100000D+01" << endl; + fid << " 22 0.000000D+00 0.100000D+01" << endl; + fid << " 23 0.000000D+00 0.000000D+00 0.100000D+01" << endl; + fid << " 24 0.000000D+00 0.000000D+00 0.000000D+00 0.100000D+01" << endl; + fid << " 25 0.812273D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.100000D+01" << endl; + fid << " 26 0.000000D+00 0.569754D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 27 0.000000D+00 0.000000D+00 0.569754D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 28 0.000000D+00 0.000000D+00 0.000000D+00 0.569754D+00 0.000000D+00" << endl; + fid << " 29 0.402091D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.727666D+00" << endl; + fid << " 30 0.000000D+00 0.164679D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 31 0.000000D+00 0.000000D+00 0.164679D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 32 0.000000D+00 0.000000D+00 0.000000D+00 0.164679D+00 0.000000D+00" << endl; + fid << " 33 0.710235D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.629936D+00" << endl; + fid << " 34 0.710235D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.629936D+00" << endl; + fid << " 35 0.710235D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.629936D+00" << endl; + fid << " 36 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 37 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 38 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 39 0.789567D-02 0.152645D-01 0.129366D-02 0.733675D-02 0.740737D-01" << endl; + fid << " 40 0.109874D+00 0.102097D+00 0.865264D-02 0.490716D-01 0.262382D+00" << endl; + fid << " 41 0.789567D-02 0.152645D-01 -0.129366D-02 -0.733675D-02 0.740737D-01" << endl; + fid << " 42 0.109874D+00 0.102097D+00 -0.865264D-02 -0.490716D-01 0.262382D+00" << endl; + fid << " 43 0.270664D+00 -0.190666D+00 0.543105D-01 0.308011D+00 0.375116D+00" << endl; + fid << " 44 0.473962D+00 -0.138280D+00 0.393885D-01 0.223384D+00 0.702351D+00" << endl; + fid << " 45 0.270664D+00 -0.190666D+00 -0.543105D-01 -0.308011D+00 0.375116D+00" << endl; + fid << " 46 0.473962D+00 -0.138280D+00 -0.393885D-01 -0.223384D+00 0.702351D+00" << endl; + fid << " 26 27 28 29 30" << endl; + fid << " 26 0.100000D+01" << endl; + fid << " 27 0.000000D+00 0.100000D+01" << endl; + fid << " 28 0.000000D+00 0.000000D+00 0.100000D+01" << endl; + fid << " 29 0.000000D+00 0.000000D+00 0.000000D+00 0.100000D+01" << endl; + fid << " 30 0.588690D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.100000D+01" << endl; + fid << " 31 0.000000D+00 0.588690D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 32 0.000000D+00 0.000000D+00 0.588690D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 33 0.000000D+00 0.000000D+00 0.000000D+00 0.323540D+00 0.000000D+00" << endl; + fid << " 34 0.000000D+00 0.000000D+00 0.000000D+00 0.323540D+00 0.000000D+00" << endl; + fid << " 35 0.000000D+00 0.000000D+00 0.000000D+00 0.323540D+00 0.000000D+00" << endl; + fid << " 36 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 37 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 38 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 39 0.176934D+00 0.149950D-01 0.850413D-01 0.158045D+00 0.225200D+00" << endl; + fid << " 40 0.381297D+00 0.323148D-01 0.183267D+00 0.424412D+00 0.505665D+00" << endl; + fid << " 41 0.176934D+00 -0.149950D-01 -0.850413D-01 0.158045D+00 0.225200D+00" << endl; + fid << " 42 0.381297D+00 -0.323148D-01 -0.183267D+00 0.424412D+00 0.505665D+00" << endl; + fid << " 43 -0.267879D+00 0.763046D-01 0.432746D+00 0.258482D+00 -0.109596D+00" << endl; + fid << " 44 -0.303675D+00 0.865010D-01 0.490572D+00 0.640357D+00 -0.226998D+00" << endl; + fid << " 45 -0.267879D+00 -0.763046D-01 -0.432746D+00 0.258482D+00 -0.109596D+00" << endl; + fid << " 46 -0.303675D+00 -0.865010D-01 -0.490572D+00 0.640357D+00 -0.226998D+00" << endl; + fid << " 31 32 33 34 35" << endl; + fid << " 31 0.100000D+01" << endl; + fid << " 32 0.000000D+00 0.100000D+01" << endl; + fid << " 33 0.000000D+00 0.000000D+00 0.100000D+01" << endl; + fid << " 34 0.000000D+00 0.000000D+00 0.333333D+00 0.100000D+01" << endl; + fid << " 35 0.000000D+00 0.000000D+00 0.333333D+00 0.333333D+00 0.100000D+01" << endl; + fid << " 36 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 37 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 38 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; + fid << " 39 0.190856D-01 0.108240D+00 0.137730D-01 0.170528D-02 0.442596D-02" << endl; + fid << " 40 0.428549D-01 0.243043D+00 0.120267D+00 0.707321D-01 0.818999D-01" << endl; + fid << " 41 -0.190856D-01 -0.108240D+00 0.137730D-01 0.170528D-02 0.442596D-02" << endl; + fid << " 42 -0.428549D-01 -0.243043D+00 0.120267D+00 0.707321D-01 0.818999D-01" << endl; + fid << " 43 0.312180D-01 0.177046D+00 0.207130D+00 0.123414D+00 0.353785D+00" << endl; + fid << " 44 0.646599D-01 0.366705D+00 0.371459D+00 0.351303D+00 0.406770D+00" << endl; + fid << " 45 -0.312180D-01 -0.177046D+00 0.207130D+00 0.123414D+00 0.353785D+00" << endl; + fid << " 46 -0.646599D-01 -0.366705D+00 0.371459D+00 0.351303D+00 0.406770D+00" << endl; + fid << " 36 37 38 39 40" << endl; + fid << " 36 0.100000D+01" << endl; + fid << " 37 0.000000D+00 0.100000D+01" << endl; + fid << " 38 0.000000D+00 0.000000D+00 0.100000D+01" << endl; + fid << " 39 0.178424D-02 0.101190D-01 0.857578D-03 0.100000D+01" << endl; + fid << " 40 0.732391D-02 0.415360D-01 0.352016D-02 0.658292D+00 0.100000D+01" << endl; + fid << " 41 -0.178424D-02 -0.101190D-01 0.857578D-03 0.125798D-01 0.128011D+00" << endl; + fid << " 42 -0.732391D-02 -0.415360D-01 0.352016D-02 0.128011D+00 0.365470D+00" << endl; + fid << " 43 -0.449500D-01 -0.254925D+00 0.726146D-01 0.571644D-03 0.366357D-01" << endl; + fid << " 44 -0.108227D-01 -0.613785D-01 0.174835D-01 0.366357D-01 0.168873D+00" << endl; + fid << " 45 0.449500D-01 0.254925D+00 0.726146D-01 0.104764D-04 0.720595D-02" << endl; + fid << " 46 0.108227D-01 0.613785D-01 0.174835D-01 0.720595D-02 0.617178D-01" << endl; + fid << " 41 42 43 44 45" << endl; + fid << " 41 0.100000D+01" << endl; + fid << " 42 0.658292D+00 0.100000D+01" << endl; + fid << " 43 0.104764D-04 0.720595D-02 0.100000D+01" << endl; + fid << " 44 0.720595D-02 0.617178D-01 0.658292D+00 0.100000D+01" << endl; + fid << " 45 0.571644D-03 0.366357D-01 0.125798D-01 0.128011D+00 0.100000D+01" << endl; + fid << " 46 0.366357D-01 0.168873D+00 0.128011D+00 0.365470D+00 0.658292D+00" << endl; + fid << " 46" << endl; + fid << " 46 0.100000D+01" << endl; + fid.close(); + } + + LogReader lr(test_file); + lr.read(); + + Eigen::MatrixXd overlap = lr.getOverlapMatrix(); + + // We will test the corners of the overlap matrix and a few elements + // at random + assert(overlap(0,0)==1); + assert(overlap(0,45)==0.01427); + assert(overlap(45,0)==0.01427); + assert(overlap(45,45)==1); + + assert(overlap(10,6)==0.588690); + assert(overlap(6,10)==0.588690); + + assert(overlap(38,27)==0.0850413); + assert(overlap(27,38)==0.0850413); + + assert(overlap(26,22)==0.569754); + assert(overlap(26,22)==0.569754); + } + cout << "Testing: LogReader read" << endl; { From 9d704766d885724c576630b1235f98c1d1ebcc8c Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Mon, 29 Apr 2019 23:47:19 -0600 Subject: [PATCH 12/68] Added overlap test --- src/tests/test_logreader.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/tests/test_logreader.cpp b/src/tests/test_logreader.cpp index a663a2a..7e570d0 100644 --- a/src/tests/test_logreader.cpp +++ b/src/tests/test_logreader.cpp @@ -141,12 +141,12 @@ int main(void) { { ofstream fid; fid.open(test_file); - fid << "*** Overlap *** " << endl; - fid << " 1 2 3 4 5 " << endl; - fid << " 1 0.100000D+01 " << endl; - fid << " 2 0.219059D+00 0.100000D+01 " << endl; - fid << " 3 0.000000D+00 0.000000D+00 0.100000D+01 " << endl; - fid << " 4 0.000000D+00 0.000000D+00 0.000000D+00 0.100000D+01 " << endl; + fid << " *** Overlap *** " << endl; + fid << " 1 2 3 4 5" << endl; + fid << " 1 0.100000D+01" << endl; + fid << " 2 0.219059D+00 0.100000D+01" << endl; + fid << " 3 0.000000D+00 0.000000D+00 0.100000D+01" << endl; + fid << " 4 0.000000D+00 0.000000D+00 0.000000D+00 0.100000D+01" << endl; fid << " 5 0.000000D+00 0.000000D+00 0.000000D+00 0.000000D+00 0.100000D+01" << endl; fid << " 6 0.184261D+00 0.812273D+00 0.000000D+00 0.000000D+00 0.000000D+00" << endl; fid << " 7 0.000000D+00 0.000000D+00 0.569754D+00 0.000000D+00 0.000000D+00" << endl; @@ -395,11 +395,18 @@ int main(void) { Eigen::MatrixXd overlap = lr.getOverlapMatrix(); + cout << "Overlap Matrix rows " << overlap.rows() << " cols " << overlap.cols() << endl; + assert(overlap.rows()==46); + assert(overlap.cols()==46); // We will test the corners of the overlap matrix and a few elements // at random + cout << "row 1 1 1.000 " << overlap(0,0) << endl; assert(overlap(0,0)==1); - assert(overlap(0,45)==0.01427); - assert(overlap(45,0)==0.01427); + cout << "row 1 46 0.01427 " << overlap(0,45) << endl; + assert(overlap(0,45)==0.0142782); + cout << "row 46 1 0.01427 " << overlap(45,0) << endl; + assert(overlap(45,0)==0.0142782); + cout << "row 46 46 1.000 " << overlap(45,45) << endl; assert(overlap(45,45)==1); assert(overlap(10,6)==0.588690); @@ -427,7 +434,8 @@ int main(void) { for (auto c : basisFuncCount) { cout << c << endl; } - auto xyz = lr.getCoords(); + + vector> xyz = lr.getCoords(); auto x = xyz.at(0); auto y = xyz.at(1); auto z = xyz.at(2); From c84823dbff05ea86968d678392e22d2fbe55ec15 Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Mon, 29 Apr 2019 23:48:49 -0600 Subject: [PATCH 13/68] checkpoint --- src/libcatnip/io/file_readers/logreader.cpp | 14 ++++++-------- src/tests/test_logreader.cpp | 4 ++-- src/tests/test_punreader.cpp | 5 +++-- src/tests/test_qc_functions.cpp | 2 +- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/libcatnip/io/file_readers/logreader.cpp b/src/libcatnip/io/file_readers/logreader.cpp index 1657492..700339c 100644 --- a/src/libcatnip/io/file_readers/logreader.cpp +++ b/src/libcatnip/io/file_readers/logreader.cpp @@ -77,6 +77,7 @@ void LogReader::AOFunctionSectionReader(void *ptr) { while (!iss.eof()) { string Tot_Alpha_Beta_Spin; iss >> Tot_Alpha_Beta_Spin; + trim(Tot_Alpha_Beta_Spin); orbVals.push_back(stod(Tot_Alpha_Beta_Spin)); } LR_ptr->orb_[make_pair(atom_num, elemType)][orbType] = orbVals; @@ -116,7 +117,6 @@ void LogReader::AOFunctionSectionReader(void *ptr) { } ++atom_num; - // getline(LR_ptr->fid_,line); if (foundSubStrInStr(line, end_pattern)) { sectionEnd = true; } @@ -166,14 +166,13 @@ void LogReader::OverlapSectionReader(void *ptr) { // Create a matrix and place all the current values in there - //Matrix *mat_S = new Matrix(countCoef, countCoef); Eigen::MatrixXd matrix_S(countCoef,countCoef); - + for (size_t row_ind = 0; row_ind < first_coefs.size(); ++row_ind) { - Eigen::Map eigen_vec((first_coefs.at(row_ind).data()),first_coefs.at(row_ind).size()); - matrix_S.row(row_ind) = eigen_vec; + Eigen::Map eigen_row((first_coefs.at(row_ind).data()),first_coefs.at(row_ind).size()); + matrix_S.block(row_ind,0,1,eigen_row.size()) = eigen_row; + matrix_S.block(0,row_ind,eigen_row.size(),1) = eigen_row.transpose(); } - int sectionReads = countCoef / 5; if (countCoef % 5 > 0) { ++sectionReads; @@ -189,7 +188,6 @@ void LogReader::OverlapSectionReader(void *ptr) { istringstream iss(line); string dummy; iss >> dummy; - //int localCoefCount = 1; int localCoefCount = 0; while (!iss.eof()) { string s_coef; @@ -197,7 +195,6 @@ void LogReader::OverlapSectionReader(void *ptr) { string val = grabStrBeforeFirstOccurance(s_coef, "D"); string expon = grabStrAfterFirstOccurance(s_coef, "D"); double value = stod(val) * pow(10.0, stod(expon)); - matrix_S(sectionCoef,currentSectionStart + localCoefCount) = value; if ((sectionCoef) != (currentSectionStart + localCoefCount)) { matrix_S(currentSectionStart + localCoefCount,sectionCoef) = value; @@ -210,6 +207,7 @@ void LogReader::OverlapSectionReader(void *ptr) { currentSectionStart += 5; getline(LR_ptr->fid_, line); } + LR_ptr->S_ = matrix_S; LOG("Success reading Overlap coefficients from .log file", 2); return; diff --git a/src/tests/test_logreader.cpp b/src/tests/test_logreader.cpp index 7e570d0..784d1a3 100644 --- a/src/tests/test_logreader.cpp +++ b/src/tests/test_logreader.cpp @@ -402,9 +402,9 @@ int main(void) { // at random cout << "row 1 1 1.000 " << overlap(0,0) << endl; assert(overlap(0,0)==1); - cout << "row 1 46 0.01427 " << overlap(0,45) << endl; + cout << "row 1 46 0.0142782 " << overlap(0,45) << endl; assert(overlap(0,45)==0.0142782); - cout << "row 46 1 0.01427 " << overlap(45,0) << endl; + cout << "row 46 1 0.0142782 " << overlap(45,0) << endl; assert(overlap(45,0)==0.0142782); cout << "row 46 46 1.000 " << overlap(45,45) << endl; assert(overlap(45,45)==1); diff --git a/src/tests/test_punreader.cpp b/src/tests/test_punreader.cpp index 87136cd..0893860 100644 --- a/src/tests/test_punreader.cpp +++ b/src/tests/test_punreader.cpp @@ -4,6 +4,7 @@ #include #include #include +#include using namespace catnip; using namespace std; @@ -18,8 +19,8 @@ int main(void) { PunReader pr("../../../GAUSSIANFILES/90_unordered/90_pair.pun"); pr.read(); - auto m = pr.getCoefsMatrix("Alpha"); - assert(m->get_rows() == 92); + Eigen::MatrixXd m = pr.getCoefsMatrix("Alpha"); + assert(m.rows() == 92); assert(pr.restrictedShell()); } return 0; diff --git a/src/tests/test_qc_functions.cpp b/src/tests/test_qc_functions.cpp index 452e850..b377280 100644 --- a/src/tests/test_qc_functions.cpp +++ b/src/tests/test_qc_functions.cpp @@ -74,7 +74,7 @@ int main(void) { assert(matchA.at(1) == 4); assert(matchB.at(0) == 0); - assert(matchB.at(1) == 4); + assert(matchB.at(1) == 3); assert(matchB.at(2) == 2); vector basisFuncDimer; From 54b55e516a6507e0a25439c557a654516dd60e79 Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Tue, 30 Apr 2019 00:05:09 -0600 Subject: [PATCH 14/68] Fixed error that was introduced --- src/libcatnip/qc_functions.cpp | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/libcatnip/qc_functions.cpp b/src/libcatnip/qc_functions.cpp index d40d2f7..d978876 100644 --- a/src/libcatnip/qc_functions.cpp +++ b/src/libcatnip/qc_functions.cpp @@ -469,7 +469,7 @@ void updateSwapLists(vector> &monBmatch, for (auto p : monBmatch) { if (p.first != p.second) { auto it = p_atom_mat_coef.begin(); - Eigen::MatrixXd & temp = *(next(it, p.first)); + Eigen::MatrixXd temp = *(next(it, p.first)); *(next(it, p.first)) = *(next(it, p.second)); *(next(it, p.second)) = temp; } @@ -477,7 +477,7 @@ void updateSwapLists(vector> &monBmatch, for (auto p : monAmatch) { if (p.first != p.second) { auto it = p_atom_mat_coef.begin(); - Eigen::MatrixXd & temp = *(next(it, p.first)); + Eigen::MatrixXd temp = *(next(it, p.first)); *(next(it, p.first)) = *(next(it, p.second)); *(next(it, p.second)) = temp; } @@ -505,7 +505,9 @@ Eigen::MatrixXd mergeListOfMatrices(list &matrix_list, const in if (ColRowMerge.compare("Columns") == 0) { int col = 0; for (auto it = matrix_list.begin(); it != matrix_list.end(); ++it) { - Eigen::MatrixXd & mat = *it; + Eigen::MatrixXd mat = *it; + cout << "Cycling columns to merge" << endl; + cout << mat << endl; int row = 0; if (col > cols) throw runtime_error("Your new matrix is not large enough"); @@ -523,6 +525,7 @@ Eigen::MatrixXd mergeListOfMatrices(list &matrix_list, const in int row = 0; for (auto it = matrix_list.begin(); it != matrix_list.end(); ++it) { Eigen::MatrixXd mat = *it; + cout << "Cycling rows " << endl; int col = 0; if (row > rows) throw runtime_error("Your new matrix is not large enough"); @@ -539,6 +542,7 @@ Eigen::MatrixXd mergeListOfMatrices(list &matrix_list, const in } else { throw invalid_argument("Unrecognized merge type for list of matrices"); } + cout << full_matrix << endl; return full_matrix; } @@ -579,9 +583,23 @@ Eigen::MatrixXd unscramble_Coef( pair pr(i + monAmatch.size(), matchDimerB.at(i)); monBmatch.push_back(pr); } + cout << "Contents of list before swap" << endl; + for( Eigen::MatrixXd & mat : p_atom_mat_coef ){ + cout << mat << "\n" << endl; + } refreshSwapOrder(monBmatch, monAmatch); + cout << "Contents of list before update" << endl; + for( Eigen::MatrixXd & mat : p_atom_mat_coef ){ + cout << mat << "\n" << endl; + } + updateSwapLists(monBmatch, monAmatch, p_atom_mat_coef); + cout << "Contents of list" << endl; + for( Eigen::MatrixXd & mat : p_atom_mat_coef ){ + cout << mat << "\n" << endl; + } + Eigen::MatrixXd dimerCoef_new = createNewMatrix( p_atom_mat_coef, dimerCoef.rows(), dimerCoef.cols(), "Columns"); @@ -632,7 +650,10 @@ Eigen::MatrixXd unscramble_S( Eigen::MatrixXd S_new(S.rows(),S.cols()); { list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Columns"); - + cout << "List of split matrices" << endl; + for( Eigen::MatrixXd & mat : p_atom_mat_S ){ + cout << mat << "\n" << endl; + } vector> monAmatch; for (unsigned i = 0; i < matchDimerA.size(); ++i) { pair pr(i, matchDimerA.at(i)); From e13daaa71cf601b3b2308d19ccbb5592d0e15d1e Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Tue, 30 Apr 2019 21:44:41 -0600 Subject: [PATCH 15/68] Updated print statment and fixed error --- src/libcatnip/qc_functions.cpp | 134 +++++++++++++++++---------------- src/libcatnip/qc_functions.hpp | 16 ++-- src/tools/main.cpp | 9 +-- 3 files changed, 81 insertions(+), 78 deletions(-) diff --git a/src/libcatnip/qc_functions.cpp b/src/libcatnip/qc_functions.cpp index d978876..3346699 100644 --- a/src/libcatnip/qc_functions.cpp +++ b/src/libcatnip/qc_functions.cpp @@ -52,37 +52,38 @@ unordered_map> findRank(Eigen::VectorXd &Orb_E_Alpha, void TransferComplex::calculate_transfer_integral_() { auto dimension = mat_1_Coef.rows()+mat_2_Coef.rows(); - Eigen::MatrixXd zetaA(dimension,dimension); - Eigen::MatrixXd zetaB(dimension,dimension); + Eigen::MatrixXd zetaA(mat_1_Coef.cols(),dimension); + Eigen::MatrixXd zetaB(mat_2_Coef.cols(),dimension); if (counterPoise_) { + LOG("Creating zeta matrices from coefficients assuming counterpoise", 2); zetaA = mat_1_Coef; zetaB = mat_2_Coef; } else { LOG("Creating zeta matrices from coefficients", 2); zetaA << mat_1_Coef, Eigen::MatrixXd::Zero(mat_1_Coef.rows(),mat_2_Coef.cols()); - zetaA << Eigen::MatrixXd::Zero(mat_2_Coef.rows(),mat_1_Coef.cols()), mat_2_Coef; + zetaB << Eigen::MatrixXd::Zero(mat_2_Coef.rows(),mat_1_Coef.cols()), mat_2_Coef; } + Eigen::MatrixXd zeta(dimension,dimension); LOG("Creating gamma and beta matrices", 2); Eigen::MatrixXd gammaA = zetaA * mat_S * mat_P_Coef.transpose(); Eigen::MatrixXd gammaB = zetaB * mat_S * mat_P_Coef.transpose(); + Eigen::MatrixXd gamma(dimension,dimension); + gamma << gammaB, gammaA; LOG("Calculating S_AB", 2); - S_AB.resize(gammaB.rows(),gammaA.cols()); - S_AB = gammaB * gammaA.transpose(); + S_AB.resize(dimension,dimension); + S_AB = gamma * gamma.transpose(); + Eigen::SelfAdjointEigenSolver eigen_solver(S_AB); Eigen::MatrixXd S_AB_inv_sqrt = eigen_solver.operatorInverseSqrt(); - Eigen::MatrixXd Energy = Eigen::MatrixXd::Identity(vec_P_OE.size(),vec_P_OE.size()); - Hamiltonian.resize(mat_S.rows(),mat_S.cols()); - Hamiltonian = mat_P_Coef * mat_S * mat_P_Coef.transpose(); - - Hamiltonian_eff.resize(Hamiltonian.rows(),Hamiltonian.cols()); - Hamiltonian_eff = S_AB_inv_sqrt * Hamiltonian * S_AB_inv_sqrt.transpose(); + Hamiltonian = gamma * vec_P_OE.asDiagonal() * gamma.transpose(); + Hamiltonian_eff = S_AB_inv_sqrt * Hamiltonian * S_AB_inv_sqrt; } void TransferComplex::printTransferIntegral( @@ -98,11 +99,11 @@ void TransferComplex::printTransferIntegral( " value is in reference to the HOMO and must be a negative number"); } // Number of orbitals that are choices - if (MO_A <= (-1 * Orbs1.second)) { + if (MO_A <= (-1 * HOMO_A_)) { string err = "You are trying to access HOMO" + to_string(MO_A) + " but there " "are only " + - to_string(Orbs1.second) + " HOMO orbitals"; + to_string(HOMO_A_) + " HOMO orbitals"; throw invalid_argument(err); } } else if (HOMO_OR_LUMO_A.compare("LUMO") == 0) { @@ -111,7 +112,7 @@ void TransferComplex::printTransferIntegral( "Having specified LUMO the MO_A" " value is in reference to the LUMO and must be a positive number"); } - int allowed_LUMO = Orbs1.first - Orbs1.second; + int allowed_LUMO = mat_1_Coef.rows() - HOMO_A_; if (MO_A >= allowed_LUMO) { string err = "You are trying to access LUMO+" + to_string(MO_A) + " but there " @@ -131,11 +132,11 @@ void TransferComplex::printTransferIntegral( "Having specified HOMO the MO_B" " value is in reference to the HOMO and must be a negative number"); } - if (MO_B <= (-1 * Orbs2.second)) { + if (MO_B <= (-1 * HOMO_B_)) { string err = "You are trying to access HOMO" + to_string(MO_B) + " but there " "are only " + - to_string(Orbs2.second) + " HOMO orbitals"; + to_string(HOMO_B_) + " HOMO orbitals"; throw invalid_argument(err); } } else if (HOMO_OR_LUMO_B.compare("LUMO") == 0) { @@ -144,7 +145,7 @@ void TransferComplex::printTransferIntegral( "Having specified LUMO the MO_B" " value is in reference to the LUMO and must be a positive number"); } - int allowed_LUMO = Orbs2.first - Orbs2.second; + int allowed_LUMO = mat_2_Coef.rows() - HOMO_B_; if (MO_B >= allowed_LUMO) { string err = "You are trying to access LUMO+" + to_string(MO_B) + " but there " @@ -167,43 +168,69 @@ void TransferComplex::printTransferIntegral_( const pair& orbital1, const pair& orbital2) const { + int offset = mat_1_Coef.rows(); int orbital1_num = 0; int orbital2_num = 0; if(orbital1.first.compare("HOMO")==0){ assert(orbitalValid_(orbital1)==true); - orbital1_num = orbital1.second; + orbital1_num = orbital1.second + HOMO_A_-1; + }else if(orbital1.first.compare("LUMO")==0){ + assert(orbitalValid_(orbital1)==true); + orbital1_num = orbital1.second + HOMO_A_; + } + if(orbital2.first.compare("HOMO")==0){ + assert(orbitalValid_(orbital2)==true); + orbital2_num = offset+orbital2.second + HOMO_B_-1; }else if(orbital2.first.compare("LUMO")==0){ assert(orbitalValid_(orbital2)==true); - orbital2_num = orbital2.second; + orbital2_num = offset+orbital2.second + HOMO_B_; } double J_ab = Hamiltonian(orbital1_num,orbital2_num); double e_a = Hamiltonian(orbital1_num,orbital1_num); double e_b = Hamiltonian(orbital2_num,orbital2_num); double S_ab = S_AB(orbital1_num,orbital2_num); + + cout << "\nPre-Orthonormalization" << endl; + cout << "J_ab " << J_ab * hartreeToeV << " eV\n"; + cout << "e_a " << e_a * hartreeToeV << " eV\n"; + cout << "e_b " << e_b * hartreeToeV << " eV\n"; + cout << "S_ab " << S_ab << "\n" << endl; + + cout << "Single Orbital DIPRO" << endl; + double J_ab_single = (J_ab - 0.5*(e_a+e_b)*S_ab)/(1-pow(S_ab,2.0)); + double e_a_single = 0.5*((e_a+e_b)-2*J_ab*S_ab+(e_a-e_b)*pow(1-pow(S_ab,2.0),0.5))/(1-pow(S_ab,2.0)); + double e_b_single = 0.5*((e_a+e_b)-2*J_ab*S_ab-(e_a-e_b)*pow(1-pow(S_ab,2.0),0.5))/(1-pow(S_ab,2.0)); + cout << "J_ab_eff_single " << J_ab_single * hartreeToeV << " eV\n"; + cout << "e_a_eff_single " << e_a_single * hartreeToeV << " eV\n"; + cout << "e_b_eff_single " << e_b_single * hartreeToeV << " eV\n" << endl; + + cout << "All Orbital DIPRO" << endl; double J_eff = Hamiltonian_eff(orbital1_num,orbital2_num); - cout << "J_ab " << J_ab * hartreeToeV << " eV\n"; - cout << "e_a " << e_a * hartreeToeV << " eV\n"; - cout << "e_b " << e_b * hartreeToeV << " eV\n"; - cout << "S_ab " << S_ab << "\n"; - cout << "J_eff " << J_eff * hartreeToeV << " eV\n"; + double e_a_eff = Hamiltonian_eff(orbital1_num,orbital1_num); + double e_b_eff = Hamiltonian_eff(orbital2_num,orbital2_num); + cout << "J_ab_eff_all " << J_eff * hartreeToeV << " eV\n"; + cout << "e_a_eff_all " << e_a_eff * hartreeToeV << " eV\n"; + cout << "e_b_eff_all " << e_b_eff * hartreeToeV << " eV\n" << endl; } void TransferComplex::printAll() const { + int HOMO_AB = HOMO_A_+HOMO_B_; + int LUMO_AB = HOMO_AB+1; int column_width = 8; cout << "Effective Hamiltonian" << endl; cout << setw(column_width+2) << ""; for(int orbital_num = 0;orbital_num & orbital) const{ + int HOMO_AB = HOMO_A_+HOMO_B_; + int LUMO_AB = HOMO_AB+1; if(orbital.first.compare("HOMO")==0){ if(orbital.second>0){ cerr << "HOMO orbital number is not negative or 0" << endl; return false; } - if(orbital.second<=(-1*HOMO_Orb_)){ - cerr << "HOMO orbital does not exst " << orbital.second << endl; + if(orbital.second>HOMO_AB){ + cerr << "HOMO orbital does not exst " << orbital.second << " "<< HOMO_AB << endl; return false; } }else if(orbital.first.compare("LUMO")==0){ if(orbital.second<0){ cerr << "LUMO orbital number is not positive or 0" << endl; return false; } - if(orbital.second>(Hamiltonian_eff.rows()-LUMO_Orb_)){ + if(orbital.second>(Hamiltonian_eff.rows()-LUMO_AB)){ cerr << "LUMO orbital does not exst " << orbital.second << endl; return false; } @@ -506,8 +535,6 @@ Eigen::MatrixXd mergeListOfMatrices(list &matrix_list, const in int col = 0; for (auto it = matrix_list.begin(); it != matrix_list.end(); ++it) { Eigen::MatrixXd mat = *it; - cout << "Cycling columns to merge" << endl; - cout << mat << endl; int row = 0; if (col > cols) throw runtime_error("Your new matrix is not large enough"); @@ -525,7 +552,6 @@ Eigen::MatrixXd mergeListOfMatrices(list &matrix_list, const in int row = 0; for (auto it = matrix_list.begin(); it != matrix_list.end(); ++it) { Eigen::MatrixXd mat = *it; - cout << "Cycling rows " << endl; int col = 0; if (row > rows) throw runtime_error("Your new matrix is not large enough"); @@ -542,7 +568,6 @@ Eigen::MatrixXd mergeListOfMatrices(list &matrix_list, const in } else { throw invalid_argument("Unrecognized merge type for list of matrices"); } - cout << full_matrix << endl; return full_matrix; } @@ -583,22 +608,9 @@ Eigen::MatrixXd unscramble_Coef( pair pr(i + monAmatch.size(), matchDimerB.at(i)); monBmatch.push_back(pr); } - cout << "Contents of list before swap" << endl; - for( Eigen::MatrixXd & mat : p_atom_mat_coef ){ - cout << mat << "\n" << endl; - } refreshSwapOrder(monBmatch, monAmatch); - cout << "Contents of list before update" << endl; - for( Eigen::MatrixXd & mat : p_atom_mat_coef ){ - cout << mat << "\n" << endl; - } - updateSwapLists(monBmatch, monAmatch, p_atom_mat_coef); - cout << "Contents of list" << endl; - for( Eigen::MatrixXd & mat : p_atom_mat_coef ){ - cout << mat << "\n" << endl; - } Eigen::MatrixXd dimerCoef_new = createNewMatrix( p_atom_mat_coef, dimerCoef.rows(), dimerCoef.cols(), "Columns"); @@ -650,10 +662,6 @@ Eigen::MatrixXd unscramble_S( Eigen::MatrixXd S_new(S.rows(),S.cols()); { list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Columns"); - cout << "List of split matrices" << endl; - for( Eigen::MatrixXd & mat : p_atom_mat_S ){ - cout << mat << "\n" << endl; - } vector> monAmatch; for (unsigned i = 0; i < matchDimerA.size(); ++i) { pair pr(i, matchDimerA.at(i)); @@ -740,8 +748,8 @@ Eigen::MatrixXd unscramble_S( } TransferComplex::TransferComplex(Eigen::MatrixXd mat1Coef, Eigen::MatrixXd mat2Coef, - Eigen::MatrixXd matPCoef, std::pair MOs1, - std::pair MOs2, Eigen::MatrixXd matS, + Eigen::MatrixXd matPCoef, const int HOMO_A, + const int HOMO_B, Eigen::MatrixXd matS, Eigen::VectorXd vecPOE, bool cp) { unscrambled_ = false; @@ -781,8 +789,8 @@ TransferComplex::TransferComplex(Eigen::MatrixXd mat1Coef, Eigen::MatrixXd mat2C mat_2_Coef = mat2Coef; mat_P_Coef.resize(matPCoef.rows(),matPCoef.cols()); mat_P_Coef = matPCoef; - Orbs1 = MOs1; - Orbs2 = MOs2; + HOMO_A_ = HOMO_A; + HOMO_B_ = HOMO_B; mat_S.resize(matS.rows(),matS.cols()); mat_S = matS; vec_P_OE.resize(vecPOE.size()); @@ -842,7 +850,7 @@ void TransferComplex::unscramble(const Eigen::MatrixXd &coord_1_mat, void TransferComplex::calcJ() { if (unscrambled_ == false) { - cerr << "WARNING unable to automatically line up basis functions of" + cerr << "\nWARNING unable to automatically line up basis functions of" " monomers with dimers, you better make sure they correctly" " line up or run the calculations again with the correct " "flag pop=full" diff --git a/src/libcatnip/qc_functions.hpp b/src/libcatnip/qc_functions.hpp index a84bfb1..086af14 100644 --- a/src/libcatnip/qc_functions.hpp +++ b/src/libcatnip/qc_functions.hpp @@ -20,8 +20,8 @@ class TransferComplex { Eigen::MatrixXd mat_P_Coef; // Stores the number of Molecular orbitals // and the HOMO for both monomer 1 and 2 - std::pair Orbs1; - std::pair Orbs2; + //std::pair Orbs1; + //std::pair Orbs2; /** * \brief basis function overlap matrix @@ -42,9 +42,11 @@ class TransferComplex { **/ Eigen::MatrixXd Hamiltonian_eff; - int HOMO_Orb_; - int LUMO_Orb_; - Eigen::VectorXd vec_P_OE; + int HOMO_A_; + int HOMO_B_; + //int HOMO_Orb_; + //int LUMO_Orb_; + Eigen::RowVectorXd vec_P_OE; // If unscrambaling is required bool unscrambled_; bool counterPoise_; @@ -63,8 +65,8 @@ class TransferComplex { Eigen::MatrixXd mat1Coef, Eigen::MatrixXd mat2Coef, Eigen::MatrixXd matPCoef, - std::pair MOs1, - std::pair MOs2, + const int HOMO_A, + const int HOMO_B, Eigen::MatrixXd matS, Eigen::VectorXd vecPOE, bool cp); diff --git a/src/tools/main.cpp b/src/tools/main.cpp index 2e4db86..57648b7 100644 --- a/src/tools/main.cpp +++ b/src/tools/main.cpp @@ -125,14 +125,8 @@ int main(int argc, const char *argv[]) { vector basis_1 = lr_1.getBasisFuncCount(); vector basis_2 = lr_2.getBasisFuncCount(); - int MO1 = static_cast(vec_1_OE.size()); - int MO2 = static_cast(vec_2_OE.size()); - - pair Orbs1 = {MO1, HOMO1}; - pair Orbs2 = {MO2, HOMO2}; - LOG("Creating transfercomplex", 1); - TransferComplex TC(mat_1_Coef, mat_2_Coef, mat_P_Coef, Orbs1, Orbs2, mat_S, + TransferComplex TC(mat_1_Coef, mat_2_Coef, mat_P_Coef, HOMO1, HOMO2, mat_S, vec_P_OE, par->getCounterPoise()); // Set the transfer complex to counterpoise if it is the case. @@ -179,7 +173,6 @@ int main(int argc, const char *argv[]) { LOG("Calculating transfer integral", 1); TC.calcJ(); TC.printTransferIntegral(orbitaltypes, orbitalnums); - } return 0; From eae3804efd7c0a3826370fd5d05f17790201b465 Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Tue, 30 Apr 2019 21:46:20 -0600 Subject: [PATCH 16/68] Updated version --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bfdae7d..8ff81e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,8 +12,8 @@ option(CODE_COVERAGE "Enable coverage reporting" OFF) ############################################################################## # Defining settings ############################################################################## -set(calcJ_VERSION_MAJOR 1 ) -set(calcJ_VERSION_MINOR 8 ) +set(calcJ_VERSION_MAJOR 2 ) +set(calcJ_VERSION_MINOR 0 ) set(calcJ_YEAR_PUBLISHED 2018 ) set(calcJ_AUTHOR_SURNAME "\"Brown\"" ) set(calcJ_AUTHOR_INITIALS "\"J. S.\"" ) From c9ba31724aec6e255b5b9b99f4fc06fa01997b83 Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Tue, 30 Apr 2019 21:58:12 -0600 Subject: [PATCH 17/68] Added switch for printing all transfer integrals --- src/libcatnip/io/io.cpp | 17 +++++++++++++++++ src/libcatnip/parameters.hpp | 7 +++++-- src/tools/main.cpp | 6 +++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/libcatnip/io/io.cpp b/src/libcatnip/io/io.cpp index 28756bc..68e802c 100644 --- a/src/libcatnip/io/io.cpp +++ b/src/libcatnip/io/io.cpp @@ -167,6 +167,12 @@ unique_ptr prepareParser(void) { desc = "Print the version"; flag18.push_back(desc); + vector flag19; + flag19.push_back("--all"); + flag19.push_back("-a"); + desc = "Print all transfer integrals, in matrix form"; + flag19.push_back(desc); + set> flags; flags.insert(flag1); flags.insert(flag2); @@ -184,6 +190,7 @@ unique_ptr prepareParser(void) { flags.insert(flag16); flags.insert(flag17); flags.insert(flag18); + flags.insert(flag19); unique_ptr ArgPars(new ArgumentParser(flags)); @@ -303,6 +310,15 @@ unique_ptr prepareParser(void) { ArgPars->setFlagDefaultValue("--counter_poise", "OFF"); } + // Set argument for allowing printing of all transfer integrals + { + ArgPars->setFlagArgOpt("--all", "ARGUMENT_SWITCH", + "PROPERTY_SWITCH", "DEFAULT", "OFF"); + + // By default the flag counter poise is turned off + ArgPars->setFlagDefaultValue("--all", "OFF"); + } + { ArgPars->setFlagArgOpt("--citation", "ARGUMENT_SWITCH", "PROPERTY_SWITCH", "DEFAULT", "OFF"); @@ -424,6 +440,7 @@ unique_ptr prepareParameters(unique_ptr& ArgParse) { // Determine if we are doing a counterpoise calculation Par->setCounterPoise(ArgParse->getInt("--counter_poise")); + Par->setPrintSwitch(ArgParse->getInt("--all")); Par->setCitation(ArgParse->getInt("--citation")); // Read Orbital related flags { diff --git a/src/libcatnip/parameters.hpp b/src/libcatnip/parameters.hpp index 1664717..59590b4 100644 --- a/src/libcatnip/parameters.hpp +++ b/src/libcatnip/parameters.hpp @@ -29,7 +29,7 @@ class Parameters { bool citation; bool counterPoise; - + bool all; public: Parameters() : log1_(""), @@ -47,7 +47,8 @@ class Parameters { orb_numP(0), orb_num1(0), orb_num2(0), - counterPoise(false){}; + counterPoise(false), + all(false) {}; std::string getLog1() const { return log1_; } std::string getLog2() const { return log2_; } @@ -68,6 +69,7 @@ class Parameters { int getOrbNum1() const { return orb_num1; } int getOrbNum2() const { return orb_num2; } bool getCounterPoise() const { return counterPoise; } + bool getPrintSwitch() const { return all; } bool getCitation() const { return citation; } void setLog1(const std::string& log1); @@ -89,6 +91,7 @@ class Parameters { void setOrbNum1(const int& num) { orb_num1 = num; } void setOrbNum2(const int& num) { orb_num2 = num; } void setCounterPoise(bool cp) { counterPoise = cp; } + void setPrintSwitch(bool print_all) { all = print_all; } void setCitation(bool cite) { citation = cite; } }; diff --git a/src/tools/main.cpp b/src/tools/main.cpp index 57648b7..28742e8 100644 --- a/src/tools/main.cpp +++ b/src/tools/main.cpp @@ -172,7 +172,11 @@ int main(int argc, const char *argv[]) { LOG("Calculating transfer integral", 1); TC.calcJ(); - TC.printTransferIntegral(orbitaltypes, orbitalnums); + if(par->getPrintSwitch()){ + TC.printAll(); + }else{ + TC.printTransferIntegral(orbitaltypes, orbitalnums); + } } return 0; From 7797dae999ef3c0b397b40025e49479ec2f40cde Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Tue, 30 Apr 2019 22:05:46 -0600 Subject: [PATCH 18/68] Add eigen as a package to ci --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 7b97a17..d5f8369 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,7 @@ jobs: compiler: gcc script: ./scripts/deploy.bash apt: + packages: eigen packages: gcov packages: lcov From 9cbfb04627a1956d8cafad005cbaea0950347ab8 Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Wed, 1 May 2019 11:23:46 -0600 Subject: [PATCH 19/68] Added eigen to ci development stage --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index d5f8369..cbcd0fd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ dist: xenial addons: apt: update: true + packages: eigen language: cpp From ab1c42b8389d9276845259ffe7a2bd804342e360 Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Wed, 1 May 2019 13:05:54 -0600 Subject: [PATCH 20/68] Corrected formatting of print all --- src/libcatnip/qc_functions.cpp | 123 ++++++++++++++++++++++----------- 1 file changed, 84 insertions(+), 39 deletions(-) diff --git a/src/libcatnip/qc_functions.cpp b/src/libcatnip/qc_functions.cpp index 3346699..d27f23a 100644 --- a/src/libcatnip/qc_functions.cpp +++ b/src/libcatnip/qc_functions.cpp @@ -215,48 +215,93 @@ void TransferComplex::printTransferIntegral_( void TransferComplex::printAll() const { - int HOMO_AB = HOMO_A_+HOMO_B_; - int LUMO_AB = HOMO_AB+1; - int column_width = 8; + int column_width = 14; cout << "Effective Hamiltonian" << endl; - cout << setw(column_width+2) << ""; - for(int orbital_num = 0;orbital_numHamiltonian.cols()){ + end_col = Hamiltonian.cols(); + } + for(int orbital_num = start_col;orbital_num=col_offset && orbital_num<(HOMO_B_+col_offset))){ + if(orbital_num=HOMO_A_ && orbital_num(col_offset+HOMO_B_)){ + if(orbital_num=col_offset && orbital_num<(HOMO_B_+col_offset))){ + if(orbital_num & orbital) const{ From c71c9ae4a227199c9fb8cc49228414f42f8b47f1 Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Thu, 2 May 2019 12:02:59 -0600 Subject: [PATCH 21/68] UPdate eigen install in travis --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index cbcd0fd..fddda62 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ dist: xenial addons: apt: update: true - packages: eigen + packages: libeigen3-dev language: cpp @@ -18,7 +18,7 @@ jobs: compiler: gcc script: ./scripts/deploy.bash apt: - packages: eigen + packages: libeigen3-dev packages: gcov packages: lcov From 43745c9da7cf484f71e6fb60aa0819b0ead87e71 Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Thu, 2 May 2019 18:07:38 -0600 Subject: [PATCH 22/68] fixing eigen includes --- src/tests/CMakeLists.txt | 6 +++--- src/tests/test_qc_functions.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 134ca4b..bf8fc4b 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -28,7 +28,7 @@ if(ENABLE_TESTS) if(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") set_source_files_properties( ${PROG}.cpp PROPERTIES COMPILE_FLAGS ${COVERAGE_FLAGS} ) endif(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") - target_link_libraries(unit_${PROG} libcatnip Eigen3::Eigen) + target_link_libraries(unit_${PROG} libcatnip) add_test(unit_${PROG} unit_${PROG}) endforeach(PROG) endif(ENABLE_TESTS) @@ -44,7 +44,7 @@ if(ENABLE_INTEGRATION_TESTS) set_source_files_properties( ${PROG}.cpp PROPERTIES COMPILE_FLAGS ${COVERAGE_FLAGS}) endif(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") - target_link_libraries(integration${PROG} libcatnip Eigen3::Eigen) + target_link_libraries(integration${PROG} libcatnip) add_test(integration${PROG} integration${PROG}) endforeach(PROG) @@ -53,7 +53,7 @@ if(ENABLE_INTEGRATION_TESTS) if(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") set_source_files_properties( test_io.cpp PROPERTIES COMPILE_FLAGS ${COVERAGE_FLAGS}) endif(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") - target_link_libraries(test_io libcatnip Eigen3::Eigen) + target_link_libraries(test_io libcatnip) add_test(regression_test_io test_io -p_P "${PROJECT_SOURCE_DIR}/GAUSSIANFILES/30/30_pair.pun" -p_1 "${PROJECT_SOURCE_DIR}/GAUSSIANFILES/30/ref.pun" -p_2 "${PROJECT_SOURCE_DIR}/GAUSSIANFILES/30/30_2.pun") add_custom_command(TARGET test_io diff --git a/src/tests/test_qc_functions.cpp b/src/tests/test_qc_functions.cpp index b377280..a5d6759 100644 --- a/src/tests/test_qc_functions.cpp +++ b/src/tests/test_qc_functions.cpp @@ -3,7 +3,7 @@ #include #include #include -#include +#include using namespace catnip; using namespace std; From 71238ece4d21b0662c9d1f467e3b72cecbe8fc4b Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Thu, 2 May 2019 18:12:30 -0600 Subject: [PATCH 23/68] Fix cmake eigen call --- CMakeLists.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8ff81e4..1d8f065 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,10 +42,10 @@ configure_file( # Find bash it is important for testing using scripts find_program (BASH_PROGRAM bash) find_library (GCOV gcov) -find_package (Eigen3 3.3 REQUIRED NO_MODULE) -if (TARGET Eigen3::Eigen) - message("-- Eigen found") -endif(TARGET Eigen3::Eigen) +#find_package (Eigen3 3.3 REQUIRED NO_MODULE) +#if (TARGET Eigen3::Eigen) +# message("-- Eigen found") +#endif(TARGET Eigen3::Eigen) add_definitions(-DLOG_LEVEL=${LOG_LEVEL}) ############################################################################## @@ -120,5 +120,5 @@ if(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") target_link_libraries(calc_J gcov) set_source_files_properties( src/tools/main.cpp PROPERTIES COMPILE_FLAGS ${COVERAGE_FLAGS}) endif(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") -target_link_libraries(calc_J libcatnip ${COMMON_LIBRARIES} Eigen3::Eigen) +target_link_libraries(calc_J libcatnip ${COMMON_LIBRARIES}) install( TARGETS calc_J DESTINATION bin) From 4188483e05d185c1756d25d396165f12d86f31d8 Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Tue, 14 May 2019 00:26:31 -0600 Subject: [PATCH 24/68] Fixed problem when reading overlap matrix with only a few coefficients --- src/libcatnip/io/file_readers/logreader.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/libcatnip/io/file_readers/logreader.cpp b/src/libcatnip/io/file_readers/logreader.cpp index 700339c..3c0a0c3 100644 --- a/src/libcatnip/io/file_readers/logreader.cpp +++ b/src/libcatnip/io/file_readers/logreader.cpp @@ -145,9 +145,12 @@ void LogReader::OverlapSectionReader(void *ptr) { getline(LR_ptr->fid_, line); istringstream iss(line); iss >> countC; + if( line.find("Kinetic")!=string::npos){ + break; + } int countCint = stoi(countC); if (countCint != (countCoef + 1)) { - endFirstSection = true; + break; } else { ++countCoef; vector row; @@ -165,7 +168,7 @@ void LogReader::OverlapSectionReader(void *ptr) { } // Create a matrix and place all the current values in there - + Eigen::MatrixXd matrix_S(countCoef,countCoef); for (size_t row_ind = 0; row_ind < first_coefs.size(); ++row_ind) { From e97a27d67f3ca41425a341173dafd732b6d0508e Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Wed, 22 May 2019 01:31:14 -0600 Subject: [PATCH 25/68] Fixed error in script with J and, dimensions of matrices --- src/libcatnip/qc_functions.cpp | 10 +++++----- src/tests/test_script_calc_J.sh | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libcatnip/qc_functions.cpp b/src/libcatnip/qc_functions.cpp index d27f23a..0b49126 100644 --- a/src/libcatnip/qc_functions.cpp +++ b/src/libcatnip/qc_functions.cpp @@ -51,9 +51,9 @@ unordered_map> findRank(Eigen::VectorXd &Orb_E_Alpha, // Essentially calculates the transfer integral void TransferComplex::calculate_transfer_integral_() { - auto dimension = mat_1_Coef.rows()+mat_2_Coef.rows(); - Eigen::MatrixXd zetaA(mat_1_Coef.cols(),dimension); - Eigen::MatrixXd zetaB(mat_2_Coef.cols(),dimension); + auto dimension = mat_1_Coef.cols()+mat_2_Coef.cols(); + Eigen::MatrixXd zetaA(mat_1_Coef.rows(),dimension); + Eigen::MatrixXd zetaB(mat_2_Coef.rows(),dimension); if (counterPoise_) { LOG("Creating zeta matrices from coefficients assuming counterpoise", 2); @@ -65,12 +65,12 @@ void TransferComplex::calculate_transfer_integral_() { zetaB << Eigen::MatrixXd::Zero(mat_2_Coef.rows(),mat_1_Coef.cols()), mat_2_Coef; } - Eigen::MatrixXd zeta(dimension,dimension); LOG("Creating gamma and beta matrices", 2); Eigen::MatrixXd gammaA = zetaA * mat_S * mat_P_Coef.transpose(); Eigen::MatrixXd gammaB = zetaB * mat_S * mat_P_Coef.transpose(); - Eigen::MatrixXd gamma(dimension,dimension); + assert(gammaA.cols() == gammaB.cols() && "Column count between gamma A and B must be consistent"); + Eigen::MatrixXd gamma(gammaA.rows()+gammaB.rows(),gammaA.cols()); gamma << gammaB, gammaA; LOG("Calculating S_AB", 2); diff --git a/src/tests/test_script_calc_J.sh b/src/tests/test_script_calc_J.sh index a84363e..27bcc4f 100644 --- a/src/tests/test_script_calc_J.sh +++ b/src/tests/test_script_calc_J.sh @@ -1,7 +1,7 @@ #!/bin/bash if [ $# -eq 0 ]; then - path="./../" + path="./.." else path=$1 fi @@ -29,7 +29,7 @@ findJeff() { echo "Num array "${#values[@]} for (( i=0; i < ${#values[@]}; i++ )) do - if [ "${values[$i]}" == "J_eff" ] + if [ "${values[$i]}" == "J_ab_eff_single" ] then J_val=${values[$i+1]} break From 95fd3bd954f358428c0abdc8d8cd46e5a0521df6 Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Wed, 22 May 2019 01:44:46 -0600 Subject: [PATCH 26/68] fixed script --- src/tests/test_script_calc_J.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 src/tests/test_script_calc_J.sh diff --git a/src/tests/test_script_calc_J.sh b/src/tests/test_script_calc_J.sh old mode 100644 new mode 100755 From c458d905b5af1ab4d26f6c3f5731ab8146ccbc86 Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Wed, 22 May 2019 23:22:45 -0600 Subject: [PATCH 27/68] Temporary changes --- src/libcatnip/qc_functions.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/libcatnip/qc_functions.cpp b/src/libcatnip/qc_functions.cpp index 0b49126..bdd4153 100644 --- a/src/libcatnip/qc_functions.cpp +++ b/src/libcatnip/qc_functions.cpp @@ -73,16 +73,29 @@ void TransferComplex::calculate_transfer_integral_() { Eigen::MatrixXd gamma(gammaA.rows()+gammaB.rows(),gammaA.cols()); gamma << gammaB, gammaA; + std::cout << "Gamma Matrix" << std::endl; + std::cout << gamma << std::endl; LOG("Calculating S_AB", 2); S_AB.resize(dimension,dimension); S_AB = gamma * gamma.transpose(); + std::cout << "Overlap Matrix" << std::endl; + std::cout << S_AB << std::endl; + /// Find out if S_AB is invertible + if(S_AB.determinant()==0){ + throw invalid_argument("Error the determinant of the Molecular Orbital Overlap matrix is 0, this means it is not invertible and thus Symmetric orthogonalization cannot be applied."); + } Eigen::SelfAdjointEigenSolver eigen_solver(S_AB); Eigen::MatrixXd S_AB_inv_sqrt = eigen_solver.operatorInverseSqrt(); Hamiltonian.resize(mat_S.rows(),mat_S.cols()); Hamiltonian = gamma * vec_P_OE.asDiagonal() * gamma.transpose(); - + + std::cout << "Inverse overlap Matrix" << std::endl; + std::cout << S_AB_inv_sqrt << std::endl; + + std::cout << "Hamiltonian Matrix" << std::endl; + std::cout << Hamiltonian << std::endl; Hamiltonian_eff = S_AB_inv_sqrt * Hamiltonian * S_AB_inv_sqrt; } From fcc12f27420922cbd69c5f67b6b919720162ab32 Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Thu, 23 May 2019 11:06:53 -0600 Subject: [PATCH 28/68] Removed unused function --- src/libcatnip/qc_functions.cpp | 55 +++++++++++----------------------- src/libcatnip/qc_functions.hpp | 3 -- src/tools/main.cpp | 4 +++ 3 files changed, 22 insertions(+), 40 deletions(-) diff --git a/src/libcatnip/qc_functions.cpp b/src/libcatnip/qc_functions.cpp index bdd4153..1f6588f 100644 --- a/src/libcatnip/qc_functions.cpp +++ b/src/libcatnip/qc_functions.cpp @@ -21,33 +21,6 @@ namespace catnip { using namespace std; -unordered_map> findRank(Eigen::VectorXd &Orb_E_Alpha, - Eigen::VectorXd &Orb_E_Beta) { - - vector> all; - - for( int i = 0; i(Orb_E_Alpha(i),"Alpha")); - } - - for( int i = 0; i(Orb_E_Beta(i), "Beta")); - } - sort(all.begin(), all.end(), - [](const pair &P1, const pair &P2) - -> bool { return P1.first < P2.first; }); - // Now that they are sorted we are going to update the ranks - int rank = 1; - - unordered_map> rank_map; - - for (auto pr : all) { - rank_map[rank] = pr; - rank++; - } - return rank_map; -} - // Essentially calculates the transfer integral void TransferComplex::calculate_transfer_integral_() { @@ -876,32 +849,40 @@ void TransferComplex::unscramble(const Eigen::MatrixXd &coord_1_mat, this->mat_2_Coef = unscrambled_2_Coef; vector match_1_P = matchCol(coord_1_mat,coord_P_mat, sig_fig); + cout << "Matching coord1 with pair" << endl; + for( const int & val : match_1_P ) { + cout << val << endl; + } - Eigen::MatrixXd unscrambled_P_Coef = unscramble_Coef(match_1_P, basisP, mat_P_Coef); - - this->mat_P_Coef = unscrambled_P_Coef; - - auto unscrambled_S = unscramble_S(match_1_P, basisP, mat_S); + this->mat_P_Coef = unscramble_Coef(match_1_P, basisP, mat_P_Coef); - this->mat_S = unscrambled_S; + this->mat_S = unscramble_S(match_1_P, basisP, mat_S); } else { // Stores the rows in P that match 1 vector match_1_P = matchCol(coord_1_mat,coord_P_mat, sig_fig); + cout << "Matching coord1 with pair" << endl; + for( const int & val : match_1_P ) { + cout << val << endl; + } // Stores the rows in P that match 2 vector match_2_P = matchCol(coord_2_mat,coord_P_mat, sig_fig); + cout << "Matching coord2 with pair" << endl; + for( const int & val : match_2_P ) { + cout << val << endl; + } LOG("Unscrambling dimer matrix with respect to matrix 1 and 2", 2); - Eigen::MatrixXd unscrambled_P_Coef = + this->mat_P_Coef = unscramble_Coef(match_1_P, match_2_P, basisP, mat_P_Coef); - this->mat_P_Coef = unscrambled_P_Coef; + cout << "Unscrambled P Coef" << endl; + cout << mat_P_Coef << endl; - auto unscrambled_S = unscramble_S(match_1_P, match_2_P, basisP, mat_S); + this->mat_S = unscramble_S(match_1_P, match_2_P, basisP, mat_S); - this->mat_S = unscrambled_S; } } diff --git a/src/libcatnip/qc_functions.hpp b/src/libcatnip/qc_functions.hpp index 086af14..9bd7849 100644 --- a/src/libcatnip/qc_functions.hpp +++ b/src/libcatnip/qc_functions.hpp @@ -101,9 +101,6 @@ class TransferComplex { void printAll() const; }; -std::unordered_map> findRank( - Eigen::VectorXd& Orb_E_Alpha, Eigen::VectorXd& Orb_E_Beta); - // Reorganize the dimer coefficients to match up with the monomers Eigen::MatrixXd organize_P_Coef(std::vector matchDimerA, std::vector matchDimerB, diff --git a/src/tools/main.cpp b/src/tools/main.cpp index 28742e8..3ea694c 100644 --- a/src/tools/main.cpp +++ b/src/tools/main.cpp @@ -131,6 +131,10 @@ int main(int argc, const char *argv[]) { // Set the transfer complex to counterpoise if it is the case. + cout << "Printing number of basis funct per atom in pair " << endl; + for ( const int & val : basis_P ){ + cout << val << endl; + } // If the basis function search returns 0 for any of the components then // we cannot automatically determine what the transfer integral is if (basis_1.size() != 0 && basis_2.size() != 0 && basis_P.size() != 0) { From 6a801be76d956e7f610940ef5a59d9c40d102970 Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Thu, 23 May 2019 12:22:16 -0600 Subject: [PATCH 29/68] Fixed error, removed cout lines unneeded, added extra test --- src/libcatnip/qc_functions.cpp | 45 ++++++++------------------------- src/libcatnip/qc_functions.hpp | 16 ++++++------ src/tests/test_script_calc_J.sh | 20 +++++++++++++++ src/tools/main.cpp | 7 +---- 4 files changed, 40 insertions(+), 48 deletions(-) diff --git a/src/libcatnip/qc_functions.cpp b/src/libcatnip/qc_functions.cpp index 1f6588f..cff108b 100644 --- a/src/libcatnip/qc_functions.cpp +++ b/src/libcatnip/qc_functions.cpp @@ -44,31 +44,18 @@ void TransferComplex::calculate_transfer_integral_() { assert(gammaA.cols() == gammaB.cols() && "Column count between gamma A and B must be consistent"); Eigen::MatrixXd gamma(gammaA.rows()+gammaB.rows(),gammaA.cols()); - gamma << gammaB, gammaA; + gamma << gammaA, gammaB; - std::cout << "Gamma Matrix" << std::endl; - std::cout << gamma << std::endl; LOG("Calculating S_AB", 2); S_AB.resize(dimension,dimension); S_AB = gamma * gamma.transpose(); - std::cout << "Overlap Matrix" << std::endl; - std::cout << S_AB << std::endl; - /// Find out if S_AB is invertible - if(S_AB.determinant()==0){ - throw invalid_argument("Error the determinant of the Molecular Orbital Overlap matrix is 0, this means it is not invertible and thus Symmetric orthogonalization cannot be applied."); - } Eigen::SelfAdjointEigenSolver eigen_solver(S_AB); Eigen::MatrixXd S_AB_inv_sqrt = eigen_solver.operatorInverseSqrt(); Hamiltonian.resize(mat_S.rows(),mat_S.cols()); Hamiltonian = gamma * vec_P_OE.asDiagonal() * gamma.transpose(); - std::cout << "Inverse overlap Matrix" << std::endl; - std::cout << S_AB_inv_sqrt << std::endl; - - std::cout << "Hamiltonian Matrix" << std::endl; - std::cout << Hamiltonian << std::endl; Hamiltonian_eff = S_AB_inv_sqrt * Hamiltonian * S_AB_inv_sqrt; } @@ -175,7 +162,7 @@ void TransferComplex::printTransferIntegral_( double e_a = Hamiltonian(orbital1_num,orbital1_num); double e_b = Hamiltonian(orbital2_num,orbital2_num); double S_ab = S_AB(orbital1_num,orbital2_num); - + cout << "\nPre-Orthonormalization" << endl; cout << "J_ab " << J_ab * hartreeToeV << " eV\n"; cout << "e_a " << e_a * hartreeToeV << " eV\n"; @@ -197,6 +184,7 @@ void TransferComplex::printTransferIntegral_( cout << "J_ab_eff_all " << J_eff * hartreeToeV << " eV\n"; cout << "e_a_eff_all " << e_a_eff * hartreeToeV << " eV\n"; cout << "e_b_eff_all " << e_b_eff * hartreeToeV << " eV\n" << endl; + } void TransferComplex::printAll() const { @@ -778,10 +766,14 @@ Eigen::MatrixXd unscramble_S( return S_new; } -TransferComplex::TransferComplex(Eigen::MatrixXd mat1Coef, Eigen::MatrixXd mat2Coef, - Eigen::MatrixXd matPCoef, const int HOMO_A, - const int HOMO_B, Eigen::MatrixXd matS, - Eigen::VectorXd vecPOE, bool cp) { +TransferComplex::TransferComplex( + const Eigen::MatrixXd & mat1Coef, + const Eigen::MatrixXd & mat2Coef, + const Eigen::MatrixXd & matPCoef, + const int HOMO_A, + const int HOMO_B, + const Eigen::MatrixXd & matS, + const Eigen::VectorXd & vecPOE, bool cp) { unscrambled_ = false; counterPoise_ = cp; @@ -849,10 +841,6 @@ void TransferComplex::unscramble(const Eigen::MatrixXd &coord_1_mat, this->mat_2_Coef = unscrambled_2_Coef; vector match_1_P = matchCol(coord_1_mat,coord_P_mat, sig_fig); - cout << "Matching coord1 with pair" << endl; - for( const int & val : match_1_P ) { - cout << val << endl; - } this->mat_P_Coef = unscramble_Coef(match_1_P, basisP, mat_P_Coef); @@ -863,24 +851,13 @@ void TransferComplex::unscramble(const Eigen::MatrixXd &coord_1_mat, // Stores the rows in P that match 1 vector match_1_P = matchCol(coord_1_mat,coord_P_mat, sig_fig); - cout << "Matching coord1 with pair" << endl; - for( const int & val : match_1_P ) { - cout << val << endl; - } // Stores the rows in P that match 2 vector match_2_P = matchCol(coord_2_mat,coord_P_mat, sig_fig); - cout << "Matching coord2 with pair" << endl; - for( const int & val : match_2_P ) { - cout << val << endl; - } LOG("Unscrambling dimer matrix with respect to matrix 1 and 2", 2); this->mat_P_Coef = unscramble_Coef(match_1_P, match_2_P, basisP, mat_P_Coef); - cout << "Unscrambled P Coef" << endl; - cout << mat_P_Coef << endl; - this->mat_S = unscramble_S(match_1_P, match_2_P, basisP, mat_S); } diff --git a/src/libcatnip/qc_functions.hpp b/src/libcatnip/qc_functions.hpp index 9bd7849..6eef70b 100644 --- a/src/libcatnip/qc_functions.hpp +++ b/src/libcatnip/qc_functions.hpp @@ -62,13 +62,13 @@ class TransferComplex { const std::pair & Orbital2) const; public: TransferComplex( - Eigen::MatrixXd mat1Coef, - Eigen::MatrixXd mat2Coef, - Eigen::MatrixXd matPCoef, - const int HOMO_A, + const Eigen::MatrixXd & mat1Coef, + const Eigen::MatrixXd & mat2Coef, + const Eigen::MatrixXd & matPCoef, + const int HOMO_A, const int HOMO_B, - Eigen::MatrixXd matS, - Eigen::VectorXd vecPOE, + const Eigen::MatrixXd & matS, + const Eigen::VectorXd & vecPOE, bool cp); void unscramble( @@ -141,10 +141,10 @@ Eigen::MatrixXd unscramble_S( const std::vector& matchDimerA, const std::vector& basisFuncDimer, Eigen::MatrixXd S); - +/* Eigen::MatrixXd unscramble_OE(std::vector matchDimerA, std::vector matchDimerB, - std::vector basisFuncDimer, Eigen::VectorXd OE); + std::vector basisFuncDimer, Eigen::VectorXd OE);*/ } // namespace catnip #endif // _CATNIP_QC_FUNCTIONS_HPP diff --git a/src/tests/test_script_calc_J.sh b/src/tests/test_script_calc_J.sh index 27bcc4f..be21925 100755 --- a/src/tests/test_script_calc_J.sh +++ b/src/tests/test_script_calc_J.sh @@ -222,6 +222,26 @@ else fi echo $data >> $fileOut +# Note the only difference in this test is that we have switched p_1 and p_2 +# because the program auto matches the right basis function coordinates with +# the right atoms you should end up with the same numbers. +exec_command="${path}/build/calc_J -p_P ${path}/GAUSSIANFILES/CuBr2_Py/CuBr2-Py.pun -p_2 ${path}/GAUSSIANFILES/CuBr2_Py/CuBr2.pun -p_1 ${path}/GAUSSIANFILES/CuBr2_Py/Py.pun" +data=$(${exec_command}) +if [ $? -eq 0 ]; then + findJeff + if (( $(bc <<< "$J_val > -0.0055" ) )) && (( $(bc <<< "$J_val < -0.0053" ) )) + then + echo "${green}[SUCCESS]${reset} ${exec_command}" + else + echo "${red}[FAILURE]${reset} ${exec_command} expected output -0.00542741" + echo "actual output $J_val" + count_fails=$(($count_fails+1)) + fi +else + echo "${red}[FAILURE]${reset} ${exec_command}" + count_fails=$((count_fails+1)) +fi +echo $data >> $fileOut # The following commands should not work diff --git a/src/tools/main.cpp b/src/tools/main.cpp index 3ea694c..3809987 100644 --- a/src/tools/main.cpp +++ b/src/tools/main.cpp @@ -130,17 +130,12 @@ int main(int argc, const char *argv[]) { vec_P_OE, par->getCounterPoise()); // Set the transfer complex to counterpoise if it is the case. - - cout << "Printing number of basis funct per atom in pair " << endl; - for ( const int & val : basis_P ){ - cout << val << endl; - } // If the basis function search returns 0 for any of the components then // we cannot automatically determine what the transfer integral is if (basis_1.size() != 0 && basis_2.size() != 0 && basis_P.size() != 0) { LOG("Unscrambling matrices", 1); TC.unscramble(coord_1_mat, coord_2_mat, coord_P_mat, basis_P, basis_2); - } + } cout << endl; cout << "Dimer Spin " << par->getSpinP() << endl; From 1d8fcc5b4bba12b468402df0bc570cea23c6ace4 Mon Sep 17 00:00:00 2001 From: Joshua Scott Brown Date: Thu, 30 May 2019 15:17:30 -0600 Subject: [PATCH 30/68] Cleanup comments --- src/libcatnip/io/file_readers/filereader.cpp | 3 +-- src/libcatnip/qc_functions.hpp | 11 +---------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/libcatnip/io/file_readers/filereader.cpp b/src/libcatnip/io/file_readers/filereader.cpp index 1fd77ea..ffdd5f2 100644 --- a/src/libcatnip/io/file_readers/filereader.cpp +++ b/src/libcatnip/io/file_readers/filereader.cpp @@ -24,8 +24,6 @@ void FileReader::read() { close(); } -// Private member functions - void FileReader::open() { if (!fileExist_()) { throw invalid_argument("File " + fileName_ + " does not exist."); @@ -39,6 +37,7 @@ void FileReader::close() { fileOpen_ = false; } +// Private member functions void FileReader::registerSections_() { checkSections_(); } // Basically check that for a given tag both a section reader diff --git a/src/libcatnip/qc_functions.hpp b/src/libcatnip/qc_functions.hpp index 6eef70b..72843e6 100644 --- a/src/libcatnip/qc_functions.hpp +++ b/src/libcatnip/qc_functions.hpp @@ -18,10 +18,6 @@ class TransferComplex { Eigen::MatrixXd mat_1_Coef; Eigen::MatrixXd mat_2_Coef; Eigen::MatrixXd mat_P_Coef; - // Stores the number of Molecular orbitals - // and the HOMO for both monomer 1 and 2 - //std::pair Orbs1; - //std::pair Orbs2; /** * \brief basis function overlap matrix @@ -44,8 +40,7 @@ class TransferComplex { int HOMO_A_; int HOMO_B_; - //int HOMO_Orb_; - //int LUMO_Orb_; + Eigen::RowVectorXd vec_P_OE; // If unscrambaling is required bool unscrambled_; @@ -141,10 +136,6 @@ Eigen::MatrixXd unscramble_S( const std::vector& matchDimerA, const std::vector& basisFuncDimer, Eigen::MatrixXd S); -/* -Eigen::MatrixXd unscramble_OE(std::vector matchDimerA, - std::vector matchDimerB, - std::vector basisFuncDimer, Eigen::VectorXd OE);*/ } // namespace catnip #endif // _CATNIP_QC_FUNCTIONS_HPP From 61e115a644bcabc17e286e715bd2c5d9a20239d4 Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Tue, 11 Feb 2020 09:54:19 -0700 Subject: [PATCH 31/68] Added profiling options, for gprof --- CMakeLists.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d8f065..a36ae19 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,7 @@ project (calc_J) option(DOWNLOAD_TUTORIAL_FILES "Download tutorial files" OFF) option(ENABLE_INTEGRATION_TESTS "Enable integration tests" OFF) option(ENABLE_TESTS "Enable tests" OFF) +option(ENABLE_PROFILING "Enable profiling" OFF) option(CODE_COVERAGE "Enable coverage reporting" OFF) ############################################################################## @@ -26,7 +27,6 @@ set(LOG_LEVEL 0 CACHE INT "Choose the log level" ) # important for using gcov .o.gcno or .cpp.gcno now will be .gcno set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1) set(CMAKE_CXX_FLAGS "-Wall -Wextra -std=c++11 -pedantic -Werror") - ############################################################################## # Configuring header file with cmake variables ############################################################################## @@ -48,6 +48,14 @@ find_library (GCOV gcov) #endif(TARGET Eigen3::Eigen) add_definitions(-DLOG_LEVEL=${LOG_LEVEL}) +############################################################################## +# Setting up profiling +############################################################################## +if(ENABLE_PROFILING) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pg") +endif() ############################################################################## # Setting up testing ############################################################################## From e5d915baa45547065ab2865a6536134285857538 Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Tue, 11 Feb 2020 09:54:37 -0700 Subject: [PATCH 32/68] Deleted comments --- src/tools/main.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/tools/main.cpp b/src/tools/main.cpp index 3809987..51098f2 100644 --- a/src/tools/main.cpp +++ b/src/tools/main.cpp @@ -78,31 +78,21 @@ int main(int argc, const char *argv[]) { // No need to worry about beta orbitals { - //Matrix *mat_S = lr_P.getOverlapMatrix(); Eigen::MatrixXd mat_S = lr_P.getOverlapMatrix(); - //Matrix *mat_P_Coef = pr_P.getCoefsMatrix(par->getSpinP()); Eigen::MatrixXd mat_P_Coef = pr_P.getCoefsMatrix(par->getSpinP()); - //auto vec_P_OE = lr_P.getOE(par->getSpinP()); Eigen::VectorXd vec_P_OE = Eigen::VectorXd(lr_P.getOE(par->getSpinP())); - //Matrix *vec_P_OE = new Matrix(vec_P_OE); int HOMO1 = lr_1.getHOMOLevel(par->getSpin1()); LOG("Getting " + par->getSpin1() + " of monomer 1", 2); Eigen::MatrixXd mat_1_Coef = pr_1.getCoefsMatrix(par->getSpin1()); - //Matrix *mat_1_Coef = pr_1.getCoefsMatrix(par->getSpin1()); Eigen::VectorXd vec_1_OE = lr_1.getOE(par->getSpin1()); - //Matrix *mat_1_OE = new Matrix(vec_1_OE); - //Eigen::MatrixXd mat_1_OE = vec_1_OE.asDiagonal(); int HOMO2 = lr_2.getHOMOLevel(par->getSpin2()); LOG("Getting " + par->getSpin2() + " of monomer 2", 2); - //Matrix *mat_2_Coef = pr_2.getCoefsMatrix(par->getSpin2()); Eigen::MatrixXd mat_2_Coef = pr_2.getCoefsMatrix(par->getSpin2()); Eigen::VectorXd vec_2_OE = lr_2.getOE(par->getSpin2()); - //Matrix *mat_2_OE = new Matrix(vec_2_OE); - //Eigen::MatrixXd mat_2_OE = vec_2_OE.asDiagonal(); // Unscramble dimer coef and energies first need to see how the dimer // and monomer coefficients line up. To determine how the ceofficients From 4195c019d6450817242bd4f11035621bc6e6b849 Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Wed, 24 Jun 2020 06:38:11 -0600 Subject: [PATCH 33/68] Success compiling --- CMakeLists.txt | 51 ++-- src/libcatnip/CMakeLists.txt | 1 + src/libcatnip/qc_functions.cpp | 426 +++++++++++++++++++++------------ src/libcatnip/qc_functions.hpp | 124 ++++++---- src/tests/CMakeLists.txt | 8 +- src/tools/main.cpp | 172 ------------- 6 files changed, 378 insertions(+), 404 deletions(-) delete mode 100644 src/tools/main.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a36ae19..45ed8a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,8 +5,8 @@ project (calc_J) # Defining options ############################################################################## option(DOWNLOAD_TUTORIAL_FILES "Download tutorial files" OFF) -option(ENABLE_INTEGRATION_TESTS "Enable integration tests" OFF) -option(ENABLE_TESTS "Enable tests" OFF) +option(ENABLE_INTEGRATION_TESTING "Enable integration tests" OFF) +option(ENABLE_UNIT_TESTING "Enable tests" OFF) option(ENABLE_PROFILING "Enable profiling" OFF) option(CODE_COVERAGE "Enable coverage reporting" OFF) @@ -26,7 +26,7 @@ set(LOG_LEVEL 0 CACHE INT "Choose the log level" ) # Prevents multiple file extensions from being appended one after the other # important for using gcov .o.gcno or .cpp.gcno now will be .gcno set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1) -set(CMAKE_CXX_FLAGS "-Wall -Wextra -std=c++11 -pedantic -Werror") +set(CMAKE_CXX_FLAGS "-Wall -std=c++11 -Werror") ############################################################################## # Configuring header file with cmake variables ############################################################################## @@ -59,7 +59,7 @@ endif() ############################################################################## # Setting up testing ############################################################################## -if(ENABLE_INTEGRATION_TESTS) +if(ENABLE_INTEGRATION_TESTING) if(EXISTS "${PROJECT_SOURCE_DIR}/GAUSSIANFILES") message("GAUSSIANFILES found will not download") set(DOWNLOAD_TUTORIAL_FILES OFF) @@ -74,12 +74,12 @@ if(DOWNLOAD_TUTORIAL_FILES) execute_process(COMMAND ${PROJECT_SOURCE_DIR}/scripts/test_suite_install.bash "${PROJECT_SOURCE_DIR}" ) endif() -if(ENABLE_TESTS OR ENABLE_INTEGRATION_TESTS) - enable_testing() - add_subdirectory("${PROJECT_SOURCE_DIR}/src/tests") -endif() +#if(ENABLE_TESTS OR ENABLE_INTEGRATION_TESTS) +# enable_testing() +# add_subdirectory("${PROJECT_SOURCE_DIR}/src/tests") +#endif() -if (ENABLE_INTEGRATION_TESTS) +if (ENABLE_INTEGRATION_TESTING) file( COPY "${PROJECT_SOURCE_DIR}/GAUSSIANFILES/90_unordered/90_pair.log" DESTINATION "${PROJECT_BINARY_DIR}/GAUSSIANFILES/90_unordered") file( COPY "${PROJECT_SOURCE_DIR}/GAUSSIANFILES/90_unordered/90_pair.pun" @@ -93,7 +93,7 @@ if (ENABLE_INTEGRATION_TESTS) DESTINATION "${PROJECT_BINARY_DIR}/GAUSSIANFILES/30_unordered") endif() -if (ENABLE_TESTS) +if (ENABLE_UNIT_TESTING) file( COPY "${PROJECT_SOURCE_DIR}/src/tests/testfile.pun" DESTINATION "${PROJECT_BINARY_DIR}/src/tests") file( COPY "${PROJECT_SOURCE_DIR}/src/tests/testfile.log" @@ -105,28 +105,15 @@ endif() ############################################################################## # Add the binary tree to the search path for include files # so that we will find calcJconfig.hpp -include_directories("${PROJECT_BINARY_DIR}/src") -include_directories("${PROJECT_SOURCE_DIR}/src/libcatnip") -include_directories("${PROJECT_SOURCE_DIR}/src/libcatnip/io/arguments/properties") -include_directories("${PROJECT_SOURCE_DIR}/src/libcatnip/io/arguments") -include_directories("${PROJECT_SOURCE_DIR}/src/libcatnip/io/file_readers") -include_directories("${PROJECT_SOURCE_DIR}/src/libcatnip/io") +#target_include_directories(calc_J "${PROJECT_BINARY_DIR}/src") +#target_link_directories(calc_J "${PROJECT_BINARY_DIR}/src") -link_directories("${PROJECT_SOURCE_DIR}/src/libcatnip/io/arguments/properties") -link_directories("${PROJECT_SOURCE_DIR}/src/libcatnip/io/arguments") -link_directories("${PROJECT_SOURCE_DIR}/src/libcatnip/io/file_readers") -link_directories("${PROJECT_SOURCE_DIR}/src/libcatnip/io") -link_directories("${PROJECT_SOURCE_DIR}/src/libcatnip") +#link_directories("${PROJECT_SOURCE_DIR}/src/libcatnip/io/arguments/properties") +#link_directories("${PROJECT_SOURCE_DIR}/src/libcatnip/io/arguments") +#link_directories("${PROJECT_SOURCE_DIR}/src/libcatnip/io/file_readers") +#link_directories("${PROJECT_SOURCE_DIR}/src/libcatnip/io") +#link_directories("${PROJECT_SOURCE_DIR}/src/libcatnip") + +add_subdirectory("${PROJECT_SOURCE_DIR}/src") -add_subdirectory("${PROJECT_SOURCE_DIR}/src/libcatnip") -############################################################################## -# Creating calc_J and setting up code coverage if on -############################################################################## -add_executable(calc_J src/tools/main.cpp) -if(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") - target_link_libraries(calc_J gcov) - set_source_files_properties( src/tools/main.cpp PROPERTIES COMPILE_FLAGS ${COVERAGE_FLAGS}) -endif(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") -target_link_libraries(calc_J libcatnip ${COMMON_LIBRARIES}) -install( TARGETS calc_J DESTINATION bin) diff --git a/src/libcatnip/CMakeLists.txt b/src/libcatnip/CMakeLists.txt index 9e7f650..a8f855a 100644 --- a/src/libcatnip/CMakeLists.txt +++ b/src/libcatnip/CMakeLists.txt @@ -7,3 +7,4 @@ file(GLOB CATNIP_SOURCE_FILES io/file_readers/*.cpp) add_library(libcatnip ${CATNIP_SOURCE_FILES}) +target_include_directories(libcatnip PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") diff --git a/src/libcatnip/qc_functions.cpp b/src/libcatnip/qc_functions.cpp index cff108b..4132711 100644 --- a/src/libcatnip/qc_functions.cpp +++ b/src/libcatnip/qc_functions.cpp @@ -4,6 +4,7 @@ #include #include #include +#include // For accumulate #include #include #include @@ -20,7 +21,7 @@ namespace catnip { using namespace std; - +/* // Essentially calculates the transfer integral void TransferComplex::calculate_transfer_integral_() { @@ -46,17 +47,17 @@ void TransferComplex::calculate_transfer_integral_() { Eigen::MatrixXd gamma(gammaA.rows()+gammaB.rows(),gammaA.cols()); gamma << gammaA, gammaB; - LOG("Calculating S_AB", 2); - S_AB.resize(dimension,dimension); - S_AB = gamma * gamma.transpose(); + LOG("Calculating S_MO", 2); + S_MO.resize(dimension,dimension); + S_MO = gamma * gamma.transpose(); - Eigen::SelfAdjointEigenSolver eigen_solver(S_AB); - Eigen::MatrixXd S_AB_inv_sqrt = eigen_solver.operatorInverseSqrt(); + Eigen::SelfAdjointEigenSolver eigen_solver(S_MO); + Eigen::MatrixXd S_MO_inv_sqrt = eigen_solver.operatorInverseSqrt(); Hamiltonian.resize(mat_S.rows(),mat_S.cols()); Hamiltonian = gamma * vec_P_OE.asDiagonal() * gamma.transpose(); - Hamiltonian_eff = S_AB_inv_sqrt * Hamiltonian * S_AB_inv_sqrt; + Hamiltonian_eff = S_MO_inv_sqrt * Hamiltonian * S_MO_inv_sqrt; } void TransferComplex::printTransferIntegral( @@ -161,7 +162,7 @@ void TransferComplex::printTransferIntegral_( double J_ab = Hamiltonian(orbital1_num,orbital2_num); double e_a = Hamiltonian(orbital1_num,orbital1_num); double e_b = Hamiltonian(orbital2_num,orbital2_num); - double S_ab = S_AB(orbital1_num,orbital2_num); + double S_ab = S_MO(orbital1_num,orbital2_num); cout << "\nPre-Orthonormalization" << endl; cout << "J_ab " << J_ab * hartreeToeV << " eV\n"; @@ -372,55 +373,56 @@ list splitCoefsUpByAtoms(const vector & basisFuncP, Eigen: // the wrong result. // // For instance say we have a matrix -// 1 row1 -// 2 row2 -// 3 row3 -// 4 row4 +// index 1 | row 1 +// index 2 | row 2 +// index 3 | row 3 +// index 4 | row 4 // // where: -// Row 1 needs to be at row 3 -// Row 4 needs to be at row 1 -// Row 2 needs to be at row 2 -// Row 3 needs to be at row 4 +// Row 1 needs to be at index 3 +// Row 4 needs to be at index 1 +// Row 2 needs to be at index 2 +// Row 3 needs to be at index 4 // // If we simply looked at our first instance of the matrix shown above // and came up with the following swaps -// Swap row 1 with row 3 -// Swap row 4 with row 1 -// Swap row 2 with row 2 -// Swap row 3 with row 4 +// Swap row 1 with index 3 +// Swap row 4 with index 1 +// Swap row 2 with index 2 +// Swap row 3 with index 4 // // First swap -// 1 row3 -// 2 row2 -// 3 row1 -// 4 row4 +// index 1 row3 +// index 2 row2 +// index 3 row1 +// index 4 row4 // // Second swap -// 1 row4 -// 2 row2 -// 3 row1 -// 4 row3 +// index 1 row4 +// index 2 row2 +// index 3 row1 +// index 4 row3 // // Third swap does nothing // Fourth swap -// 1 row4 -// 2 row2 -// 3 row3 -// 4 row1 +// index 1 row4 +// index 2 row2 +// index 3 row3 +// index 4 row1 // // When what we really wanted was -// 1 row4 -// 2 row2 -// 3 row1 -// 4 row3 +// index 1 row4 +// index 2 row2 +// index 3 row1 +// index 4 row3 // // Notice the row3 and row1 are in the wrong place // The instructions should be rewritten -// Swap row 1 with row 3 -// Swap row 4 with row 3 -// Swap row 2 with row 2 - no swap -// Swap row 3 with row 3 - no swap +// Swap row 1 with index 3 +// Swap row 4 with index 3 +// Swap row 2 with index 2 - no swap +// Swap row 3 with index 3 - no swap +// void refreshSwapOrder(vector> &monBmatch, vector> &monAmatch) { @@ -508,6 +510,53 @@ void refreshSwapOrder(vector> &monAmatch) { return; } +// To replace both refreshSwapOrder and updateSwapLists +// instead of figuring out a proper order for swapping we will simply start +// with a new link list of the same size and place the coefficents in that +// new list +Eigen::MatrixXd createSortedCoefMatrix(vector> & mon_match_ind, list & atom_mat_coefs){ + + // Actually lets use a vector of pointers to the matrices that are in the list + vector mat_ptrs; + // Error checking + if(atom_mat_coefs.size()==0){ + throw std::runtime_error("ERROR cannot create sorted coef matrix, there are atomically partitioned matrices to build the full sorted coef matrix from."); + } + + int cols = atom_mat_coefs.front().cols(); + for ( list::iterator coef_ptr = atom_mat_coefs.begin(); + coef_ptr != atom_mat_coefs.end(); + ++coef_ptr ){ + if(coef_ptr->cols()!=cols){ + throw std::runtime_error("ERROR cannot created sorted coef matrix from atomically partitioned matrices with varying number of columns."); + } + } + // End of error checking + + // Count the total number of rows in each atomically partitioned coef matrix + vector rows_per_mat; + for ( list::iterator coef_ptr = atom_mat_coefs.begin(); + coef_ptr != atom_mat_coefs.end(); + ++coef_ptr ){ + rows_per_mat.push_back(coef_ptr->rows()); + } + + int initial_value = 0; + int total_rows = std::accumulate(rows_per_mat.begin(),rows_per_mat.end(), initial_value); + + // Determine the offset of each row to each index + std::map row_to_index_offset; + int offset = 0; + for ( std::pair & row_ind : mon_match_ind ){ + row_to_index_offset.at(row_ind.first) = offset; + offset+= rows_per_mat.at(row_ind.second); + } + + Eigen::MatrixXd sorted_atom_mat_coefs + + + +} // The above function determines the appropriate sequence of swaps this function // then actually implements the swaps by exchanging the matrices in the list. void updateSwapLists(vector> &monBmatch, @@ -597,19 +646,91 @@ Eigen::MatrixXd createNewMatrix(list &p_atom_mat_coef, int rows } // unscramble the coefficients -Eigen::MatrixXd unscramble_Coef( - const std::vector &matchDimerA, - const std::vector &matchDimerB, - const std::vector &basisFuncP, - const Eigen::MatrixXd & dimerCoef) { +//Eigen::MatrixXd unscramble_Coef( +// const std::vector &matchDimerA, +// const std::vector &matchDimerB, +// const std::vector &basisFuncP, +// const Eigen::MatrixXd & dimerCoef) { +// +// // Let's reduce the complexity of the problem by instead of working +// // with the basis functions lets just work with the atoms. We can do +// // this by treating all the basis functions associated with a single +// // atom as a block. +// +// list p_atom_mat_coef = +// splitCoefsUpByAtoms(basisFuncP, dimerCoef, "Columns"); +// +// // Place all of monomer A atom basis functions on the left side of the +// // matrix and all of B monomer atom basis functions on the right side +// // of the dimer matrix +// // First int is the col in the dimer the atom should be at +// // Second int is the col in the dimer the atom is presently at +// +// vector> monAmatch; +// for (unsigned i = 0; i < matchDimerA.size(); ++i) { +// pair pr(i, matchDimerA.at(i)); +// monAmatch.push_back(pr); +// } +// vector> monBmatch; +// for (unsigned i = 0; i < matchDimerB.size(); ++i) { +// pair pr(i + monAmatch.size(), matchDimerB.at(i)); +// monBmatch.push_back(pr); +// } +// +// refreshSwapOrder(monBmatch, monAmatch); +// updateSwapLists(monBmatch, monAmatch, p_atom_mat_coef); +// +// Eigen::MatrixXd dimerCoef_new = createNewMatrix( +// p_atom_mat_coef, dimerCoef.rows(), dimerCoef.cols(), "Columns"); +// +// return dimerCoef_new; +//} +// +//// unscramble the coefficients +//Eigen::MatrixXd unscramble_Coef( +// const std::vector &matchDimerB, +// const std::vector &basisFuncB, +// const Eigen::MatrixXd &Coef) { +// +// // Let's reduce the complexity of the problem by instead of working +// // with the basis functions lets just work with the atoms. We can do +// // this by treating all the basis functions associated with a single +// // atom as a block. +// +// list atom_mat_coef = +// splitCoefsUpByAtoms(basisFuncB, Coef, "Columns"); +// +// // Place all of monomer A atom basis functions on the left side of the +// // matrix and all of B monomer atom basis functions on the right side +// // of the matrix +// // First int is the col in the dimer the atom should be at +// // Second int is the col in the dimer the atom is presently at +// +// vector> monBmatch; +// for (unsigned i = 0; i < matchDimerB.size(); ++i) { +// pair pr(i, matchDimerB.at(i)); +// monBmatch.push_back(pr); +// } +// +// refreshSwapOrder(monBmatch); +// updateSwapLists(monBmatch, atom_mat_coef); +// Eigen::MatrixXd Coef_new = createNewMatrix(atom_mat_coef, Coef.rows(), +// Coef.cols(), "Columns"); +// return Coef_new; +//} + +Eigen::MatrixXd unscrambleCoef( + const std::vector> &match_mon_complex, + const std::vector &basis_functions_complex, + const Eigen::MatrixXd & complex_coefs) { // Let's reduce the complexity of the problem by instead of working // with the basis functions lets just work with the atoms. We can do // this by treating all the basis functions associated with a single // atom as a block. - list p_atom_mat_coef = - splitCoefsUpByAtoms(basisFuncP, dimerCoef, "Columns"); + list complex_coef_block = + splitCoefsUpByAtoms(basis_functions_complex, complex_coefs, "Columns"); // Place all of monomer A atom basis functions on the left side of the // matrix and all of B monomer atom basis functions on the right side @@ -617,59 +738,32 @@ Eigen::MatrixXd unscramble_Coef( // First int is the col in the dimer the atom should be at // Second int is the col in the dimer the atom is presently at - vector> monAmatch; - for (unsigned i = 0; i < matchDimerA.size(); ++i) { - pair pr(i, matchDimerA.at(i)); - monAmatch.push_back(pr); - } - vector> monBmatch; - for (unsigned i = 0; i < matchDimerB.size(); ++i) { - pair pr(i + monAmatch.size(), matchDimerB.at(i)); - monBmatch.push_back(pr); - } - - refreshSwapOrder(monBmatch, monAmatch); - updateSwapLists(monBmatch, monAmatch, p_atom_mat_coef); - - Eigen::MatrixXd dimerCoef_new = createNewMatrix( - p_atom_mat_coef, dimerCoef.rows(), dimerCoef.cols(), "Columns"); - - return dimerCoef_new; -} - -// unscramble the coefficients -Eigen::MatrixXd unscramble_Coef( - const std::vector &matchDimerB, - const std::vector &basisFuncB, - const Eigen::MatrixXd &Coef) { - - // Let's reduce the complexity of the problem by instead of working - // with the basis functions lets just work with the atoms. We can do - // this by treating all the basis functions associated with a single - // atom as a block. - - list atom_mat_coef = - splitCoefsUpByAtoms(basisFuncB, Coef, "Columns"); - - // Place all of monomer A atom basis functions on the left side of the - // matrix and all of B monomer atom basis functions on the right side - // of the matrix - // First int is the col in the dimer the atom should be at - // Second int is the col in the dimer the atom is presently at - - vector> monBmatch; - for (unsigned i = 0; i < matchDimerB.size(); ++i) { - pair pr(i, matchDimerB.at(i)); - monBmatch.push_back(pr); +// vector> monBmatch; +// for (unsigned i = 0; i < matchDimerB.size(); ++i) { +// pair pr(i, matchDimerB.at(i)); +// monBmatch.push_back(pr); +// } + + vector>> mon_match_index; + unsigned new_index = 0; + for ( const vector & monomer_rows : match_mon_complex){ + vector> mon_matching_index_row; + for( const int & row_index : monomer_rows ){ + pair pr(new_index,row_index); + mon_matching_index_row.push_back(pr); + } + mon_match_index.push_back(mon_matching_index_row); } - refreshSwapOrder(monBmatch); - updateSwapLists(monBmatch, atom_mat_coef); + //refreshSwapOrder(monBmatch); +// refreshSwapOrder(mon_match_index); + // updateSwapLists(monBmatch, atom_mat_coef); Eigen::MatrixXd Coef_new = createNewMatrix(atom_mat_coef, Coef.rows(), Coef.cols(), "Columns"); return Coef_new; -} + +} // Similar to the above function but we will be moving both the rows // and columns Eigen::MatrixXd unscramble_S( @@ -766,66 +860,96 @@ Eigen::MatrixXd unscramble_S( return S_new; } -TransferComplex::TransferComplex( - const Eigen::MatrixXd & mat1Coef, - const Eigen::MatrixXd & mat2Coef, - const Eigen::MatrixXd & matPCoef, - const int HOMO_A, - const int HOMO_B, - const Eigen::MatrixXd & matS, - const Eigen::VectorXd & vecPOE, bool cp) { + +//TransferComplex::TransferComplex( +// const Eigen::MatrixXd & mat1Coef, +// const Eigen::MatrixXd & mat2Coef, +// const Eigen::MatrixXd & matPCoef, +// const int HOMO_A, +// const int HOMO_B, +// const Eigen::MatrixXd & matS, +// const Eigen::VectorXd & vecPOE, bool cp) { +// +TransferComplex::TransferComplex(const Parameters params) : params_(params) { unscrambled_ = false; - counterPoise_ = cp; +// counterPoise_ = cp; // Consistency check - if (matS.cols() != matPCoef.cols()) { + if (params_.S_AO.cols() != params_.mat_complex.cols()) { throw invalid_argument( "The overlap matrix must have the same number " "of basis functions as the dimer"); } - if (cp) { - if (mat1Coef.cols() != matPCoef.cols()) { - throw invalid_argument( - "Counter poise correction requires that the" - " monomers have the same number of coefficients as the dimer. " - "Your monomer 1 does not"); - } - if (mat2Coef.cols() != matPCoef.cols()) { - throw invalid_argument( - "Counter poise correction requires that the" - " monomers have the same number of coefficients as the dimer. " - "Your monomer 2 does not"); - } + //if (cp) { + if (params_.counter_poise) { + int monomer_number = 1; + for ( const Eigen::MatrixXd & mat : params_.mat_monomers){ + if(params_.mat_complex.cols() != mat.cols()){ + throw invalid_argument( + "Counter poise correction requires that the" + " monomers have the same number of coefficients as the complex. " + "Your monomer " + std::to_string(monomer_number) +" does not"); + } + ++monomer_number; + } +// if (mat1Coef.cols() != matPCoef.cols()) { +// throw invalid_argument( +// "Counter poise correction requires that the" +// " monomers have the same number of coefficients as the dimer. " +// "Your monomer 1 does not"); +// } +// if (mat2Coef.cols() != matPCoef.cols()) { +// throw invalid_argument( +// "Counter poise correction requires that the" +// " monomers have the same number of coefficients as the dimer. " +// "Your monomer 2 does not"); +// } } else { - int total_cols = mat1Coef.cols() + mat2Coef.cols(); - - if (total_cols > matPCoef.cols()) { + /// If not counter poise the sum of the cols should equal the same number as is in the complex +// int total_cols = mat1Coef.cols() + mat2Coef.cols(); + int total_cols = 0; + for ( const Eigen::MatrixXd & mat : params_.mat_monomers){ + total_cols+=mat.cols(); + } + + //if (total_cols > matPCoef.cols()) { + if (total_cols > params_.mat_complex.cols()) { throw invalid_argument( - "Counter poise has not been specified and your " - "monomers have more basis function cols than your dimer"); + "Counter poise has not been specified and the total number of " + "basis functions in your monomers is more than the number of basis " + "functions in your complex."); + }else if(total_cols < params_.complex_coefs.cols()){ + throw invalid_argument( + "Counter poise has not been specified and the total number of " + "basis functions in your monomers is less than the number of basis " + "functions in your complex."); } } - - mat_1_Coef.resize(mat1Coef.rows(),mat1Coef.cols()); - mat_1_Coef = mat1Coef; - mat_2_Coef.resize(mat2Coef.rows(),mat2Coef.cols()); - mat_2_Coef = mat2Coef; - mat_P_Coef.resize(matPCoef.rows(),matPCoef.cols()); - mat_P_Coef = matPCoef; - HOMO_A_ = HOMO_A; - HOMO_B_ = HOMO_B; - mat_S.resize(matS.rows(),matS.cols()); - mat_S = matS; - vec_P_OE.resize(vecPOE.size()); - vec_P_OE = vecPOE; +// +// mat_1_Coef.resize(mat1Coef.rows(),mat1Coef.cols()); +// mat_1_Coef = mat1Coef; +// mat_2_Coef.resize(mat2Coef.rows(),mat2Coef.cols()); +// mat_2_Coef = mat2Coef; +// mat_P_Coef.resize(matPCoef.rows(),matPCoef.cols()); +// mat_P_Coef = matPCoef; +// HOMO_A_ = HOMO_A; +// HOMO_B_ = HOMO_B; +// mat_S.resize(matS.rows(),matS.cols()); +// mat_S = matS; +// vec_P_OE.resize(vecPOE.size()); +// vec_P_OE = vecPOE; } -void TransferComplex::unscramble(const Eigen::MatrixXd &coord_1_mat, - const Eigen::MatrixXd &coord_2_mat, - const Eigen::MatrixXd &coord_P_mat, - const std::vector &basisP, +//void TransferComplex::unscramble(const Eigen::MatrixXd &coord_1_mat, +// const Eigen::MatrixXd &coord_2_mat, +// const Eigen::MatrixXd &coord_P_mat, +// const std::vector &basisP, +// const std::vector &basis2) { +// +void TransferComplex::unscramble(const vector &coord_monomers, + const Eigen::MatrixXd &coord_complex, + const std::vector &basis_complex, const std::vector &basis2) { - unscrambled_ = true; const int sig_fig = 4; @@ -848,18 +972,20 @@ void TransferComplex::unscramble(const Eigen::MatrixXd &coord_1_mat, } else { - // Stores the rows in P that match 1 - vector match_1_P = matchCol(coord_1_mat,coord_P_mat, sig_fig); - + vector> match_mon_complex; + for ( const Eigen::MatrixXd & coord_mon : coord_monomers){ + // Returns each of the rows in complex that match each of the monomers + match_mon_complex.push_back(matchCol(coord_mon,coord_complex, sig_fig)); + } // Stores the rows in P that match 2 - vector match_2_P = matchCol(coord_2_mat,coord_P_mat, sig_fig); + //vector match_2_P = matchCol(coord_2_mat,coord_P_mat, sig_fig); LOG("Unscrambling dimer matrix with respect to matrix 1 and 2", 2); - this->mat_P_Coef = - unscramble_Coef(match_1_P, match_2_P, basisP, mat_P_Coef); - - this->mat_S = unscramble_S(match_1_P, match_2_P, basisP, mat_S); - + //this->mat_P_Coef = + // unscramble_Coef(match_1_P, match_2_P, basisP, mat_P_Coef); + this->params_.complex_coefs = unscrambleCoef(match_mon_complex,basis_complex,complex_coefs); +// this->mat_S = unscramble_S(match_1_P, match_2_P, basisP, mat_S); + } } } @@ -875,5 +1001,5 @@ void TransferComplex::calcJ() { calculate_transfer_integral_(); } - +*/ } // namespace catnip diff --git a/src/libcatnip/qc_functions.hpp b/src/libcatnip/qc_functions.hpp index 72843e6..ba25bcc 100644 --- a/src/libcatnip/qc_functions.hpp +++ b/src/libcatnip/qc_functions.hpp @@ -14,57 +14,35 @@ namespace catnip { class TransferComplex { - private: - Eigen::MatrixXd mat_1_Coef; - Eigen::MatrixXd mat_2_Coef; - Eigen::MatrixXd mat_P_Coef; - - /** - * \brief basis function overlap matrix - **/ - Eigen::MatrixXd mat_S; - /** - * \brief Molecular orbital overlap matrix - **/ - Eigen::MatrixXd S_AB; - - /** - * \brief Non orthonormalized Hamiltonian matrix - **/ - Eigen::MatrixXd Hamiltonian; - - /** - * \brief Orthonormalized Hamiltonian Matrix - **/ - Eigen::MatrixXd Hamiltonian_eff; - int HOMO_A_; - int HOMO_B_; - - Eigen::RowVectorXd vec_P_OE; - // If unscrambaling is required - bool unscrambled_; - bool counterPoise_; - - /* - * \brief Determine if the provided orbital is valid - **/ - bool orbitalValid_(const std::pair & orbital) const; + public: - void calculate_transfer_integral_(); + struct Parameters { + const std::vector monomers_coefs; + const Eigen::MatrixXd complex_coefs; + /// Location of each of the homo_orbitals in each of the monomers + const std::vector homo_orbitals; + //HOMO_A; + //const int HOMO_B; + /// Atomic Orbital overlap matrix + const Eigen::MatrixXd S_AO; + const Eigen::VectorXd complex_orbital_energies; + /// Counter poise flag + bool counter_poise = false; + /// Calculate all couplings + bool calculate_all = false; + }; - void printTransferIntegral_(const std::pair & Orbital1, - const std::pair & Orbital2) const; - public: TransferComplex( - const Eigen::MatrixXd & mat1Coef, + const Parameters params + /*const Eigen::MatrixXd & mat1Coef, const Eigen::MatrixXd & mat2Coef, const Eigen::MatrixXd & matPCoef, const int HOMO_A, const int HOMO_B, const Eigen::MatrixXd & matS, const Eigen::VectorXd & vecPOE, - bool cp); + bool cp*/); void unscramble( const Eigen::MatrixXd& coord_1_mat, @@ -94,6 +72,49 @@ class TransferComplex { * \brief Print All info in matrix form **/ void printAll() const; + + private: + + Parameters params_; +// Eigen::MatrixXd mat_1_Coef; +// Eigen::MatrixXd mat_2_Coef; +// Eigen::MatrixXd mat_P_Coef; + + /** + * \brief basis function overlap matrix + **/ + //Eigen::MatrixXd mat_S; + /** + * \brief Molecular orbital overlap matrix + **/ + Eigen::MatrixXd S_MO_; + + /** + * \brief Non orthonormalized Hamiltonian matrix + **/ + Eigen::MatrixXd Hamiltonian_; + + /** + * \brief Orthonormalized Hamiltonian Matrix + **/ + Eigen::MatrixXd Hamiltonian_eff_; + + //int HOMO_A_; + //int HOMO_B_; + + //Eigen::RowVectorXd vec_P_OE; + // If unscrambaling is required + bool unscrambled_; + //bool counterPoise_; + /* + * \brief Determine if the provided orbital is valid + **/ + bool orbitalValid_(const std::pair & orbital) const; + + void calculate_transfer_integral_(); + + void printTransferIntegral_(const std::pair & Orbital1, + const std::pair & Orbital2) const; }; // Reorganize the dimer coefficients to match up with the monomers @@ -109,12 +130,18 @@ Eigen::MatrixXd unscramble_Coef( const std::vector& matchDimerA, const std::vector& matchDimerB, const std::vector& basisFuncDimer, - const Eigen::MatrixXd & dimerCoef); + const Eigen::MatrixXd & dimerCoef) { + Eigen::MatrixXd m; + return m; +} Eigen::MatrixXd unscramble_Coef( const std::vector& matchDimerA, const std::vector& basisFuncDimer, - const Eigen::MatrixXd & dimerCoef); + const Eigen::MatrixXd & dimerCoef){ + Eigen::MatrixXd m; + return m; +} // Reorganize the dimer overlap matrix to line up with the monomer // coefficients. @@ -126,7 +153,10 @@ Eigen::MatrixXd unscramble_S( const std::vector& matchDimerA, const std::vector& matchDimerB, const std::vector& basisFuncDimer, - Eigen::MatrixXd S); + Eigen::MatrixXd S) { + Eigen::MatrixXd m; + return m; +} /** * @@ -135,7 +165,9 @@ Eigen::MatrixXd unscramble_S( Eigen::MatrixXd unscramble_S( const std::vector& matchDimerA, const std::vector& basisFuncDimer, - Eigen::MatrixXd S); - + Eigen::MatrixXd S){ + Eigen::MatrixXd m; + return m; +} } // namespace catnip #endif // _CATNIP_QC_FUNCTIONS_HPP diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index bf8fc4b..ab1c7c6 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -22,7 +22,7 @@ if(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") link_libraries(gcov) endif(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") -if(ENABLE_TESTS) +if(ENABLE_UNIT_TESTING) foreach(PROG IN LISTS UNIT_TEST_SOURCE_FILES) add_executable(unit_${PROG} ${PROG}.cpp) if(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") @@ -31,9 +31,9 @@ if(ENABLE_TESTS) target_link_libraries(unit_${PROG} libcatnip) add_test(unit_${PROG} unit_${PROG}) endforeach(PROG) -endif(ENABLE_TESTS) +endif(ENABLE_UNIT_TESTING) -if(ENABLE_INTEGRATION_TESTS) +if(ENABLE_INTEGRATION_TESTING) foreach(PROG test_logreader @@ -67,7 +67,7 @@ if(ENABLE_INTEGRATION_TESTS) endif(BASH_PROGRAM) -endif(ENABLE_INTEGRATION_TESTS) +endif(ENABLE_INTEGRATION_TESTING) diff --git a/src/tools/main.cpp b/src/tools/main.cpp deleted file mode 100644 index 51098f2..0000000 --- a/src/tools/main.cpp +++ /dev/null @@ -1,172 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../libcatnip/io/argumentparser.hpp" -#include "../libcatnip/io/file_readers/logreader.hpp" -#include "../libcatnip/io/file_readers/punreader.hpp" -#include "../libcatnip/io/io.hpp" -#include "../libcatnip/log.hpp" -#include "../libcatnip/parameters.hpp" -#include "../libcatnip/qc_functions.hpp" -#include "../libcatnip/matrix.hpp" -#include "../libcatnip/calcJconfig.hpp" - -#include - -using namespace catnip; -using namespace std; - -int main(int argc, const char *argv[]) { - cout << endl; - cout << "Running calc_J VERSION " << calcJ_VERSION_MAJOR << "."; - cout << calcJ_VERSION_MINOR << endl; - - string line; - LOG("Preparing parser", 1); - auto ArgPars = prepareParser(); - LOG("Parsing arguments", 1); - ArgPars->parse(argv, argc); - LOG("Preparing parameter object", 1); - auto par = prepareParameters(ArgPars); - - cout << "log file for first monomer is: " + par->getLog1() + '\n'; - cout << "log file for second monomer is: " + par->getLog2() + '\n'; - cout << "log file for dimer is: " + par->getLogP() + '\n'; - cout << "pun file for the first monomer is: " + par->getPun1() + '\n'; - cout << "pun file for the second monomer is: " + par->getPun2() + '\n'; - cout << "pun file for the dimer is: " + par->getPunP() + '\n'; - - // Open the .pun file find the total number of molecular orbitals - - LOG("Reading pun files", 1); - LOG("Reading pun file: " + par->getPunP(), 2); - PunReader pr_P(par->getPunP()); - pr_P.read(); - LOG("Reading pun file: " + par->getPun1(), 2); - PunReader pr_1(par->getPun1()); - pr_1.read(); - LOG("Reading pun file: " + par->getPun2(), 2); - PunReader pr_2(par->getPun2()); - pr_2.read(); - - LOG("Reading log files", 1); - LOG("Reading log file: " + par->getLogP(), 2); - LogReader lr_P(par->getLogP()); - lr_P.read(); - LOG("Reading log file: " + par->getLog1(), 2); - LogReader lr_1(par->getLog1()); - lr_1.read(); - LOG("Reading log file: " + par->getLog2(), 2); - LogReader lr_2(par->getLog2()); - lr_2.read(); - // Load in general coefficients - - // If there are only alpha orbitals then we can assume that restricted HF - // was used - - // No need to worry about beta orbitals - - { - Eigen::MatrixXd mat_S = lr_P.getOverlapMatrix(); - - Eigen::MatrixXd mat_P_Coef = pr_P.getCoefsMatrix(par->getSpinP()); - - Eigen::VectorXd vec_P_OE = Eigen::VectorXd(lr_P.getOE(par->getSpinP())); - - int HOMO1 = lr_1.getHOMOLevel(par->getSpin1()); - LOG("Getting " + par->getSpin1() + " of monomer 1", 2); - Eigen::MatrixXd mat_1_Coef = pr_1.getCoefsMatrix(par->getSpin1()); - Eigen::VectorXd vec_1_OE = lr_1.getOE(par->getSpin1()); - - int HOMO2 = lr_2.getHOMOLevel(par->getSpin2()); - LOG("Getting " + par->getSpin2() + " of monomer 2", 2); - Eigen::MatrixXd mat_2_Coef = pr_2.getCoefsMatrix(par->getSpin2()); - Eigen::VectorXd vec_2_OE = lr_2.getOE(par->getSpin2()); - - // Unscramble dimer coef and energies first need to see how the dimer - // and monomer coefficients line up. To determine how the ceofficients - // line up we will first look at how the atoms appear in each of the - // .gjf files. We will also check to see how many coefficients are - // assocaited with each of the atoms by checking the .log files. Given - // the position of the atoms in the monomer unit and the positions of - // the atoms in the dimer we can determine how the coefficients need - // to be rearranged. - vector> coord_P = lr_P.getCoords(); - vector> coord_1 = lr_1.getCoords(); - vector> coord_2 = lr_2.getCoords(); - - // Convert coords to matrices - Eigen::MatrixXd coord_P_mat = convert(coord_P); - Eigen::MatrixXd coord_1_mat = convert(coord_1); - Eigen::MatrixXd coord_2_mat = convert(coord_2); - - vector basis_P = lr_P.getBasisFuncCount(); - vector basis_1 = lr_1.getBasisFuncCount(); - vector basis_2 = lr_2.getBasisFuncCount(); - - LOG("Creating transfercomplex", 1); - TransferComplex TC(mat_1_Coef, mat_2_Coef, mat_P_Coef, HOMO1, HOMO2, mat_S, - vec_P_OE, par->getCounterPoise()); - - // Set the transfer complex to counterpoise if it is the case. - // If the basis function search returns 0 for any of the components then - // we cannot automatically determine what the transfer integral is - if (basis_1.size() != 0 && basis_2.size() != 0 && basis_P.size() != 0) { - LOG("Unscrambling matrices", 1); - TC.unscramble(coord_1_mat, coord_2_mat, coord_P_mat, basis_P, basis_2); - } - - cout << endl; - cout << "Dimer Spin " << par->getSpinP() << endl; - - cout << "Monomer 1 Spin " << par->getSpin1() << " "; - if (par->getOrbNum1() == 0) { - cout << "Orbital " << par->getOrbType1() << endl; - } else if (par->getOrbNum1() > 0) { - cout << "Orbital " << par->getOrbType1(); - cout << "+" << par->getOrbNum1() << endl; - } else { - cout << "Orbital " << par->getOrbType1(); - cout << par->getOrbNum1() << endl; - } - - cout << "Monomer 2 Spin " << par->getSpin2() << " "; - if (par->getOrbNum2() == 0) { - cout << "Orbital " << par->getOrbType2() << endl; - } else if (par->getOrbNum2() > 0) { - cout << "Orbital " << par->getOrbType2(); - cout << "+" << par->getOrbNum2() << endl; - } else { - cout << "Orbital " << par->getOrbType2(); - cout << par->getOrbNum2() << endl; - } - - map orbitaltypes; - map orbitalnums; - orbitaltypes["mon1"] = par->getOrbType1(); - orbitaltypes["mon2"] = par->getOrbType2(); - orbitalnums["mon1"] = par->getOrbNum1(); - orbitalnums["mon2"] = par->getOrbNum2(); - - LOG("Calculating transfer integral", 1); - TC.calcJ(); - if(par->getPrintSwitch()){ - TC.printAll(); - }else{ - TC.printTransferIntegral(orbitaltypes, orbitalnums); - } - } - - return 0; -} From 3c14cae25b29eae0b3827e83fb187bee63e2420e Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Wed, 24 Jun 2020 06:57:55 -0600 Subject: [PATCH 34/68] Fixed make target tests --- CMakeLists.txt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 45ed8a6..93d229e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,10 +74,9 @@ if(DOWNLOAD_TUTORIAL_FILES) execute_process(COMMAND ${PROJECT_SOURCE_DIR}/scripts/test_suite_install.bash "${PROJECT_SOURCE_DIR}" ) endif() -#if(ENABLE_TESTS OR ENABLE_INTEGRATION_TESTS) -# enable_testing() -# add_subdirectory("${PROJECT_SOURCE_DIR}/src/tests") -#endif() +if(ENABLE_UNIT_TESTING OR ENABLE_INTEGRATION_TESTING) + enable_testing() +endif() if (ENABLE_INTEGRATION_TESTING) file( COPY "${PROJECT_SOURCE_DIR}/GAUSSIANFILES/90_unordered/90_pair.log" From 0a142dd8eb28d5d162f9fc40eed358cc0325698c Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Thu, 9 Jul 2020 07:33:01 -0600 Subject: [PATCH 35/68] checkpoint --- src/CMakeLists.txt | 7 + src/libcatnip/atom.hpp | 40 + src/libcatnip/atom_group.cpp | 17 + src/libcatnip/atom_group.hpp | 83 ++ src/libcatnip/atom_group_container.cpp | 169 ++++ src/libcatnip/atom_group_container.hpp | 107 +++ src/libcatnip/calcJconfig.hpp | 18 + src/libcatnip/elements.hpp | 406 +++++++++ src/libcatnip/index_map.cpp | 43 + src/libcatnip/index_map.hpp | 28 + src/libcatnip/organizer.hpp | 29 + src/libcatnip/swap_engine.cpp | 84 ++ src/libcatnip/transfer_complex.cpp | 1155 ++++++++++++++++++++++++ src/libcatnip/transfer_complex.hpp | 74 ++ src/tests/test_qc_functions.cpp | 3 + 15 files changed, 2263 insertions(+) create mode 100644 src/CMakeLists.txt create mode 100644 src/libcatnip/atom.hpp create mode 100644 src/libcatnip/atom_group.cpp create mode 100644 src/libcatnip/atom_group.hpp create mode 100644 src/libcatnip/atom_group_container.cpp create mode 100644 src/libcatnip/atom_group_container.hpp create mode 100644 src/libcatnip/calcJconfig.hpp create mode 100644 src/libcatnip/elements.hpp create mode 100644 src/libcatnip/index_map.cpp create mode 100644 src/libcatnip/index_map.hpp create mode 100644 src/libcatnip/organizer.hpp create mode 100644 src/libcatnip/swap_engine.cpp create mode 100644 src/libcatnip/transfer_complex.cpp create mode 100644 src/libcatnip/transfer_complex.hpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..3637265 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,7 @@ +add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/libcatnip") +add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/tools") +if(ENABLE_UNIT_TESTING OR ENABLE_INTEGRATION_TESTING) + add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/tests") +endif() + + diff --git a/src/libcatnip/atom.hpp b/src/libcatnip/atom.hpp new file mode 100644 index 0000000..24c8b19 --- /dev/null +++ b/src/libcatnip/atom.hpp @@ -0,0 +1,40 @@ + +#pragma once +#ifndef _CATNIP_ATOM_HPP +#define _CATNIP_ATOM_HPP + + +#include "elements.hpp" + +#include + +namespace catnip { + + class Atom { + private: + Element element_; + Eigen::Vector3d xyz_; + int basis_func_count_ = -1; + public: + Atom(Element element, double x, double y, double z) : element_(element), xyz_(x,y,z) {}; + + void setBasisFuncCount(int count) { + basis_func_count_ = count; + } + + int getBasisFuncCount() const noexcept { return basis_func_count_; } + + bool equal( Atom & atm2 ) const { + if ( element_ == atm2.element_ ){ + if ( xyz_.isApprox(atm2.xyz_)) { + return true; + } + } + return false; + } + }; + + +} + +#endif // _CATNIP_ATOM_HPP diff --git a/src/libcatnip/atom_group.cpp b/src/libcatnip/atom_group.cpp new file mode 100644 index 0000000..cd5eb95 --- /dev/null +++ b/src/libcatnip/atom_group.cpp @@ -0,0 +1,17 @@ + +#include "atom_group.hpp" +#include "atom.hpp" + +namespace catnip { + + int AtomGroup::findIndex(std::shared_ptr atom) { + int index = 0; + for ( std::shared_ptr & atom_ : atoms_){ + if ( atom_->equal(*atom)){ + return index; + } + ++index; + } + return -1; + } +} diff --git a/src/libcatnip/atom_group.hpp b/src/libcatnip/atom_group.hpp new file mode 100644 index 0000000..6647207 --- /dev/null +++ b/src/libcatnip/atom_group.hpp @@ -0,0 +1,83 @@ +#pragma once +#ifndef _CATNIP_ATOM_GROUP_HPP +#define _CATNIP_ATOM_GROUP_HPP + +#include +#include +#include +#include +#include +#include + +#include + +namespace catnip { + + class Atom; + + /** + * @brief Atom groups can either be a component or a complex + */ + enum class GroupType { + PotentialComponent, // The atoms in all the components == the num atoms in the complex + Component, // All atoms in the components have a matching atom in the complex + Complex, + Unknown + }; + + /** + * @brief Stores the name of the atom group, the group type and the atoms in + * the group + * + */ + class AtomGroup { + private: + GroupType type_ = GroupType::Unknown; + std::string name_; + std::vector> atoms_; + public: + AtomGroup(std::string group_name) : name_(group_name) {}; + + size_t size() const noexcept { return atoms_.size(); } + + std::vector>::iterator + begin() { return atoms_.begin(); } + + std::vector>::iterator + end() { return atoms_.end(); } + + std::shared_ptr at(size_t ind) const { + return atoms_.at(ind); + } + + void add(std::shared_ptr atom){ + atoms_.push_back(atom); + } + + void add(std::vector> atoms){ + atoms_.insert(atoms_.end(),atoms.begin(),atoms.end()); + } + + size_t numberOfAtoms() const noexcept { + return atoms_.size(); + } + + void setType(const GroupType & type) noexcept { + type_ = type; + } + GroupType getType() const noexcept { return type_; } + + /** + * @brief Find the index of the atom in the group if it exists and return + * the index + * + * @param atom + * + * @return index if found -1 if not found + */ + int findIndex(std::shared_ptr atom); + }; + + +} // namespace catnip +#endif // _CATNIP_ATOM_GROUP_HPP diff --git a/src/libcatnip/atom_group_container.cpp b/src/libcatnip/atom_group_container.cpp new file mode 100644 index 0000000..08874c3 --- /dev/null +++ b/src/libcatnip/atom_group_container.cpp @@ -0,0 +1,169 @@ + +#include "atom_group_container.hpp" + +#include "atom.hpp" +#include "atom_group.hpp" + +#include +#include +#include +#include +#include +#include + +#include + +namespace catnip { + + void AtomGroupContainer::assignBasisFuncCountToComplex_(const std::vector& complex_basis_func_count) { + // Cycle through the atoms in the complex and assign the correct number of + // basis functions + int index = 0; + for( std::shared_ptr & atom_ptr : atom_groups_.at(index_of_complex_) ){ + atom_ptr->setBasisFuncCount(complex_basis_func_count.at(index)); + index++; + } + } + + // Assumes the complex atoms already have been assigned the basis functioncount + void AtomGroupContainer::assignBasisFuncCountToComponents_() { + std::vector paired_atoms = matchComponentAtomsToComplex_(); + for ( AtomMatch atom_match : paired_atoms ) { + int basis_func_count = atom_groups_.at(index_of_complex_).at(atom_match.index_complex_atom)->getBasisFuncCount(); + atom_groups_.at(atom_match.index_component).at(atom_match.index_component_atom)->setBasisFuncCount(basis_func_count); + } + } + + std::vector AtomGroupContainer::getGroups(const GroupType & type) const { + std::vector groups; + int ind1 = 0; + for( const AtomGroup & group : atom_groups_ ){ + if( group.getType() == type){ + groups.push_back(ind1); + } + ++ind1; + } + return groups; + } + std::unordered_map AtomGroupContainer::matchAtoms_( + const AtomGroup & grp1, const AtomGroup & grp2) const { + + std::unordered_map paired_atoms; + for ( size_t ind1 = 0; ind1 < grp1.size(); ++ind1){ + for (size_t ind2 = 0; ind2 < grp2.size(); ++ind2){ + if ( grp1.at(ind1)->equal(*grp2.at(ind2)) ){ + if ( paired_atoms.count(ind1) ) { + throw std::runtime_error("Atom in complex has already been paired with an atom in the component, you have two or more atoms in a component that are redundant with an atom in the complex"); + } + paired_atoms[ind1] = ind2; + break; + } + } + } + return paired_atoms; + } + + + void AtomGroupContainer::add( AtomGroup atom_group ) { + if( isUniqueGroup(atom_group) ){ + atom_groups_.push_back(atom_group); + } + group_types_uptodate_ = false; + index_of_complex_ = -1; + } + + void AtomGroupContainer::assignAtomGroupTypes(){ + if (group_types_uptodate_ ) return; + std::vector number_atoms; + for( AtomGroup group : atom_groups_){ + number_atoms.push_back(group.numberOfAtoms()); + } + auto max_elem_it = max_element(number_atoms.begin(),number_atoms.end()); + size_t max_elem = *max_elem_it; + for( AtomGroup group : atom_groups_){ + group.setType(GroupType::Component); + } + size_t number_atoms_excluding_max = std::accumulate(number_atoms.begin(),number_atoms.end(),-1*max_elem); + if ( std::count(number_atoms.begin(),number_atoms.end(), max_elem) == 1 && + number_atoms_excluding_max == max_elem ){ + for( AtomGroup group : atom_groups_){ + if( group.numberOfAtoms() == max_elem ){ + group.setType(GroupType::Complex); + index_of_complex_ = std::distance(number_atoms.begin(),max_elem_it); + } + } + } + group_types_uptodate_ = true; + } + + int AtomGroupContainer::getTotalBasisFunctionCount(const GroupType & type) const { + int total_num_basis = 0; + std::vector group_indices = getGroups(type); + for ( int ind : group_indices ){ + AtomGroup group = getGroup(ind); + for( const std::shared_ptr & atom_ptr : group ) { + total_num_basis += atom_ptr->getBasisFuncCount(); + } + } + return total_num_basis; + } + + int AtomGroupContainer::getMaxBasisFunctionCount(const GroupType & type) const { + int max_num_basis = 0; + std::vector group_indices = getGroups(type); + for ( int ind : group_indices ){ + AtomGroup group = getGroup(ind); + for( const std::shared_ptr & atom_ptr : group ) { + if( atom_ptr->getBasisFuncCount() > max_num_basis){ + max_num_basis = atom_ptr->getBasisFuncCount(); + } + } + } + return max_num_basis; + } + + bool AtomGroupContainer::complexExists() const { + // First check that all the group types have been assigned + if ( group_types_uptodate_ == false ){ + throw std::runtime_error("Cannot determine if complex exists group types are not up to date"); + } + return index_of_complex_ > -1; + } + + std::vector AtomGroupContainer::matchComponentAtomsToComplex_(){ + + AtomGroup complex_group = atom_groups_.at(index_of_complex_); + std::vector component_indices = getGroups(GroupType::Component); + std::vector all_paired_atoms; + for ( const int & component_index : component_indices ) { + std::unordered_map paired_atoms = matchAtoms_(complex_group,atom_groups_.at(component_index)); + // Pass to vector + for ( auto pr : paired_atoms ){ + AtomMatch atom_match; + atom_match.index_component = component_index; + atom_match.index_component_atom = pr.second; + atom_match.index_complex_atom = pr.first; + all_paired_atoms.push_back(atom_match); + } + } + } + + void AtomGroupContainer::assignBasisFunctionCount( + const std::vector& complex_basis_func_count) { + + // 1. Check that up to date + if ( group_types_uptodate_ == false ){ + throw std::runtime_error("Cannot assign basis functions to atoms as group types are not up to date!"); + } + // 2. Check that the number of atoms in the complex is consistent with the number of values provided + if ( complex_basis_func_count.size() != atom_groups_.at(index_of_complex_).numberOfAtoms() ){ + throw std::runtime_error("Cannot assign basis function count to atoms as the basis function count vector is not equal to the number of atoms!"); + } + + assignBasisFuncCountToComplex_(complex_basis_func_count); + assignBasisFuncCountToComponents_(); + + } + + +} // namespace catnip diff --git a/src/libcatnip/atom_group_container.hpp b/src/libcatnip/atom_group_container.hpp new file mode 100644 index 0000000..4203669 --- /dev/null +++ b/src/libcatnip/atom_group_container.hpp @@ -0,0 +1,107 @@ +#pragma once +#ifndef _CATNIP_ATOM_GROUP_CONTAINER_HPP +#define _CATNIP_ATOM_GROUP_CONTAINER_HPP + +#include "atom_group.hpp" + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace catnip { + + class Atom; + + class AtomGroupContainer { + std::vector atom_groups_; + + bool group_types_uptodate_ = false; + /** + * @brief Checks to makes sure the group is unique + * + * @param atom_group + * + * @return + */ + bool isUniqueGroup_( AtomGroup atom_group ); + + + /** + * @brief Match the indices of the first atom group with any that share + * coordinates and the same element in atom group 2 + * + * @param grp1 + * @param grp2 + * + * @return map returns indices in group two that match group 1 + */ + std::unordered_map matchAtoms_( const AtomGroup & grp1, const AtomGroup & grp2) const; + + void assignBasisFuncCountToComplex_(const std::vector& complex_basis_func_count); + void assignBasisFuncCountToComponents_(); + + struct AtomMatch { + int index_component; + int index_component_atom; + int index_complex_atom; + }; + + std::vector matchComponentAtomsToComplex_(); + int index_of_complex_ = -1; + public: + void add( AtomGroup atom_group ); + + /** + * @brief This algorithm determines if a complex exists + * + * This algorithm does not compare the atoms in the complex with the + * atoms in the components, so it is not a rigourous algorithm but should + * be sufficient for our purposes. + * + * Only a single atom group can be the complex + */ + void assignAtomGroupTypes(); + + /** + * @brief Determine if a complex exists within the atom groups + * + * Only a single atom group can be a complex + * + * @return + */ + bool complexExists() const ; + + /** + * @brief If a complex exists and we know the number of basis functions + * associated with each atom in the complex we can assign the basis function + * number to each of the atoms + * + * @param complex_basis_func_count + */ + void assignBasisFunctionCount(const std::vector& complex_basis_func_count); + + int getTotalBasisFunctionCount(const GroupType & type) const; + + int getMaxBasisFunctionCount(const GroupType & type) const; + /** + * @brief Get the indices of all the groups of the specified group type + * + * @param type + * + * @return + */ + std::vector getGroups(const GroupType & type) const; + + AtomGroup getGroup(size_t ind) const { return atom_groups_.at(ind);} + + + }; + +} // namespace catnip +#endif // _CATNIP_ATOM_GROUP_CONTAINER_HPP diff --git a/src/libcatnip/calcJconfig.hpp b/src/libcatnip/calcJconfig.hpp new file mode 100644 index 0000000..e574fe9 --- /dev/null +++ b/src/libcatnip/calcJconfig.hpp @@ -0,0 +1,18 @@ +// Configured options and settings for calcJ + +#ifndef CATNIP_CONFIG_HPP +#define CATNIP_CONFIG_HPP + +#include + +namespace catnip { +const int calcJ_VERSION_MAJOR = 2; +const int calcJ_VERSION_MINOR = 0; +const int calcJ_YEAR_PUBLISHED = 2018; +const std::string calcJ_AUTHOR_SURNAME = "Brown"; +const std::string calcJ_AUTHOR_INITIALS = "J. S."; +const std::string calcJ_TITLE = "CATNIP"; +const std::string calcJ_URL = "https://github.com/JoshuaSBrown/QC_Tools"; +} // namespace catnip + +#endif // CATNIP_CONFIG_HPP diff --git a/src/libcatnip/elements.hpp b/src/libcatnip/elements.hpp new file mode 100644 index 0000000..03fc1b5 --- /dev/null +++ b/src/libcatnip/elements.hpp @@ -0,0 +1,406 @@ +#include +#include +#include +#include + +namespace catnip { + + enum class Element { + Ac, + Al, + Am, + Sb, + Ar, + As, + At, + Ba, + Bk, + Be, + Bi, + Bh, + B, + Br, + Cd, + Ca, + Cf, + C, + Ce, + Cs, + Cl, + Cr, + Co, + Cu, + Cm, + Ds, + Db, + Dy, + Es, + Er, + Eu, + Fm, + F, + Fr, + Gd, + Ga, + Ge, + Au, + Hf, + Hs, + He, + Ho, + H, + In, + I, + Ir, + Fe, + Kr, + La, + Lr, + Pb, + Li, + Lu, + Mg, + Mn, + Mt, + Md, + Hg, + Mo, + Nd, + Ne, + Np, + Ni, + Nb, + N, + No, + Uuo, + Os, + O, + Pd, + P, + Pt, + Pu, + Po, + K, + Pr, + Pm, + Pa, + Ra, + Rn, + Re, + Rh, + Rg, + Rb, + Ru, + Rf, + Sm, + Sc, + Sg, + Se, + Si, + Ag, + Na, + Sr, + S, + Ta, + Tc, + Te, + Tb, + Tl, + Th, + Tm, + Sn, + Ti, + W, + Uub, + Uuh, + Uup, + Uuq, + Uus, + Uut, + U, + V, + Xe, + Yb, + Y, + Zn, + Zr, + Unknown + }; + + /** + * @brief For manipulating Elements + * + * Converts string to enum class type + */ + class Elements { + + private: + void to_lower_(std::string & data) const noexcept { + std::transform(data.begin(), data.end(), data.begin(), + [](unsigned char c){ return std::tolower(c); }); + } + public: + + /** + * @brief Case insensitive get Element enum + * + * @param element_name + * + * @return + */ + Element getElement(std::string element_name) const noexcept { + to_lower_(element_name); + if( elements_.count(element_name)) { + return elements_.at(element_name); + } + if( elementssym_.count(element_name)) { + return elementssym_.at(element_name); + } + return Element::Unknown; + } + + private: + std::map elements_ = { + {"actinium", Element::Ac}, + {"aluminum", Element::Al}, + {"americium", Element::Am}, + {"antimony", Element::Sb}, + {"argon", Element::Ar}, + {"arsenic", Element::As}, + {"astatine", Element::At}, + {"barium", Element::Ba}, + {"berkelium", Element::Bk}, + {"beryllium", Element::Be}, + {"bismuth", Element::Bi}, + {"bohrium", Element::Bh}, + {"boron", Element::B}, + {"bromine", Element::Br}, + {"cadmium", Element::Cd}, + {"calcium", Element::Ca}, + {"californium", Element::Cf}, + {"carbon", Element::C}, + {"cerium", Element::Ce}, + {"cesium", Element::Cs}, + {"chlorine", Element::Cl}, + {"chromium", Element::Cr}, + {"cobalt", Element::Co}, + {"copper", Element::Cu}, + {"curium", Element::Cm}, + {"darmstadtium", Element::Ds}, + {"dubnium", Element::Db}, + {"dysprosium", Element::Dy}, + {"einsteinium", Element::Es}, + {"erbium", Element::Er}, + {"europium", Element::Eu}, + {"fermium", Element::Fm}, + {"fluorine", Element::F}, + {"francium", Element::Fr}, + {"gadolinium", Element::Gd}, + {"gallium", Element::Ga}, + {"germanium", Element::Ge}, + {"gold", Element::Au}, + {"hafnium", Element::Hf}, + {"hassium", Element::Hs}, + {"helium", Element::He}, + {"holmium", Element::Ho}, + {"hydrogen", Element::H}, + {"indium", Element::In}, + {"iodine", Element::I}, + {"iridium", Element::Ir}, + {"iron", Element::Fe}, + {"krypton", Element::Kr}, + {"lanthanum", Element::La}, + {"lawrencium", Element::Lr}, + {"lead", Element::Pb}, + {"lithium", Element::Li}, + {"lutetium", Element::Lu}, + {"magnesium", Element::Mg}, + {"manganese", Element::Mn}, + {"meitnerium", Element::Mt}, + {"mendelevium", Element::Md}, + {"mercury", Element::Hg}, + {"molybdenum", Element::Mo}, + {"neodymium", Element::Nd}, + {"neon", Element::Ne}, + {"neptunium", Element::Np}, + {"nickel", Element::Ni}, + {"niobium", Element::Nb}, + {"nitrogen", Element::N}, + {"nobelium", Element::No}, + {"oganesson", Element::Uuo}, + {"osmium", Element::Os}, + {"oxygen", Element::O}, + {"palladium", Element::Pd}, + {"phosphorus", Element::P}, + {"platinum", Element::Pt}, + {"plutonium", Element::Pu}, + {"polonium", Element::Po}, + {"potassium", Element::K}, + {"praseodymium", Element::Pr}, + {"promethium", Element::Pm}, + {"protactinium", Element::Pa}, + {"radium", Element::Ra}, + {"radon", Element::Rn}, + {"rhenium", Element::Re}, + {"rhodium", Element::Rh}, + {"roentgenium", Element::Rg}, + {"rubidium", Element::Rb}, + {"ruthenium", Element::Ru}, + {"rutherfordium",Element::Rf}, + {"samarium", Element::Sm}, + {"scandium", Element::Sc}, + {"seaborgium", Element::Sg}, + {"selenium", Element::Se}, + {"silicon", Element::Si}, + {"silver", Element::Ag}, + {"sodium", Element::Na}, + {"strontium", Element::Sr}, + {"sulfur", Element::S}, + {"tantalum", Element::Ta}, + {"technetium", Element::Tc}, + {"tellurium", Element::Te}, + {"terbium", Element::Tb}, + {"thallium", Element::Tl}, + {"thorium", Element::Th}, + {"thulium", Element::Tm}, + {"tin", Element::Sn}, + {"titanium", Element::Ti}, + {"tungsten", Element::W}, + {"ununbium", Element::Uub}, + {"ununhexium", Element::Uuh}, + {"ununpentium", Element::Uup}, + {"ununquadium", Element::Uuq}, + {"ununseptium", Element::Uus}, + {"ununtrium", Element::Uut}, + {"uranium", Element::U}, + {"vanadium", Element::V}, + {"xenon", Element::Xe}, + {"ytterbium", Element::Yb}, + {"yttrium", Element::Y}, + {"zinc", Element::Zn}, + {"zirconium", Element::Zr}}; + + std::map elementssym_ = { + {"ac", Element::Ac}, + {"al", Element::Al}, + {"am", Element::Am}, + {"sb", Element::Sb}, + {"ar", Element::Ar}, + {"as", Element::As}, + {"at", Element::At}, + {"ba", Element::Ba}, + {"bk", Element::Bk}, + {"be", Element::Be}, + {"bi", Element::Bi}, + {"bh", Element::Bh}, + {"b", Element::B}, + {"br", Element::Br}, + {"cd", Element::Cd}, + {"ca", Element::Ca}, + {"cf", Element::Cf}, + {"c", Element::C}, + {"ce", Element::Ce}, + {"cs", Element::Cs}, + {"cl", Element::Cl}, + {"cr", Element::Cr}, + {"co", Element::Co}, + {"cu", Element::Cu}, + {"cm", Element::Cm}, + {"ds", Element::Ds}, + {"db", Element::Db}, + {"dy", Element::Dy}, + {"es", Element::Es}, + {"er", Element::Er}, + {"eu", Element::Eu}, + {"fm", Element::Fm}, + {"f", Element::F}, + {"fr", Element::Fr}, + {"gd", Element::Gd}, + {"ga", Element::Ga}, + {"ge", Element::Ge}, + {"au", Element::Au}, + {"hf", Element::Hf}, + {"hs", Element::Hs}, + {"he", Element::He}, + {"ho", Element::Ho}, + {"h", Element::H}, + {"in", Element::In}, + {"i", Element::I}, + {"ir", Element::Ir}, + {"fe", Element::Fe}, + {"kr", Element::Kr}, + {"la", Element::La}, + {"lr", Element::Lr}, + {"pb", Element::Pb}, + {"li", Element::Li}, + {"lu", Element::Lu}, + {"mg", Element::Mg}, + {"mn", Element::Mn}, + {"mt", Element::Mt}, + {"md", Element::Md}, + {"hg", Element::Hg}, + {"mo", Element::Mo}, + {"nd", Element::Nd}, + {"ne", Element::Ne}, + {"np", Element::Np}, + {"ni", Element::Ni}, + {"nb", Element::Nb}, + {"n", Element::N}, + {"no", Element::No}, + {"uuo", Element::Uuo}, + {"os", Element::Os}, + {"o", Element::O}, + {"pd", Element::Pd}, + {"p", Element::P}, + {"pt", Element::Pt}, + {"pu", Element::Pu}, + {"po", Element::Po}, + {"k", Element::K}, + {"pr", Element::Pr}, + {"pm", Element::Pm}, + {"pa", Element::Pa}, + {"ra", Element::Ra}, + {"rn", Element::Rn}, + {"re", Element::Re}, + {"rh", Element::Rh}, + {"rg", Element::Rg}, + {"rb", Element::Rb}, + {"ru", Element::Ru}, + {"rf", Element::Rf}, + {"sm", Element::Sm}, + {"sc", Element::Sc}, + {"sg", Element::Sg}, + {"se", Element::Se}, + {"si", Element::Si}, + {"ag", Element::Ag}, + {"na", Element::Na}, + {"sr", Element::Sr}, + {"s", Element::S}, + {"ta", Element::Ta}, + {"tc", Element::Tc}, + {"te", Element::Te}, + {"tb", Element::Tb}, + {"tl", Element::Tl}, + {"th", Element::Th}, + {"tm", Element::Tm}, + {"sn", Element::Sn}, + {"ti", Element::Ti}, + {"w", Element::W}, + {"uub", Element::Uub}, + {"uuh", Element::Uuh}, + {"uup", Element::Uup}, + {"uuq", Element::Uuq}, + {"uus", Element::Uus}, + {"uut", Element::Uut}, + {"u", Element::U}, + {"v", Element::V}, + {"xe", Element::Xe}, + {"yb", Element::Yb}, + {"y", Element::Y}, + {"zn", Element::Zn}, + {"zr", Element::Zr}}; + + }; + +} + diff --git a/src/libcatnip/index_map.cpp b/src/libcatnip/index_map.cpp new file mode 100644 index 0000000..0497ca3 --- /dev/null +++ b/src/libcatnip/index_map.cpp @@ -0,0 +1,43 @@ + + +#include "index_map.hpp" + +#include "atom.hpp" +#include "atom_group.hpp" + +namespace catnip { + + IndexMap::IndexMap(AtomGroupContainer atom_groups){ + std::vector group_indices = atom_groups.getGroups(GroupType::Component); + int complex_ind = atom_groups.getGroups(GroupType::Complex).at(0); + AtomGroup complex_group = atom_groups.getGroup(complex_ind); + int sys_ind = 0; + for ( int & group_ind : group_indices) { + AtomGroup component_group = atom_groups.getGroup(group_ind); + for( std::shared_ptr & atom : component_group){ + int atom_ind = complex_group.findIndex(atom); + int num_basis = complex_group.at(atom_ind)->getBasisFuncCount(); + for ( int ind_temp = 0; ind_temp IndexMap::findLocation(int row){ + std::pair group_row; + for( std::pair> group_rows : row_col_init){ + int row_ind = 0; + for ( int row_ : group_rows.second ){ + if (row_ == row){ + return std::pair(group_rows.first, row_ind); + } + ++row_ind; + } + } + } + +} // namespace catnip diff --git a/src/libcatnip/index_map.hpp b/src/libcatnip/index_map.hpp new file mode 100644 index 0000000..c1df94f --- /dev/null +++ b/src/libcatnip/index_map.hpp @@ -0,0 +1,28 @@ + + +#include "transfer_complex.hpp" + +#include "atom.hpp" +#include "atom_group.hpp" + +namespace catnip { + + class IndexMap { + public: + + IndexMap(AtomGroupContainer atom_groups); + // The component rows and colums in their current locations in + // in the full system matrix of the complex + std::map> row_col_init; + + // Map indicate where the rows and cols should go in the final state + // Each int in the vector represents the locatin in the full system matrix + std::map> row_col_final; + + // Searches the init row for the provided row and returns the group it is + // in as well as its current index + std::pair findLocation(int row); + }; + + +} // namespace catnip diff --git a/src/libcatnip/organizer.hpp b/src/libcatnip/organizer.hpp new file mode 100644 index 0000000..fa992d5 --- /dev/null +++ b/src/libcatnip/organizer.hpp @@ -0,0 +1,29 @@ +#pragma once +#ifndef _CATNIP_ORGANIZER_HPP +#define _CATNIP_ORGANIZER_HPP + + +#include +#include +#include +#include +#include +#include + +//#include "matrix.hpp" +#include + +namespace catnip { + + /** + * @brief The purpose of this class is to be able to organize basis functions + * with the correct atoms in a molecule + */ + class Organizer { + + + public: + void unscramble(AtomGroupContainer cont); + }; +} // namespace catnip +#endif // _CATNIP_ORGANIZER_HPP diff --git a/src/libcatnip/swap_engine.cpp b/src/libcatnip/swap_engine.cpp new file mode 100644 index 0000000..a673b17 --- /dev/null +++ b/src/libcatnip/swap_engine.cpp @@ -0,0 +1,84 @@ + + +#include "swap_engine.hpp" + +#include "atom.hpp" +#include "atom_group.hpp" + +namespace catnip { + + // Swaps rows columns and keeps up with how future swaps should be updated + class SwapEngine { + private: + size_t size_; + IndexMap ind_map_; + Eigen::MatrixXd scratch_; + + public: + SwapEngine(IndexMap ind_map, size_t size) : + size_(size), ind_map_(ind_map) { + scratch_ = Eigen::MatrixXd::Zero(size, 1); + + + // Already have enough information to calculate the correct swap order + // Note the order of swaps is important. + for ( std::pair> group_row : ind_map_.row_col_init ){ + int group_ind = group_row.first; + for ( int row : group_row.second ) { + int final_row = ind_map_.row_col_final[group_ind].at(row); + std::pair swap(row,final_row); + // Now we need to update index map, the row located at the final + // position has now been moved + auto group_and_row_ind = ind_map_.findLocation(final_row); + + // Final row location needs to be pointed to the starting row + ind_map_.row_col_init[group_and_row_ind.first].at(group_and_row_ind.second) = row; + } + } + }; + + + // This method of swapping was chosen to keep the memory footprint + // reasonable. + // Will correctly sort the rows and columns of the matrix + void arrange(Eigen::MatrixXd & mat) { + + // Check that matrix is square + if( mat.rows() != mat.cols() ) { + throw std::runtime_error("Can only arrange square matrices"); + } + if( mat.rows() != size_ ) { + throw std::runtime_error("Index map has different number of basis functions to matrix"); + } + + for ( std::pair> group_row : ind_map_.row_col_init ){ + int group_ind = group_row.first; + for ( int row : group_row.second ) { + int final_row = ind_map_.row_col_final[group_ind].at(row); + if(final_row == row ) continue; + // Copy the data at the final row into the scratch space + scratch_.col(0) = mat.row(final_row); + // Copy the data from the initial row into the final row + mat.row(final_row) = mat.row(row); + // Copy the data from the temporary row into the initial row + mat.row(row) = scratch_.col(0); + } + } + + // Repeat for columns + for ( std::pair> group_col : ind_map_.row_col_init ){ + int group_ind = group_col.first; + for ( int col : group_col.second ) { + int final_col = ind_map_.row_col_final[group_ind].at(col); + if(final_col == col ) continue; + // Copy the data at the final row into the scratch space + scratch_.col(0) = mat.col(final_col); + // Copy the data from the initial row into the final row + mat.col(final_col) = mat.col(col); + // Copy the data from the temporary row into the initial row + mat.col(col) = scratch_.col(0); + } + } + } + }; +} // namespace catnip diff --git a/src/libcatnip/transfer_complex.cpp b/src/libcatnip/transfer_complex.cpp new file mode 100644 index 0000000..7575b7f --- /dev/null +++ b/src/libcatnip/transfer_complex.cpp @@ -0,0 +1,1155 @@ + + +#include "transfer_complex.hpp" + +#include "atom.hpp" +#include "atom_group.hpp" +//#include "constants.hpp" +//#include "io/io.hpp" +//#include "log.hpp" +//#include "matrix.hpp" +// +//#include +//#include +// +//#include +//#include +//#include +//#include +//#include +//#include +//#include // For accumulate +//#include +//#include +//#include +//#include +// + +namespace catnip { + + class IndexMap { + public: + + IndexMap(AtomGroupContainer atom_groups){ + std::vector group_indices = atom_groups.getGroups(GroupType::Component); + int complex_ind = atom_groups.getGroups(GroupType::Complex).at(0); + AtomGroup complex_group = atom_groups.getGroup(complex_ind); + int sys_ind = 0; + for ( int & group_ind : group_indices) { + AtomGroup component_group = atom_groups.getGroup(group_ind); + for( std::shared_ptr & atom : component_group){ + int atom_ind = complex_group.findIndex(atom); + int num_basis = complex_group.at(atom_ind)->getBasisFuncCount(); + for ( int ind_temp = 0; ind_temp> row_col_init; + + // Map indicate where the rows and cols should go in the final state + // Each int in the vector represents the locatin in the full system matrix + std::map> row_col_final; + + // Searches the init row for the provided row and returns the group it is + // in as well as its current index + std::pair findLocation(int row){ + std::pair group_row; + for( std::pair> group_rows : row_col_init){ + int row_ind = 0; + for ( int row_ : group_rows.second ){ + if (row_ == row){ + return std::pair(group_rows.first, row_ind); + } + ++row_ind; + } + } + } + }; + + // Swaps rows columns and keeps up with how future swaps should be updated + class SwapEngine { + private: + size_t size_; + IndexMap ind_map_; + Eigen::MatrixXd scratch_; + + public: + SwapEngine(IndexMap ind_map, size_t size) : + size_(size), ind_map_(ind_map) { + scratch_ = Eigen::MatrixXd::Zero(size, 1); + + + // Already have enough information to calculate the correct swap order + // Note the order of swaps is important. + for ( std::pair> group_row : ind_map_.row_col_init ){ + int group_ind = group_row.first; + for ( int row : group_row.second ) { + int final_row = ind_map_.row_col_final[group_ind].at(row); + std::pair swap(row,final_row); + // Now we need to update index map, the row located at the final + // position has now been moved + auto group_and_row_ind = ind_map_.findLocation(final_row); + + // Final row location needs to be pointed to the starting row + ind_map_.row_col_init[group_and_row_ind.first].at(group_and_row_ind.second) = row; + } + } + }; + + + // This method of swapping was chosen to keep the memory footprint + // reasonable. + // Will correctly sort the rows and columns of the matrix + void arrange(Eigen::MatrixXd & mat) { + + // Check that matrix is square + if( mat.rows() != mat.cols() ) { + throw std::runtime_error("Can only arrange square matrices"); + } + if( mat.rows() != size_ ) { + throw std::runtime_error("Index map has different number of basis functions to matrix"); + } + + for ( std::pair> group_row : ind_map_.row_col_init ){ + int group_ind = group_row.first; + for ( int row : group_row.second ) { + int final_row = ind_map_.row_col_final[group_ind].at(row); + if(final_row == row ) continue; + // Copy the data at the final row into the scratch space + scratch_.col(0) = mat.row(final_row); + // Copy the data from the initial row into the final row + mat.row(final_row) = mat.row(row); + // Copy the data from the temporary row into the initial row + mat.row(row) = scratch_.col(0); + } + } + + // Repeat for columns + for ( std::pair> group_col : ind_map_.row_col_init ){ + int group_ind = group_col.first; + for ( int col : group_col.second ) { + int final_col = ind_map_.row_col_final[group_ind].at(col); + if(final_col == col ) continue; + // Copy the data at the final row into the scratch space + scratch_.col(0) = mat.col(final_col); + // Copy the data from the initial row into the final row + mat.col(final_col) = mat.col(col); + // Copy the data from the temporary row into the initial row + mat.col(col) = scratch_.col(0); + } + } + } + }; + + void TransferComplex::unscramble(AtomGroupContainer atom_groups) { + // We should figure out how all the rows and columns should be + // rearranged before moving any of the coefficients in the matrix + IndexMap ind_map = IndexMap(atom_groups); + + size_t total_basis = atom_groups.getTotalBasisFunctionCount(GroupType::Component); + size_t total_basis_comp = atom_groups.getTotalBasisFunctionCount(GroupType::Complex); + + // If the total number of basis functions in the components is greater than + // the total number of basis functions in the complex, throw an error + if(total_basis != total_basis_comp) { + throw std::runtime_error("Sum of basis functions in components does not equal the number of basis functions in the complex"); + } + + auto swap_eng = SwapEngine(ind_map,total_basis); + + swap_eng.arrange(*(params_->complex_coefs)); + swap_eng.arrange(*(params_->S_AO)); + + } + + void TransferComplex::calcJ() {}; +// using namespace std; +/* +// Essentially calculates the transfer integral +void TransferComplex::calculate_transfer_integral_() { + + auto dimension = mat_1_Coef.cols()+mat_2_Coef.cols(); + Eigen::MatrixXd zetaA(mat_1_Coef.rows(),dimension); + Eigen::MatrixXd zetaB(mat_2_Coef.rows(),dimension); + if (counterPoise_) { + + LOG("Creating zeta matrices from coefficients assuming counterpoise", 2); + zetaA = mat_1_Coef; + zetaB = mat_2_Coef; + } else { + LOG("Creating zeta matrices from coefficients", 2); + zetaA << mat_1_Coef, Eigen::MatrixXd::Zero(mat_1_Coef.rows(),mat_2_Coef.cols()); + zetaB << Eigen::MatrixXd::Zero(mat_2_Coef.rows(),mat_1_Coef.cols()), mat_2_Coef; + } + + LOG("Creating gamma and beta matrices", 2); + Eigen::MatrixXd gammaA = zetaA * mat_S * mat_P_Coef.transpose(); + Eigen::MatrixXd gammaB = zetaB * mat_S * mat_P_Coef.transpose(); + + assert(gammaA.cols() == gammaB.cols() && "Column count between gamma A and B must be consistent"); + Eigen::MatrixXd gamma(gammaA.rows()+gammaB.rows(),gammaA.cols()); + gamma << gammaA, gammaB; + + LOG("Calculating S_MO", 2); + S_MO.resize(dimension,dimension); + S_MO = gamma * gamma.transpose(); + + Eigen::SelfAdjointEigenSolver eigen_solver(S_MO); + Eigen::MatrixXd S_MO_inv_sqrt = eigen_solver.operatorInverseSqrt(); + + Hamiltonian.resize(mat_S.rows(),mat_S.cols()); + Hamiltonian = gamma * vec_P_OE.asDiagonal() * gamma.transpose(); + + Hamiltonian_eff = S_MO_inv_sqrt * Hamiltonian * S_MO_inv_sqrt; +} + +void TransferComplex::printTransferIntegral( + const map &orbitaltype, + const map &orbnum) const { + + string HOMO_OR_LUMO_A = orbitaltype.at("mon1"); + int MO_A = orbnum.at("mon1"); + if (HOMO_OR_LUMO_A.compare("HOMO") == 0) { + if (MO_A > 0) { + throw invalid_argument( + "Having specified HOMO the MO_A" + " value is in reference to the HOMO and must be a negative number"); + } + // Number of orbitals that are choices + if (MO_A <= (-1 * HOMO_A_)) { + string err = "You are trying to access HOMO" + to_string(MO_A) + + " but there " + "are only " + + to_string(HOMO_A_) + " HOMO orbitals"; + throw invalid_argument(err); + } + } else if (HOMO_OR_LUMO_A.compare("LUMO") == 0) { + if (MO_A < 0) { + throw invalid_argument( + "Having specified LUMO the MO_A" + " value is in reference to the LUMO and must be a positive number"); + } + int allowed_LUMO = mat_1_Coef.rows() - HOMO_A_; + if (MO_A >= allowed_LUMO) { + string err = "You are trying to access LUMO+" + to_string(MO_A) + + " but there " + "are only " + + to_string(allowed_LUMO) + " LUMO orbitals"; + throw invalid_argument(err); + } + } else { + throw invalid_argument("orbitals must be referred to as HOMO or LUMO"); + } + + string HOMO_OR_LUMO_B = orbitaltype.at("mon2"); + int MO_B = orbnum.at("mon2"); + if (HOMO_OR_LUMO_B.compare("HOMO") == 0) { + if (MO_B > 0) { + throw invalid_argument( + "Having specified HOMO the MO_B" + " value is in reference to the HOMO and must be a negative number"); + } + if (MO_B <= (-1 * HOMO_B_)) { + string err = "You are trying to access HOMO" + to_string(MO_B) + + " but there " + "are only " + + to_string(HOMO_B_) + " HOMO orbitals"; + throw invalid_argument(err); + } + } else if (HOMO_OR_LUMO_B.compare("LUMO") == 0) { + if (MO_B < 0) { + throw invalid_argument( + "Having specified LUMO the MO_B" + " value is in reference to the LUMO and must be a positive number"); + } + int allowed_LUMO = mat_2_Coef.rows() - HOMO_B_; + if (MO_B >= allowed_LUMO) { + string err = "You are trying to access LUMO+" + to_string(MO_B) + + " but there " + "are only " + + to_string(allowed_LUMO) + " LUMO orbitals"; + throw invalid_argument(err); + } + } else { + throw invalid_argument("orbitals must be referred to as HOMO or LUMO"); + } + + printTransferIntegral_( + pair(HOMO_OR_LUMO_A,MO_A), + pair(HOMO_OR_LUMO_B,MO_B)); +} +// Find the transfer integral between two orbitals. +// pair string - Either HOMO or LUMO +// int - is the orbital number HOMO-3 LUMO+5 +void TransferComplex::printTransferIntegral_( + const pair& orbital1, + const pair& orbital2) const { + + int offset = mat_1_Coef.rows(); + int orbital1_num = 0; + int orbital2_num = 0; + if(orbital1.first.compare("HOMO")==0){ + assert(orbitalValid_(orbital1)==true); + orbital1_num = orbital1.second + HOMO_A_-1; + }else if(orbital1.first.compare("LUMO")==0){ + assert(orbitalValid_(orbital1)==true); + orbital1_num = orbital1.second + HOMO_A_; + } + if(orbital2.first.compare("HOMO")==0){ + assert(orbitalValid_(orbital2)==true); + orbital2_num = offset+orbital2.second + HOMO_B_-1; + }else if(orbital2.first.compare("LUMO")==0){ + assert(orbitalValid_(orbital2)==true); + orbital2_num = offset+orbital2.second + HOMO_B_; + } + double J_ab = Hamiltonian(orbital1_num,orbital2_num); + double e_a = Hamiltonian(orbital1_num,orbital1_num); + double e_b = Hamiltonian(orbital2_num,orbital2_num); + double S_ab = S_MO(orbital1_num,orbital2_num); + + cout << "\nPre-Orthonormalization" << endl; + cout << "J_ab " << J_ab * hartreeToeV << " eV\n"; + cout << "e_a " << e_a * hartreeToeV << " eV\n"; + cout << "e_b " << e_b * hartreeToeV << " eV\n"; + cout << "S_ab " << S_ab << "\n" << endl; + + cout << "Single Orbital DIPRO" << endl; + double J_ab_single = (J_ab - 0.5*(e_a+e_b)*S_ab)/(1-pow(S_ab,2.0)); + double e_a_single = 0.5*((e_a+e_b)-2*J_ab*S_ab+(e_a-e_b)*pow(1-pow(S_ab,2.0),0.5))/(1-pow(S_ab,2.0)); + double e_b_single = 0.5*((e_a+e_b)-2*J_ab*S_ab-(e_a-e_b)*pow(1-pow(S_ab,2.0),0.5))/(1-pow(S_ab,2.0)); + cout << "J_ab_eff_single " << J_ab_single * hartreeToeV << " eV\n"; + cout << "e_a_eff_single " << e_a_single * hartreeToeV << " eV\n"; + cout << "e_b_eff_single " << e_b_single * hartreeToeV << " eV\n" << endl; + + cout << "All Orbital DIPRO" << endl; + double J_eff = Hamiltonian_eff(orbital1_num,orbital2_num); + double e_a_eff = Hamiltonian_eff(orbital1_num,orbital1_num); + double e_b_eff = Hamiltonian_eff(orbital2_num,orbital2_num); + cout << "J_ab_eff_all " << J_eff * hartreeToeV << " eV\n"; + cout << "e_a_eff_all " << e_a_eff * hartreeToeV << " eV\n"; + cout << "e_b_eff_all " << e_b_eff * hartreeToeV << " eV\n" << endl; + +} + +void TransferComplex::printAll() const { + + int column_width = 14; + cout << "Effective Hamiltonian" << endl; + + int col_offset = mat_1_Coef.cols(); + int start_col = 0; + int end_col = 5; + while(start_colHamiltonian.cols()){ + end_col = Hamiltonian.cols(); + } + for(int orbital_num = start_col;orbital_num=col_offset && orbital_num<(HOMO_B_+col_offset))){ + if(orbital_num=HOMO_A_ && orbital_num(col_offset+HOMO_B_)){ + if(orbital_num=col_offset && orbital_num<(HOMO_B_+col_offset))){ + if(orbital_num & orbital) const{ + int HOMO_AB = HOMO_A_+HOMO_B_; + int LUMO_AB = HOMO_AB+1; + if(orbital.first.compare("HOMO")==0){ + if(orbital.second>0){ + cerr << "HOMO orbital number is not negative or 0" << endl; + return false; + } + if(orbital.second>HOMO_AB){ + cerr << "HOMO orbital does not exst " << orbital.second << " "<< HOMO_AB << endl; + return false; + } + }else if(orbital.first.compare("LUMO")==0){ + if(orbital.second<0){ + cerr << "LUMO orbital number is not positive or 0" << endl; return false; + } + if(orbital.second>(Hamiltonian_eff.rows()-LUMO_AB)){ + cerr << "LUMO orbital does not exst " << orbital.second << endl; + return false; + } + } + return true; +} +// Split a matrix up into a list of smaller matrices. The matrix can be split +// in columns or in rows. The number of rows/cols in each smaller matrix is +// held in the vector subMatrixDimension +// +// E.g. Given the matrix +// +// 1 2 3 +// 3 4 5 +// +// subMatrixDimension = { 2 1 } +// +// And I split by cols +// +// list contain +// +// matrix 1 matrix 2 +// 1 2 3 +// 3 4 5 +// +list splitMatrixIntoList( + const vector &subMatrixDimension, + const Eigen::MatrixXd mat, + const string &ColRowSplit) { + + list list_matrix; + int num_sub_matrices = subMatrixDimension.size(); + if (ColRowSplit.compare("Columns") == 0) { + int col = 0; + for (int i = 0; i < num_sub_matrices; ++i) { + Eigen::MatrixXd mat_new(mat.rows(), subMatrixDimension.at(i)); + for (auto k = 0; k < mat.rows(); ++k) { + for (auto j = 0; j < subMatrixDimension.at(i); ++j) { + mat_new(k,j) = mat(k, col + j); + } + } + col += subMatrixDimension.at(i); + list_matrix.push_back(mat_new); + } + } else if (ColRowSplit.compare("Rows") == 0) { + int row = 0; + for (auto i = 0; i < num_sub_matrices; ++i) { + Eigen::MatrixXd mat_new(subMatrixDimension.at(i), mat.cols()); + for (auto k = 0; k < mat.cols(); ++k) { + for (auto j = 0; j < subMatrixDimension.at(i); ++j) { + mat_new(j,k) = mat(row + j, k); + } + } + row += subMatrixDimension.at(i); + list_matrix.push_back(mat_new); + } + } else { + throw invalid_argument("Unrecognized string tag provided"); + } + return list_matrix; +} + +list splitCoefsUpByAtoms(const vector & basisFuncP, Eigen::MatrixXd Coefs, + const string & ColRow) { + return splitMatrixIntoList(basisFuncP, Coefs, ColRow); +} + +// The purpose of this function is to ensure that swapping occurs correctly +// The following example explains in more detail what this is meant to do +// Now if we have a matrix in a specific state and want to swap the rows +// we can not simply list all the rows that need to be changed and then make +// the changes. +// +// We have to figure out how to swap rows sequentially without ending up with +// the wrong result. +// +// For instance say we have a matrix +// index 1 | row 1 +// index 2 | row 2 +// index 3 | row 3 +// index 4 | row 4 +// +// where: +// Row 1 needs to be at index 3 +// Row 4 needs to be at index 1 +// Row 2 needs to be at index 2 +// Row 3 needs to be at index 4 +// +// If we simply looked at our first instance of the matrix shown above +// and came up with the following swaps +// Swap row 1 with index 3 +// Swap row 4 with index 1 +// Swap row 2 with index 2 +// Swap row 3 with index 4 +// +// First swap +// index 1 row3 +// index 2 row2 +// index 3 row1 +// index 4 row4 +// +// Second swap +// index 1 row4 +// index 2 row2 +// index 3 row1 +// index 4 row3 +// +// Third swap does nothing +// Fourth swap +// index 1 row4 +// index 2 row2 +// index 3 row3 +// index 4 row1 +// +// When what we really wanted was +// index 1 row4 +// index 2 row2 +// index 3 row1 +// index 4 row3 +// +// Notice the row3 and row1 are in the wrong place +// The instructions should be rewritten +// Swap row 1 with index 3 +// Swap row 4 with index 3 +// Swap row 2 with index 2 - no swap +// Swap row 3 with index 3 - no swap +// +void refreshSwapOrder(vector> &monBmatch, + vector> &monAmatch) { + + // Because matrix B appears at the top of our full matrix e.g. + // + // [ B ] + // [ A ] + // + // When sorting out the swap order we need to cycle through elements in B and + // see where they appear in both the B and A matrix + // + // B -> [ B ] + // B -> [ A ] + // + for (auto pr_ptr = monBmatch.begin(); pr_ptr != monBmatch.end(); ++pr_ptr) { + auto pr = *pr_ptr; + + int row1was = pr.first; + int row1is = pr.second; + auto pr_ptr_temp = pr_ptr; + pr_ptr_temp++; + while (pr_ptr_temp != monBmatch.end()) { + pr_ptr_temp = find_if( + pr_ptr_temp, monBmatch.end(), + [row1was](const pair &p) { return row1was == p.second; }); + if (pr_ptr_temp != monBmatch.end()) { + pr_ptr_temp->second = row1is; + } + } + pr_ptr_temp = monAmatch.begin(); + while (pr_ptr_temp != monAmatch.end()) { + pr_ptr_temp = find_if( + pr_ptr_temp, monAmatch.end(), + [row1was](const pair &p) { return row1was == p.second; }); + if (pr_ptr_temp != monAmatch.end()) { + pr_ptr_temp->second = row1is; + } + } + } + // Here we have already looked at the rows in B and they are up to date but + // we still need to make sure the rows in A are swapped in the appropriate + // order + // + // [ B ] + // A -> [ A ] + // + for (auto pr_ptr = monAmatch.begin(); pr_ptr != monAmatch.end(); ++pr_ptr) { + auto pr = *pr_ptr; + int row1was = pr.first; + int row1is = pr.second; + if (row1was != row1is) { + auto pr_ptr_temp = pr_ptr; + pr_ptr_temp++; + while (pr_ptr_temp != monAmatch.end()) { + pr_ptr_temp = find_if( + pr_ptr_temp, monAmatch.end(), + [row1was](const pair &p) { return row1was == p.second; }); + if (pr_ptr_temp != monAmatch.end()) { + pr_ptr_temp->second = row1is; + } + } + } + } + return; +} + +void refreshSwapOrder(vector> &monAmatch) { + + for (auto pr_ptr = monAmatch.begin(); pr_ptr != monAmatch.end(); ++pr_ptr) { + auto pr = *pr_ptr; + + int row1was = pr.first; + int row1is = pr.second; + auto pr_ptr_temp = pr_ptr; + pr_ptr_temp++; + while (pr_ptr_temp != monAmatch.end()) { + pr_ptr_temp = find_if( + pr_ptr_temp, monAmatch.end(), + [row1was](const pair &p) { return row1was == p.second; }); + if (pr_ptr_temp != monAmatch.end()) { + pr_ptr_temp->second = row1is; + } + } + } + return; +} + +// To replace both refreshSwapOrder and updateSwapLists +// instead of figuring out a proper order for swapping we will simply start +// with a new link list of the same size and place the coefficents in that +// new list +Eigen::MatrixXd createSortedCoefMatrix(vector> & mon_match_ind, list & atom_mat_coefs){ + + // Actually lets use a vector of pointers to the matrices that are in the list + vector mat_ptrs; + // Error checking + if(atom_mat_coefs.size()==0){ + throw std::runtime_error("ERROR cannot create sorted coef matrix, there are atomically partitioned matrices to build the full sorted coef matrix from."); + } + + int cols = atom_mat_coefs.front().cols(); + for ( list::iterator coef_ptr = atom_mat_coefs.begin(); + coef_ptr != atom_mat_coefs.end(); + ++coef_ptr ){ + if(coef_ptr->cols()!=cols){ + throw std::runtime_error("ERROR cannot created sorted coef matrix from atomically partitioned matrices with varying number of columns."); + } + } + // End of error checking + + // Count the total number of rows in each atomically partitioned coef matrix + vector rows_per_mat; + for ( list::iterator coef_ptr = atom_mat_coefs.begin(); + coef_ptr != atom_mat_coefs.end(); + ++coef_ptr ){ + rows_per_mat.push_back(coef_ptr->rows()); + } + + int initial_value = 0; + int total_rows = std::accumulate(rows_per_mat.begin(),rows_per_mat.end(), initial_value); + + // Determine the offset of each row to each index + std::map row_to_index_offset; + int offset = 0; + for ( std::pair & row_ind : mon_match_ind ){ + row_to_index_offset.at(row_ind.first) = offset; + offset+= rows_per_mat.at(row_ind.second); + } + + Eigen::MatrixXd sorted_atom_mat_coefs + + + +} +// The above function determines the appropriate sequence of swaps this function +// then actually implements the swaps by exchanging the matrices in the list. +void updateSwapLists(vector> &monBmatch, + vector> &monAmatch, + list &p_atom_mat_coef) { + + for (auto p : monBmatch) { + if (p.first != p.second) { + auto it = p_atom_mat_coef.begin(); + Eigen::MatrixXd temp = *(next(it, p.first)); + *(next(it, p.first)) = *(next(it, p.second)); + *(next(it, p.second)) = temp; + } + } + for (auto p : monAmatch) { + if (p.first != p.second) { + auto it = p_atom_mat_coef.begin(); + Eigen::MatrixXd temp = *(next(it, p.first)); + *(next(it, p.first)) = *(next(it, p.second)); + *(next(it, p.second)) = temp; + } + } + return; +} +void updateSwapLists(vector> &monAmatch, + list &atom_mat_coef) { + + for (auto p : monAmatch) { + if (p.first != p.second) { + auto it = atom_mat_coef.begin(); + Eigen::MatrixXd & temp = *(next(it, p.first)); + *(next(it, p.first)) = *(next(it, p.second)); + *(next(it, p.second)) = temp; + } + } + return; +} + +Eigen::MatrixXd mergeListOfMatrices(list &matrix_list, const int rows, + const int cols, const string &ColRowMerge) { + + Eigen::MatrixXd full_matrix(rows, cols); + if (ColRowMerge.compare("Columns") == 0) { + int col = 0; + for (auto it = matrix_list.begin(); it != matrix_list.end(); ++it) { + Eigen::MatrixXd mat = *it; + int row = 0; + if (col > cols) + throw runtime_error("Your new matrix is not large enough"); + for (auto i = 0; i < mat.rows(); ++i) { + if (row > rows) + throw runtime_error("Your new matrix is not large enough"); + for (auto j = 0; j < mat.cols(); ++j) { + full_matrix(row,j+col) = mat(i, j); + } + ++row; + } + col += mat.cols(); + } + } else if (ColRowMerge.compare("Rows") == 0) { + int row = 0; + for (auto it = matrix_list.begin(); it != matrix_list.end(); ++it) { + Eigen::MatrixXd mat = *it; + int col = 0; + if (row > rows) + throw runtime_error("Your new matrix is not large enough"); + for (auto j = 0; j < mat.cols(); ++j) { + if (col > cols) + throw runtime_error("Your new matrix is not large enough"); + for (auto i = 0; i < mat.rows(); ++i) { + full_matrix(row + i, col) = mat(i, j); + } + ++col; + } + row += mat.rows(); + } + } else { + throw invalid_argument("Unrecognized merge type for list of matrices"); + } + return full_matrix; +} + +// This function +Eigen::MatrixXd createNewMatrix(list &p_atom_mat_coef, int rows, int cols, + const string &ColRow) { + return mergeListOfMatrices(p_atom_mat_coef, rows, cols, ColRow); +} + +// unscramble the coefficients +//Eigen::MatrixXd unscramble_Coef( +// const std::vector &matchDimerA, +// const std::vector &matchDimerB, +// const std::vector &basisFuncP, +// const Eigen::MatrixXd & dimerCoef) { +// +// // Let's reduce the complexity of the problem by instead of working +// // with the basis functions lets just work with the atoms. We can do +// // this by treating all the basis functions associated with a single +// // atom as a block. +// +// list p_atom_mat_coef = +// splitCoefsUpByAtoms(basisFuncP, dimerCoef, "Columns"); +// +// // Place all of monomer A atom basis functions on the left side of the +// // matrix and all of B monomer atom basis functions on the right side +// // of the dimer matrix +// // First int is the col in the dimer the atom should be at +// // Second int is the col in the dimer the atom is presently at +// +// vector> monAmatch; +// for (unsigned i = 0; i < matchDimerA.size(); ++i) { +// pair pr(i, matchDimerA.at(i)); +// monAmatch.push_back(pr); +// } +// vector> monBmatch; +// for (unsigned i = 0; i < matchDimerB.size(); ++i) { +// pair pr(i + monAmatch.size(), matchDimerB.at(i)); +// monBmatch.push_back(pr); +// } +// +// refreshSwapOrder(monBmatch, monAmatch); +// updateSwapLists(monBmatch, monAmatch, p_atom_mat_coef); +// +// Eigen::MatrixXd dimerCoef_new = createNewMatrix( +// p_atom_mat_coef, dimerCoef.rows(), dimerCoef.cols(), "Columns"); +// +// return dimerCoef_new; +//} +// +//// unscramble the coefficients +//Eigen::MatrixXd unscramble_Coef( +// const std::vector &matchDimerB, +// const std::vector &basisFuncB, +// const Eigen::MatrixXd &Coef) { +// +// // Let's reduce the complexity of the problem by instead of working +// // with the basis functions lets just work with the atoms. We can do +// // this by treating all the basis functions associated with a single +// // atom as a block. +// +// list atom_mat_coef = +// splitCoefsUpByAtoms(basisFuncB, Coef, "Columns"); +// +// // Place all of monomer A atom basis functions on the left side of the +// // matrix and all of B monomer atom basis functions on the right side +// // of the matrix +// // First int is the col in the dimer the atom should be at +// // Second int is the col in the dimer the atom is presently at +// +// vector> monBmatch; +// for (unsigned i = 0; i < matchDimerB.size(); ++i) { +// pair pr(i, matchDimerB.at(i)); +// monBmatch.push_back(pr); +// } +// +// refreshSwapOrder(monBmatch); +// updateSwapLists(monBmatch, atom_mat_coef); +// Eigen::MatrixXd Coef_new = createNewMatrix(atom_mat_coef, Coef.rows(), +// Coef.cols(), "Columns"); +// return Coef_new; +//} + +Eigen::MatrixXd unscrambleCoef( + const std::vector> &match_mon_complex, + const std::vector &basis_functions_complex, + const Eigen::MatrixXd & complex_coefs) { + + // Let's reduce the complexity of the problem by instead of working + // with the basis functions lets just work with the atoms. We can do + // this by treating all the basis functions associated with a single + // atom as a block. + + list complex_coef_block = + splitCoefsUpByAtoms(basis_functions_complex, complex_coefs, "Columns"); + + // Place all of monomer A atom basis functions on the left side of the + // matrix and all of B monomer atom basis functions on the right side + // of the dimer matrix + // First int is the col in the dimer the atom should be at + // Second int is the col in the dimer the atom is presently at + +// vector> monBmatch; +// for (unsigned i = 0; i < matchDimerB.size(); ++i) { +// pair pr(i, matchDimerB.at(i)); +// monBmatch.push_back(pr); +// } + + vector>> mon_match_index; + unsigned new_index = 0; + for ( const vector & monomer_rows : match_mon_complex){ + vector> mon_matching_index_row; + for( const int & row_index : monomer_rows ){ + pair pr(new_index,row_index); + mon_matching_index_row.push_back(pr); + } + mon_match_index.push_back(mon_matching_index_row); + } + + //refreshSwapOrder(monBmatch); +// refreshSwapOrder(mon_match_index); + // updateSwapLists(monBmatch, atom_mat_coef); + Eigen::MatrixXd Coef_new = createNewMatrix(atom_mat_coef, Coef.rows(), + Coef.cols(), "Columns"); + return Coef_new; + + +} +// Similar to the above function but we will be moving both the rows +// and columns +Eigen::MatrixXd unscramble_S( + const std::vector &matchDimerA, + const std::vector &matchDimerB, + const std::vector &basisFuncP, + Eigen::MatrixXd S) { + + Eigen::MatrixXd S_new(S.rows(),S.cols()); + { + list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Columns"); + vector> monAmatch; + for (unsigned i = 0; i < matchDimerA.size(); ++i) { + pair pr(i, matchDimerA.at(i)); + monAmatch.push_back(pr); + } + vector> monBmatch; + for (unsigned i = 0; i < matchDimerB.size(); ++i) { + pair pr(i + monAmatch.size(), matchDimerB.at(i)); + monBmatch.push_back(pr); + } + + refreshSwapOrder(monBmatch, monAmatch); + updateSwapLists(monBmatch, monAmatch, p_atom_mat_S); + S_new = + createNewMatrix(p_atom_mat_S, S.rows(), S.cols(), "Columns"); + } + + S = S_new; + + { + list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Rows"); + + vector> monAmatch; + for (unsigned i = 0; i < matchDimerA.size(); ++i) { + pair pr(i, matchDimerA.at(i)); + monAmatch.push_back(pr); + } + vector> monBmatch; + for (unsigned i = 0; i < matchDimerB.size(); ++i) { + pair pr(i + monAmatch.size(), matchDimerB.at(i)); + monBmatch.push_back(pr); + } + + refreshSwapOrder(monBmatch, monAmatch); + updateSwapLists(monBmatch, monAmatch, p_atom_mat_S); + S_new = createNewMatrix(p_atom_mat_S, S.rows(), S.cols(), "Rows"); + } + + // Return the correctly swapped dimerCoef + return S_new; +} + +// Same as the above function but here we are assuming counterpoise correction +// is being used and thus we do not need to match with both monomer A and +// monomer B but only need to match with A. +Eigen::MatrixXd unscramble_S( + const std::vector &matchDimerA, + const std::vector &basisFuncP, + Eigen::MatrixXd S) { + + Eigen::MatrixXd S_new(S.rows(),S.cols()); + { + list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Columns"); + + vector> monAmatch; + for (unsigned i = 0; i < matchDimerA.size(); ++i) { + pair pr(i, matchDimerA.at(i)); + monAmatch.push_back(pr); + } + refreshSwapOrder(monAmatch); + updateSwapLists(monAmatch, p_atom_mat_S); + S_new = + createNewMatrix(p_atom_mat_S, S.rows(), S.cols(), "Columns"); + } + + S = S_new; + + { + list p_atom_mat_S = splitCoefsUpByAtoms(basisFuncP, S, "Rows"); + + vector> monAmatch; + for (unsigned i = 0; i < matchDimerA.size(); ++i) { + pair pr(i, matchDimerA.at(i)); + monAmatch.push_back(pr); + } + + refreshSwapOrder(monAmatch); + updateSwapLists(monAmatch, p_atom_mat_S); + S_new = createNewMatrix(p_atom_mat_S, S.rows(), S.cols(), "Rows"); + } + + // Return the correctly swapped dimerCoef + return S_new; +} + + +//TransferComplex::TransferComplex( +// const Eigen::MatrixXd & mat1Coef, +// const Eigen::MatrixXd & mat2Coef, +// const Eigen::MatrixXd & matPCoef, +// const int HOMO_A, +// const int HOMO_B, +// const Eigen::MatrixXd & matS, +// const Eigen::VectorXd & vecPOE, bool cp) { +// +TransferComplex::TransferComplex(const Parameters params) : params_(params) { + + unscrambled_ = false; +// counterPoise_ = cp; + // Consistency check + if (params_.S_AO.cols() != params_.mat_complex.cols()) { + throw invalid_argument( + "The overlap matrix must have the same number " + "of basis functions as the dimer"); + } + //if (cp) { + if (params_.counter_poise) { + int monomer_number = 1; + for ( const Eigen::MatrixXd & mat : params_.mat_monomers){ + if(params_.mat_complex.cols() != mat.cols()){ + throw invalid_argument( + "Counter poise correction requires that the" + " monomers have the same number of coefficients as the complex. " + "Your monomer " + std::to_string(monomer_number) +" does not"); + } + ++monomer_number; + } +// if (mat1Coef.cols() != matPCoef.cols()) { +// throw invalid_argument( +// "Counter poise correction requires that the" +// " monomers have the same number of coefficients as the dimer. " +// "Your monomer 1 does not"); +// } +// if (mat2Coef.cols() != matPCoef.cols()) { +// throw invalid_argument( +// "Counter poise correction requires that the" +// " monomers have the same number of coefficients as the dimer. " +// "Your monomer 2 does not"); +// } + } else { + /// If not counter poise the sum of the cols should equal the same number as is in the complex +// int total_cols = mat1Coef.cols() + mat2Coef.cols(); + int total_cols = 0; + for ( const Eigen::MatrixXd & mat : params_.mat_monomers){ + total_cols+=mat.cols(); + } + + //if (total_cols > matPCoef.cols()) { + if (total_cols > params_.mat_complex.cols()) { + throw invalid_argument( + "Counter poise has not been specified and the total number of " + "basis functions in your monomers is more than the number of basis " + "functions in your complex."); + }else if(total_cols < params_.complex_coefs.cols()){ + throw invalid_argument( + "Counter poise has not been specified and the total number of " + "basis functions in your monomers is less than the number of basis " + "functions in your complex."); + } + } +// +// mat_1_Coef.resize(mat1Coef.rows(),mat1Coef.cols()); +// mat_1_Coef = mat1Coef; +// mat_2_Coef.resize(mat2Coef.rows(),mat2Coef.cols()); +// mat_2_Coef = mat2Coef; +// mat_P_Coef.resize(matPCoef.rows(),matPCoef.cols()); +// mat_P_Coef = matPCoef; +// HOMO_A_ = HOMO_A; +// HOMO_B_ = HOMO_B; +// mat_S.resize(matS.rows(),matS.cols()); +// mat_S = matS; +// vec_P_OE.resize(vecPOE.size()); +// vec_P_OE = vecPOE; +} + +//void TransferComplex::unscramble(const Eigen::MatrixXd &coord_1_mat, +// const Eigen::MatrixXd &coord_2_mat, +// const Eigen::MatrixXd &coord_P_mat, +// const std::vector &basisP, +// const std::vector &basis2) { +// +void TransferComplex::unscramble(const vector &coord_monomers, + const Eigen::MatrixXd &coord_complex, + const std::vector &basis_complex, + const std::vector &basis2) { + unscrambled_ = true; + + const int sig_fig = 4; + + // If dealing with counter poise correction may also need to unscramble + // the basis functions of the monomers + if (counterPoise_) { + vector match_1_2 = matchCol(coord_1_mat,coord_2_mat, sig_fig); + + LOG("Counter Poise unscrambling matrix 2 with respect to matrix 1", 2); + Eigen::MatrixXd unscrambled_2_Coef = unscramble_Coef(match_1_2, basis2, mat_2_Coef); + + this->mat_2_Coef = unscrambled_2_Coef; + + vector match_1_P = matchCol(coord_1_mat,coord_P_mat, sig_fig); + + this->mat_P_Coef = unscramble_Coef(match_1_P, basisP, mat_P_Coef); + + this->mat_S = unscramble_S(match_1_P, basisP, mat_S); + + } else { + + vector> match_mon_complex; + for ( const Eigen::MatrixXd & coord_mon : coord_monomers){ + // Returns each of the rows in complex that match each of the monomers + match_mon_complex.push_back(matchCol(coord_mon,coord_complex, sig_fig)); + } + // Stores the rows in P that match 2 + //vector match_2_P = matchCol(coord_2_mat,coord_P_mat, sig_fig); + + LOG("Unscrambling dimer matrix with respect to matrix 1 and 2", 2); + //this->mat_P_Coef = + // unscramble_Coef(match_1_P, match_2_P, basisP, mat_P_Coef); + this->params_.complex_coefs = unscrambleCoef(match_mon_complex,basis_complex,complex_coefs); +// this->mat_S = unscramble_S(match_1_P, match_2_P, basisP, mat_S); + } + } +} + +void TransferComplex::calcJ() { + + if (unscrambled_ == false) { + cerr << "\nWARNING unable to automatically line up basis functions of" + " monomers with dimers, you better make sure they correctly" + " line up or run the calculations again with the correct " + "flag pop=full" + << endl; + } + + calculate_transfer_integral_(); +} +*/ +} // namespace catnip diff --git a/src/libcatnip/transfer_complex.hpp b/src/libcatnip/transfer_complex.hpp new file mode 100644 index 0000000..632725b --- /dev/null +++ b/src/libcatnip/transfer_complex.hpp @@ -0,0 +1,74 @@ +#pragma once +#ifndef _CATNIP_TRANSFER_COMPLEX_HPP +#define _CATNIP_TRANSFER_COMPLEX_HPP + +#include "atom_group_container.hpp" + +#include +#include +#include +#include +#include + +//#include "matrix.hpp" +#include + +namespace catnip { + +class TransferComplex { + + public: + + class Parameters { + public: + const std::vector> monomers_coefs; + const std::unique_ptr complex_coefs; + /// Location of each of the homo_orbitals in each of the monomers + const std::vector homo_orbitals; + //HOMO_A; + //const int HOMO_B; + /// Atomic Orbital overlap matrix + const std::unique_ptr S_AO; + const std::unique_ptr complex_orbital_energies; + /// Counter poise flag + bool counter_poise = false; + /// Calculate all couplings + bool calculate_all = false; + }; + + private: + + Parameters * params_; + + public: + + TransferComplex(Parameters * params) : params_(params) {}; + + void unscramble(AtomGroupContainer atom_groups); + + // Orbital type and a map of the corresponding number + // E.g. + // orbital type orbital number + // "mon1" "LUMO" "mon1" -3 + // "mon2" "HOMO" "mon2" 0 + // + // monomer1 LUMO-3 + // monomer2 HOMO + void calcJ(); + + /** + * \brief Print the transfer integral specified + **/ +// void printTransferIntegral( + // const std::map & orbital_type, + // const std::map & orbnum) const; + + /** + * \brief Print All info in matrix form + **/ + // void printAll() const; + +}; + +} // namespace catnip +#endif // _CATNIP_TRANSFER_COMPLEX_HPP diff --git a/src/tests/test_qc_functions.cpp b/src/tests/test_qc_functions.cpp index a5d6759..f4874d6 100644 --- a/src/tests/test_qc_functions.cpp +++ b/src/tests/test_qc_functions.cpp @@ -115,8 +115,11 @@ int main(void) { // atm1 atm1 atm2 atm2 cerr << "Before passing in" << endl; + cerr << "MatchA" << endl; for (auto it : matchA) cerr << it << endl; + cerr << "MatchB" << endl; for (auto it : matchB) cerr << it << endl; + cerr << "Basis Functions of Dimer" << endl; for (auto it : basisFuncDimer) cerr << it << endl; // If we correct the dimer coefficient matrix to line up with the // coefficients of the monomers it should look like this From ecade9011c2a1e47c2f0055cd1149e2cb92bc27d Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Sat, 11 Jul 2020 22:06:32 -0600 Subject: [PATCH 36/68] update --- src/libcatnip/transfer_complex.cpp | 145 +---------------------------- 1 file changed, 3 insertions(+), 142 deletions(-) diff --git a/src/libcatnip/transfer_complex.cpp b/src/libcatnip/transfer_complex.cpp index 7575b7f..907e042 100644 --- a/src/libcatnip/transfer_complex.cpp +++ b/src/libcatnip/transfer_complex.cpp @@ -1,153 +1,14 @@ - +// Local private includes #include "transfer_complex.hpp" #include "atom.hpp" #include "atom_group.hpp" -//#include "constants.hpp" -//#include "io/io.hpp" -//#include "log.hpp" -//#include "matrix.hpp" -// -//#include -//#include -// -//#include -//#include -//#include -//#include -//#include -//#include -//#include // For accumulate -//#include -//#include -//#include -//#include -// +#include "index_map.hpp" +#include "swap_engine.hpp" namespace catnip { - class IndexMap { - public: - - IndexMap(AtomGroupContainer atom_groups){ - std::vector group_indices = atom_groups.getGroups(GroupType::Component); - int complex_ind = atom_groups.getGroups(GroupType::Complex).at(0); - AtomGroup complex_group = atom_groups.getGroup(complex_ind); - int sys_ind = 0; - for ( int & group_ind : group_indices) { - AtomGroup component_group = atom_groups.getGroup(group_ind); - for( std::shared_ptr & atom : component_group){ - int atom_ind = complex_group.findIndex(atom); - int num_basis = complex_group.at(atom_ind)->getBasisFuncCount(); - for ( int ind_temp = 0; ind_temp> row_col_init; - - // Map indicate where the rows and cols should go in the final state - // Each int in the vector represents the locatin in the full system matrix - std::map> row_col_final; - - // Searches the init row for the provided row and returns the group it is - // in as well as its current index - std::pair findLocation(int row){ - std::pair group_row; - for( std::pair> group_rows : row_col_init){ - int row_ind = 0; - for ( int row_ : group_rows.second ){ - if (row_ == row){ - return std::pair(group_rows.first, row_ind); - } - ++row_ind; - } - } - } - }; - - // Swaps rows columns and keeps up with how future swaps should be updated - class SwapEngine { - private: - size_t size_; - IndexMap ind_map_; - Eigen::MatrixXd scratch_; - - public: - SwapEngine(IndexMap ind_map, size_t size) : - size_(size), ind_map_(ind_map) { - scratch_ = Eigen::MatrixXd::Zero(size, 1); - - - // Already have enough information to calculate the correct swap order - // Note the order of swaps is important. - for ( std::pair> group_row : ind_map_.row_col_init ){ - int group_ind = group_row.first; - for ( int row : group_row.second ) { - int final_row = ind_map_.row_col_final[group_ind].at(row); - std::pair swap(row,final_row); - // Now we need to update index map, the row located at the final - // position has now been moved - auto group_and_row_ind = ind_map_.findLocation(final_row); - - // Final row location needs to be pointed to the starting row - ind_map_.row_col_init[group_and_row_ind.first].at(group_and_row_ind.second) = row; - } - } - }; - - - // This method of swapping was chosen to keep the memory footprint - // reasonable. - // Will correctly sort the rows and columns of the matrix - void arrange(Eigen::MatrixXd & mat) { - - // Check that matrix is square - if( mat.rows() != mat.cols() ) { - throw std::runtime_error("Can only arrange square matrices"); - } - if( mat.rows() != size_ ) { - throw std::runtime_error("Index map has different number of basis functions to matrix"); - } - - for ( std::pair> group_row : ind_map_.row_col_init ){ - int group_ind = group_row.first; - for ( int row : group_row.second ) { - int final_row = ind_map_.row_col_final[group_ind].at(row); - if(final_row == row ) continue; - // Copy the data at the final row into the scratch space - scratch_.col(0) = mat.row(final_row); - // Copy the data from the initial row into the final row - mat.row(final_row) = mat.row(row); - // Copy the data from the temporary row into the initial row - mat.row(row) = scratch_.col(0); - } - } - - // Repeat for columns - for ( std::pair> group_col : ind_map_.row_col_init ){ - int group_ind = group_col.first; - for ( int col : group_col.second ) { - int final_col = ind_map_.row_col_final[group_ind].at(col); - if(final_col == col ) continue; - // Copy the data at the final row into the scratch space - scratch_.col(0) = mat.col(final_col); - // Copy the data from the initial row into the final row - mat.col(final_col) = mat.col(col); - // Copy the data from the temporary row into the initial row - mat.col(col) = scratch_.col(0); - } - } - } - }; - void TransferComplex::unscramble(AtomGroupContainer atom_groups) { // We should figure out how all the rows and columns should be // rearranged before moving any of the coefficients in the matrix From 7eb2ff594c18fd98ee25510b15f6a2612ec25132 Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Sat, 11 Jul 2020 23:57:58 -0600 Subject: [PATCH 37/68] Success compile --- CMakeLists.txt | 19 ++-- cmake/InstallGdown.cmake | 29 ++++++ src/CMakeLists.txt | 2 +- src/libcatnip/atom.hpp | 3 +- src/libcatnip/atom_group_container.cpp | 3 +- src/libcatnip/elements.hpp | 6 +- src/libcatnip/index_map.cpp | 2 +- src/libcatnip/index_map.hpp | 4 + src/libcatnip/size_type.hpp | 9 ++ src/libcatnip/swap_engine.cpp | 123 ++++++++++++------------- src/libcatnip/swap_engine.hpp | 29 ++++++ 11 files changed, 147 insertions(+), 82 deletions(-) create mode 100644 cmake/InstallGdown.cmake create mode 100644 src/libcatnip/size_type.hpp create mode 100644 src/libcatnip/swap_engine.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 93d229e..b987762 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,9 +4,10 @@ project (calc_J) ############################################################################## # Defining options ############################################################################## -option(DOWNLOAD_TUTORIAL_FILES "Download tutorial files" OFF) -option(ENABLE_INTEGRATION_TESTING "Enable integration tests" OFF) -option(ENABLE_UNIT_TESTING "Enable tests" OFF) +option(ENABLE_TESTS "Enable testing" Off) +option(DOWNLOAD_TUTORIAL_FILES "Download tutorial files" ${ENABLE_TESTS}) +option(ENABLE_INTEGRATION_TESTING "Enable integration tests" ${ENABLE_TESTS}) +option(ENABLE_UNIT_TESTING "Enable tests" ${ENABLE_TESTS}) option(ENABLE_PROFILING "Enable profiling" OFF) option(CODE_COVERAGE "Enable coverage reporting" OFF) @@ -22,7 +23,7 @@ set(calcJ_TITLE "\"CATNIP\"") set(calcJ_URL "\"https://github.com/JoshuaSBrown/QC_Tools\"" ) set(COVERAGE_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") set(COMMON_LIBRARIES stdc++ m) -set(LOG_LEVEL 0 CACHE INT "Choose the log level" ) +set(LOG_LEVEL 0 CACHE STRING "Choose the log level" ) # Prevents multiple file extensions from being appended one after the other # important for using gcov .o.gcno or .cpp.gcno now will be .gcno set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1) @@ -64,14 +65,10 @@ if(ENABLE_INTEGRATION_TESTING) message("GAUSSIANFILES found will not download") set(DOWNLOAD_TUTORIAL_FILES OFF) else(EXISTS "${PROJECT_SOURCE_DIR}/GAUSSIANFILES") - message("GAUSSIANFILES not found will download") - set(DOWNLOAD_TUTORIAL_FILES ON) - endif(EXISTS "${PROJECT_SOURCE_DIR}/GAUSSIANFILES") -endif() + message("GAUSSIANFILES not found will attempt to download") -if(DOWNLOAD_TUTORIAL_FILES) - message("Downloading gaussian tutorial files") - execute_process(COMMAND ${PROJECT_SOURCE_DIR}/scripts/test_suite_install.bash "${PROJECT_SOURCE_DIR}" ) + include(${PROJECT_SOURCE_DIR}/cmake/InstallGdown.cmake) + endif(EXISTS "${PROJECT_SOURCE_DIR}/GAUSSIANFILES") endif() if(ENABLE_UNIT_TESTING OR ENABLE_INTEGRATION_TESTING) diff --git a/cmake/InstallGdown.cmake b/cmake/InstallGdown.cmake new file mode 100644 index 0000000..d1b5f7f --- /dev/null +++ b/cmake/InstallGdown.cmake @@ -0,0 +1,29 @@ + +if(NOT EXISTS "${CMAKE_SOURCE_DIR}/GAUSSIANFILES") + find_program(GDOWN gdown ~/.local/bin) + + if( NOT GDOWN) + find_program(PIP NAMES pip pip3 PATHS ~/.local/bin) + if( NOT PIP) + message(FATAL_ERROR "Unable to download tutorial files with gdown, tutorial" + "files are needed to run both the tutorials and the integration tests," + "unable to locate pip to install gdown, please install pip, or install gdown" + "through some other means.") + else() + message("Pip is ") + execute_process(COMMAND ${PIP} "install" "--user" "--upgrade" "pip") + execute_process(COMMAND ${PIP} "install" "--user" "gdown" ) + endif() + find_program(GDOWN gdown ~/.local/bin) + + endif() + + if( GDOWN ) + find_program(UNZIP unzip) + execute_process(COMMAND ${GDOWN} https://drive.google.com/uc?id=1rCsj_jpMyE0S0cokFJDyBSA0aPNiIHNb WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + execute_process(COMMAND ${UNZIP} "GAUSSIANFILES.zip" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) + execute_process(COMMAND rm "GAUSSIANFILES.zip" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + else() + message(FATAL_ERROR "Found pip, but still unable to install or find gdown") + endif() +endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3637265..bc2fbfc 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,5 @@ add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/libcatnip") -add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/tools") +#add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/tools") if(ENABLE_UNIT_TESTING OR ENABLE_INTEGRATION_TESTING) add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/tests") endif() diff --git a/src/libcatnip/atom.hpp b/src/libcatnip/atom.hpp index 24c8b19..434579a 100644 --- a/src/libcatnip/atom.hpp +++ b/src/libcatnip/atom.hpp @@ -3,9 +3,10 @@ #ifndef _CATNIP_ATOM_HPP #define _CATNIP_ATOM_HPP - +// Private local includes #include "elements.hpp" +// Third party includes #include namespace catnip { diff --git a/src/libcatnip/atom_group_container.cpp b/src/libcatnip/atom_group_container.cpp index 08874c3..6c4dca1 100644 --- a/src/libcatnip/atom_group_container.cpp +++ b/src/libcatnip/atom_group_container.cpp @@ -65,7 +65,7 @@ namespace catnip { void AtomGroupContainer::add( AtomGroup atom_group ) { - if( isUniqueGroup(atom_group) ){ + if( isUniqueGroup_(atom_group) ){ atom_groups_.push_back(atom_group); } group_types_uptodate_ = false; @@ -146,6 +146,7 @@ namespace catnip { all_paired_atoms.push_back(atom_match); } } + return all_paired_atoms; } void AtomGroupContainer::assignBasisFunctionCount( diff --git a/src/libcatnip/elements.hpp b/src/libcatnip/elements.hpp index 03fc1b5..f5b7a14 100644 --- a/src/libcatnip/elements.hpp +++ b/src/libcatnip/elements.hpp @@ -1,3 +1,7 @@ + +#pragma once +#ifndef _CATNIP_ELEMENTS_HPP +#define _CATNIP_ELEMENTS_HPP #include #include #include @@ -403,4 +407,4 @@ namespace catnip { }; } - +#endif // _CATNIP_ELEMENTS_HPP diff --git a/src/libcatnip/index_map.cpp b/src/libcatnip/index_map.cpp index 0497ca3..0f71bc4 100644 --- a/src/libcatnip/index_map.cpp +++ b/src/libcatnip/index_map.cpp @@ -28,7 +28,6 @@ namespace catnip { // Searches the init row for the provided row and returns the group it is // in as well as its current index std::pair IndexMap::findLocation(int row){ - std::pair group_row; for( std::pair> group_rows : row_col_init){ int row_ind = 0; for ( int row_ : group_rows.second ){ @@ -38,6 +37,7 @@ namespace catnip { ++row_ind; } } + return std::pair(); } } // namespace catnip diff --git a/src/libcatnip/index_map.hpp b/src/libcatnip/index_map.hpp index c1df94f..6029185 100644 --- a/src/libcatnip/index_map.hpp +++ b/src/libcatnip/index_map.hpp @@ -2,6 +2,9 @@ #include "transfer_complex.hpp" +#pragma once +#ifndef _CATNIP_INDEX_MAP_HPP +#define _CATNIP_INDEX_MAP_HPP #include "atom.hpp" #include "atom_group.hpp" @@ -26,3 +29,4 @@ namespace catnip { } // namespace catnip +#endif // _CATNIP_INDEX_MAP_HPP diff --git a/src/libcatnip/size_type.hpp b/src/libcatnip/size_type.hpp new file mode 100644 index 0000000..7a4f4ce --- /dev/null +++ b/src/libcatnip/size_type.hpp @@ -0,0 +1,9 @@ +#pragma once +#ifndef _CATNIP_SIZE_TYPE_HPP +#define _CATNIP_SIZE_TYPE_HPP + +namespace catnip { + using Size = long int; +}; +#endif // _CATNIP_SIZE_TYPE_HPP + diff --git a/src/libcatnip/swap_engine.cpp b/src/libcatnip/swap_engine.cpp index a673b17..0ce44e0 100644 --- a/src/libcatnip/swap_engine.cpp +++ b/src/libcatnip/swap_engine.cpp @@ -4,81 +4,72 @@ #include "atom.hpp" #include "atom_group.hpp" +#include "size_type.hpp" namespace catnip { // Swaps rows columns and keeps up with how future swaps should be updated - class SwapEngine { - private: - size_t size_; - IndexMap ind_map_; - Eigen::MatrixXd scratch_; + SwapEngine::SwapEngine(IndexMap ind_map, Size size) : + size_(size), ind_map_(ind_map) { + scratch_ = Eigen::MatrixXd::Zero(size, 1); - public: - SwapEngine(IndexMap ind_map, size_t size) : - size_(size), ind_map_(ind_map) { - scratch_ = Eigen::MatrixXd::Zero(size, 1); + // Already have enough information to calculate the correct swap order + // Note the order of swaps is important. + for ( std::pair> group_row : ind_map_.row_col_init ){ + int group_ind = group_row.first; + for ( int row : group_row.second ) { + int final_row = ind_map_.row_col_final[group_ind].at(row); + std::pair swap(row,final_row); + // Now we need to update index map, the row located at the final + // position has now been moved + auto group_and_row_ind = ind_map_.findLocation(final_row); - // Already have enough information to calculate the correct swap order - // Note the order of swaps is important. - for ( std::pair> group_row : ind_map_.row_col_init ){ - int group_ind = group_row.first; - for ( int row : group_row.second ) { - int final_row = ind_map_.row_col_final[group_ind].at(row); - std::pair swap(row,final_row); - // Now we need to update index map, the row located at the final - // position has now been moved - auto group_and_row_ind = ind_map_.findLocation(final_row); - - // Final row location needs to be pointed to the starting row - ind_map_.row_col_init[group_and_row_ind.first].at(group_and_row_ind.second) = row; - } - } - }; - - - // This method of swapping was chosen to keep the memory footprint - // reasonable. - // Will correctly sort the rows and columns of the matrix - void arrange(Eigen::MatrixXd & mat) { + // Final row location needs to be pointed to the starting row + ind_map_.row_col_init[group_and_row_ind.first].at(group_and_row_ind.second) = row; + } + } + } + // This method of swapping was chosen to keep the memory footprint + // reasonable. + // Will correctly sort the rows and columns of the matrix + void SwapEngine::arrange(Eigen::MatrixXd & mat) { - // Check that matrix is square - if( mat.rows() != mat.cols() ) { - throw std::runtime_error("Can only arrange square matrices"); - } - if( mat.rows() != size_ ) { - throw std::runtime_error("Index map has different number of basis functions to matrix"); - } + // Check that matrix is square + if( mat.rows() != mat.cols() ) { + throw std::runtime_error("Can only arrange square matrices"); + } + if( mat.rows() != size_ ) { + throw std::runtime_error("Index map has different number of basis functions to matrix"); + } - for ( std::pair> group_row : ind_map_.row_col_init ){ - int group_ind = group_row.first; - for ( int row : group_row.second ) { - int final_row = ind_map_.row_col_final[group_ind].at(row); - if(final_row == row ) continue; - // Copy the data at the final row into the scratch space - scratch_.col(0) = mat.row(final_row); - // Copy the data from the initial row into the final row - mat.row(final_row) = mat.row(row); - // Copy the data from the temporary row into the initial row - mat.row(row) = scratch_.col(0); - } - } + for ( std::pair> group_row : ind_map_.row_col_init ){ + int group_ind = group_row.first; + for ( int row : group_row.second ) { + int final_row = ind_map_.row_col_final[group_ind].at(row); + if(final_row == row ) continue; + // Copy the data at the final row into the scratch space + scratch_.col(0) = mat.row(final_row); + // Copy the data from the initial row into the final row + mat.row(final_row) = mat.row(row); + // Copy the data from the temporary row into the initial row + mat.row(row) = scratch_.col(0); + } + } - // Repeat for columns - for ( std::pair> group_col : ind_map_.row_col_init ){ - int group_ind = group_col.first; - for ( int col : group_col.second ) { - int final_col = ind_map_.row_col_final[group_ind].at(col); - if(final_col == col ) continue; - // Copy the data at the final row into the scratch space - scratch_.col(0) = mat.col(final_col); - // Copy the data from the initial row into the final row - mat.col(final_col) = mat.col(col); - // Copy the data from the temporary row into the initial row - mat.col(col) = scratch_.col(0); - } - } + // Repeat for columns + for ( std::pair> group_col : ind_map_.row_col_init ){ + int group_ind = group_col.first; + for ( int col : group_col.second ) { + int final_col = ind_map_.row_col_final[group_ind].at(col); + if(final_col == col ) continue; + // Copy the data at the final row into the scratch space + scratch_.col(0) = mat.col(final_col); + // Copy the data from the initial row into the final row + mat.col(final_col) = mat.col(col); + // Copy the data from the temporary row into the initial row + mat.col(col) = scratch_.col(0); } - }; + } + } } // namespace catnip diff --git a/src/libcatnip/swap_engine.hpp b/src/libcatnip/swap_engine.hpp new file mode 100644 index 0000000..e5d7d6e --- /dev/null +++ b/src/libcatnip/swap_engine.hpp @@ -0,0 +1,29 @@ + +#pragma once +#ifndef _CATNIP_SWAP_ENGINE_HPP +#define _CATNIP_SWAP_ENGINE_HPP + +#include "atom.hpp" +#include "atom_group.hpp" +#include "index_map.hpp" +#include "size_type.hpp" + +namespace catnip { + + // Swaps rows columns and keeps up with how future swaps should be updated + class SwapEngine { + private: + Size size_; + IndexMap ind_map_; + Eigen::MatrixXd scratch_; + + public: + SwapEngine(IndexMap ind_map, Size size); + + void arrange(Eigen::MatrixXd & mat); + }; + + +} // namespace catnip + +#endif // _CATNIP_SWAP_ENGINE_HPP From c9ebdf6f281280cabd9fbec7db10b0686b36e41a Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Wed, 15 Jul 2020 06:59:02 -0600 Subject: [PATCH 38/68] Added Catch2 submodule --- .gitmodules | 3 +++ external/Catch2 | 1 + 2 files changed, 4 insertions(+) create mode 100644 .gitmodules create mode 160000 external/Catch2 diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..800345d --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "external/Catch2"] + path = external/Catch2 + url = https://github.com/catchorg/Catch2.git diff --git a/external/Catch2 b/external/Catch2 new file mode 160000 index 0000000..7f21cc6 --- /dev/null +++ b/external/Catch2 @@ -0,0 +1 @@ +Subproject commit 7f21cc6c5599f59835f769debf13b4c3e6148a28 From ccfdb7023c9e8b850372d49e92241cb7201c4f0c Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Wed, 15 Jul 2020 07:38:58 -0600 Subject: [PATCH 39/68] Added catch2 testing framework --- CMakeLists.txt | 72 ++++++++++++------------- cmake/InstallCatch2.cmake | 25 +++++++++ src/CMakeLists.txt | 1 + src/libcatnip/calcJconfig.hpp | 2 +- src/libcatnip/calcJconfig.hpp.in | 4 +- src/libcatnip/index_map.hpp | 14 ++--- src/tests/CMakeLists.txt | 11 ++-- src/tests/test_argumentdouble.cpp | 6 ++- src/tests/test_argumentfile.cpp | 5 +- src/tests/test_argumentint.cpp | 5 +- src/tests/test_argumentparser.cpp | 5 +- src/tests/test_argumentstring.cpp | 6 ++- src/tests/test_argumentswitch.cpp | 5 +- src/tests/test_log.cpp | 5 +- src/tests/test_logreader.cpp | 5 +- src/tests/test_parameters.cpp | 7 ++- src/tests/test_propertydouble.cpp | 6 ++- src/tests/test_propertyfileexist.cpp | 6 ++- src/tests/test_propertyfileext.cpp | 6 ++- src/tests/test_propertyint.cpp | 6 ++- src/tests/test_propertysisterfile.cpp | 6 ++- src/tests/test_propertystring.cpp | 6 ++- src/tests/test_propertystringchoice.cpp | 5 +- src/tests/test_propertyswitch.cpp | 5 +- src/tests/test_punreader.cpp | 5 +- src/tests/test_qc_functions.cpp | 6 ++- src/tests/test_string_support.cpp | 5 +- 27 files changed, 148 insertions(+), 92 deletions(-) create mode 100644 cmake/InstallCatch2.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index b987762..d7ba802 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ -cmake_minimum_required (VERSION 2.8) -project (calc_J) +cmake_minimum_required (VERSION 3.0) +project (calc_J VERSION 2.0.0) ############################################################################## # Defining options @@ -14,9 +14,9 @@ option(CODE_COVERAGE "Enable coverage reporting" OFF) ############################################################################## # Defining settings ############################################################################## -set(calcJ_VERSION_MAJOR 2 ) -set(calcJ_VERSION_MINOR 0 ) -set(calcJ_YEAR_PUBLISHED 2018 ) +#set(calcJ_VERSION_MAJOR 2 ) +#set(calcJ_VERSION_MINOR 0 ) +set(calcJ_YEAR_PUBLISHED 2020 ) set(calcJ_AUTHOR_SURNAME "\"Brown\"" ) set(calcJ_AUTHOR_INITIALS "\"J. S.\"" ) set(calcJ_TITLE "\"CATNIP\"") @@ -41,7 +41,6 @@ configure_file( # Finding dependencies ############################################################################## # Find bash it is important for testing using scripts -find_program (BASH_PROGRAM bash) find_library (GCOV gcov) #find_package (Eigen3 3.3 REQUIRED NO_MODULE) #if (TARGET Eigen3::Eigen) @@ -62,54 +61,49 @@ endif() ############################################################################## if(ENABLE_INTEGRATION_TESTING) if(EXISTS "${PROJECT_SOURCE_DIR}/GAUSSIANFILES") - message("GAUSSIANFILES found will not download") + message(STATUS "GAUSSIANFILES found will not download") set(DOWNLOAD_TUTORIAL_FILES OFF) else(EXISTS "${PROJECT_SOURCE_DIR}/GAUSSIANFILES") - message("GAUSSIANFILES not found will attempt to download") - + message(STATUS "GAUSSIANFILES not found will attempt to download") include(${PROJECT_SOURCE_DIR}/cmake/InstallGdown.cmake) endif(EXISTS "${PROJECT_SOURCE_DIR}/GAUSSIANFILES") endif() if(ENABLE_UNIT_TESTING OR ENABLE_INTEGRATION_TESTING) + find_package(Catch2 2.11.1) + if( NOT Catch2 ) + include(${PROJECT_SOURCE_DIR}/cmake/InstallCatch2.cmake) + else() + message(STATUS "found system installed Catch2 will not download") + endif() enable_testing() -endif() + include(ParseAndAddCatchTests) -if (ENABLE_INTEGRATION_TESTING) - file( COPY "${PROJECT_SOURCE_DIR}/GAUSSIANFILES/90_unordered/90_pair.log" - DESTINATION "${PROJECT_BINARY_DIR}/GAUSSIANFILES/90_unordered") - file( COPY "${PROJECT_SOURCE_DIR}/GAUSSIANFILES/90_unordered/90_pair.pun" - DESTINATION "${PROJECT_BINARY_DIR}/GAUSSIANFILES/90_unordered") + if (ENABLE_INTEGRATION_TESTING) + file( COPY "${PROJECT_SOURCE_DIR}/GAUSSIANFILES/90_unordered/90_pair.log" + DESTINATION "${PROJECT_BINARY_DIR}/GAUSSIANFILES/90_unordered") + file( COPY "${PROJECT_SOURCE_DIR}/GAUSSIANFILES/90_unordered/90_pair.pun" + DESTINATION "${PROJECT_BINARY_DIR}/GAUSSIANFILES/90_unordered") - file( COPY "${PROJECT_SOURCE_DIR}/GAUSSIANFILES/30_unordered/30_pair.pun" - DESTINATION "${PROJECT_BINARY_DIR}/GAUSSIANFILES/30_unordered") - file( COPY "${PROJECT_SOURCE_DIR}/GAUSSIANFILES/30_unordered/ref.pun" - DESTINATION "${PROJECT_BINARY_DIR}/GAUSSIANFILES/30_unordered") - file( COPY "${PROJECT_SOURCE_DIR}/GAUSSIANFILES/30_unordered/30_2.pun" - DESTINATION "${PROJECT_BINARY_DIR}/GAUSSIANFILES/30_unordered") -endif() + file( COPY "${PROJECT_SOURCE_DIR}/GAUSSIANFILES/30_unordered/30_pair.pun" + DESTINATION "${PROJECT_BINARY_DIR}/GAUSSIANFILES/30_unordered") + file( COPY "${PROJECT_SOURCE_DIR}/GAUSSIANFILES/30_unordered/ref.pun" + DESTINATION "${PROJECT_BINARY_DIR}/GAUSSIANFILES/30_unordered") + file( COPY "${PROJECT_SOURCE_DIR}/GAUSSIANFILES/30_unordered/30_2.pun" + DESTINATION "${PROJECT_BINARY_DIR}/GAUSSIANFILES/30_unordered") + endif() -if (ENABLE_UNIT_TESTING) - file( COPY "${PROJECT_SOURCE_DIR}/src/tests/testfile.pun" - DESTINATION "${PROJECT_BINARY_DIR}/src/tests") - file( COPY "${PROJECT_SOURCE_DIR}/src/tests/testfile.log" - DESTINATION "${PROJECT_BINARY_DIR}/src/tests") -endif() + if (ENABLE_UNIT_TESTING) + file( COPY "${PROJECT_SOURCE_DIR}/src/tests/testfile.pun" + DESTINATION "${PROJECT_BINARY_DIR}/src/tests") + file( COPY "${PROJECT_SOURCE_DIR}/src/tests/testfile.log" + DESTINATION "${PROJECT_BINARY_DIR}/src/tests") + endif() +endif() ############################################################################## # Compiling build tree/paths ############################################################################## -# Add the binary tree to the search path for include files -# so that we will find calcJconfig.hpp -#target_include_directories(calc_J "${PROJECT_BINARY_DIR}/src") -#target_link_directories(calc_J "${PROJECT_BINARY_DIR}/src") - -#link_directories("${PROJECT_SOURCE_DIR}/src/libcatnip/io/arguments/properties") -#link_directories("${PROJECT_SOURCE_DIR}/src/libcatnip/io/arguments") -#link_directories("${PROJECT_SOURCE_DIR}/src/libcatnip/io/file_readers") -#link_directories("${PROJECT_SOURCE_DIR}/src/libcatnip/io") -#link_directories("${PROJECT_SOURCE_DIR}/src/libcatnip") - add_subdirectory("${PROJECT_SOURCE_DIR}/src") diff --git a/cmake/InstallCatch2.cmake b/cmake/InstallCatch2.cmake new file mode 100644 index 0000000..b645d23 --- /dev/null +++ b/cmake/InstallCatch2.cmake @@ -0,0 +1,25 @@ + +# +#if(NOT EXISTS "${CMAKE_SOURCE_DIR}/external/Catch2/includes") +# find_program(CURL curl) +# if( NOT CURL) +# message(FATAL_ERROR "Unable to download Catch2, unable to locate curl, please install curl") +# else() +# execute_process(COMMAND mkdir -p ${CMAKE_SOURCE_DIR}/external/Catch2/single_include/catch2) +# execute_process(COMMAND ${CURL} https://raw.githubusercontent.com/catchorg/Catch2/master/single_include/catch2/catch.hpp -o ${CMAKE_SOURCE_DIR}/external/Catch2/single_include/catch2/catch.hpp) +# endif() +# add_library(Catch2 INTERFACE) +# target_include_directories(Catch2 INTERFACE ${CMAKE_SOURCE_DIR}/external/Catch2/single_include) +#endif() + +# If Catch2 is not found, instead use the git submodule +if (NOT EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/external/Catch2/single_include) + # Unable to find the header files for Catch2 or they don't exist + message(STATUS "Downloading Catch2 submodule.") + + # Clone the submodule + execute_process(COMMAND git submodule update --init --force -- external/Catch2 WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) +endif() + +add_subdirectory(${CMAKE_SOURCE_DIR}/external/Catch2) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/external/Catch2/contrib") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bc2fbfc..6efb70d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/libcatnip") #add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/tools") if(ENABLE_UNIT_TESTING OR ENABLE_INTEGRATION_TESTING) + message(STATUS "adding test directory") add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/tests") endif() diff --git a/src/libcatnip/calcJconfig.hpp b/src/libcatnip/calcJconfig.hpp index e574fe9..c8aaf0b 100644 --- a/src/libcatnip/calcJconfig.hpp +++ b/src/libcatnip/calcJconfig.hpp @@ -8,7 +8,7 @@ namespace catnip { const int calcJ_VERSION_MAJOR = 2; const int calcJ_VERSION_MINOR = 0; -const int calcJ_YEAR_PUBLISHED = 2018; +const int calcJ_YEAR_PUBLISHED = 2020; const std::string calcJ_AUTHOR_SURNAME = "Brown"; const std::string calcJ_AUTHOR_INITIALS = "J. S."; const std::string calcJ_TITLE = "CATNIP"; diff --git a/src/libcatnip/calcJconfig.hpp.in b/src/libcatnip/calcJconfig.hpp.in index f7777ce..83ca160 100644 --- a/src/libcatnip/calcJconfig.hpp.in +++ b/src/libcatnip/calcJconfig.hpp.in @@ -6,8 +6,8 @@ #include namespace catnip { -const int calcJ_VERSION_MAJOR = @calcJ_VERSION_MAJOR@; -const int calcJ_VERSION_MINOR = @calcJ_VERSION_MINOR@; +const int calcJ_VERSION_MAJOR = @PROJECT_VERSION_MAJOR@; +const int calcJ_VERSION_MINOR = @PROJECT_VERSION_MINOR@; const int calcJ_YEAR_PUBLISHED = @calcJ_YEAR_PUBLISHED@; const std::string calcJ_AUTHOR_SURNAME = @calcJ_AUTHOR_SURNAME@; const std::string calcJ_AUTHOR_INITIALS = @calcJ_AUTHOR_INITIALS@; diff --git a/src/libcatnip/index_map.hpp b/src/libcatnip/index_map.hpp index 6029185..51b50b5 100644 --- a/src/libcatnip/index_map.hpp +++ b/src/libcatnip/index_map.hpp @@ -1,18 +1,20 @@ - -#include "transfer_complex.hpp" - #pragma once #ifndef _CATNIP_INDEX_MAP_HPP #define _CATNIP_INDEX_MAP_HPP -#include "atom.hpp" -#include "atom_group.hpp" + +// Local private includes +#include "atom_group_container.hpp" + +// Standard includes +#include +#include namespace catnip { class IndexMap { public: - + IndexMap() = default; IndexMap(AtomGroupContainer atom_groups); // The component rows and colums in their current locations in // in the full system matrix of the complex diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index ab1c7c6..2326895 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -19,7 +19,7 @@ list( APPEND UNIT_TEST_SOURCE_FILES test_string_support) if(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") - link_libraries(gcov) + find_library (GCOV gcov) endif(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") if(ENABLE_UNIT_TESTING) @@ -28,8 +28,8 @@ if(ENABLE_UNIT_TESTING) if(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") set_source_files_properties( ${PROG}.cpp PROPERTIES COMPILE_FLAGS ${COVERAGE_FLAGS} ) endif(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") - target_link_libraries(unit_${PROG} libcatnip) - add_test(unit_${PROG} unit_${PROG}) + target_link_libraries(unit_${PROG} libcatnip Catch2::Catch2) + ParseAndAddCatchTests(unit_${PROG}) endforeach(PROG) endif(ENABLE_UNIT_TESTING) @@ -44,7 +44,7 @@ if(ENABLE_INTEGRATION_TESTING) set_source_files_properties( ${PROG}.cpp PROPERTIES COMPILE_FLAGS ${COVERAGE_FLAGS}) endif(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") - target_link_libraries(integration${PROG} libcatnip) + target_link_libraries(integration${PROG} libcatnip Catch2::Catch2) add_test(integration${PROG} integration${PROG}) endforeach(PROG) @@ -60,11 +60,14 @@ if(ENABLE_INTEGRATION_TESTING) POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_CURRENT_SOURCE_DIR}) + find_program (BASH_PROGRAM bash) if(BASH_PROGRAM) add_test(regression_test_io_script ${BASH_PROGRAM} ${PROJECT_SOURCE_DIR}/src/tests/test_script_io.sh ${CMAKE_CURRENT_SOURCE_DIR}) add_test(integration_test_calc_J_script ${BASH_PROGRAM} ${PROJECT_SOURCE_DIR}/src/tests/test_script_calc_J.sh ${CMAKE_SOURCE_DIR}) + else() + message(STATUS "Unable to add integration tests, unable to find bash") endif(BASH_PROGRAM) endif(ENABLE_INTEGRATION_TESTING) diff --git a/src/tests/test_argumentdouble.cpp b/src/tests/test_argumentdouble.cpp index 51d64c2..781b3ef 100644 --- a/src/tests/test_argumentdouble.cpp +++ b/src/tests/test_argumentdouble.cpp @@ -1,4 +1,7 @@ +#define CATCH_CONFIG_MAIN +#include + #include "../libcatnip/io/arguments/argumentdouble.hpp" #include #include @@ -6,7 +9,7 @@ using namespace catnip; using namespace std; -int main(void) { +TEST_CASE("Argument Doubles","[unit]") { cerr << "Testing: argumentdouble" << endl; cerr << "Testing: constructor" << endl; @@ -87,5 +90,4 @@ int main(void) { assert(opt_max_val); } - return 0; } diff --git a/src/tests/test_argumentfile.cpp b/src/tests/test_argumentfile.cpp index 53e9484..00a7b3f 100644 --- a/src/tests/test_argumentfile.cpp +++ b/src/tests/test_argumentfile.cpp @@ -1,11 +1,13 @@ +#define CATCH_CONFIG_MAIN +#include #include "../libcatnip/io/arguments/argumentfile.hpp" #include using namespace catnip; using namespace std; -int main(void) { +TEST_CASE("Argument File","[unit]") { cerr << "Testing: argumentfile" << endl; cerr << "Testing: constructor" << endl; @@ -159,5 +161,4 @@ int main(void) { cerr << "extensions " << str_exts << endl; } - return 0; } diff --git a/src/tests/test_argumentint.cpp b/src/tests/test_argumentint.cpp index c059c3b..ab2746c 100644 --- a/src/tests/test_argumentint.cpp +++ b/src/tests/test_argumentint.cpp @@ -1,4 +1,6 @@ +#define CATCH_CONFIG_MAIN +#include #include "../libcatnip/io/arguments/argumentint.hpp" #include #include @@ -6,7 +8,7 @@ using namespace catnip; using namespace std; -int main(void) { +TEST_CASE("Argument int","[unit]") { cerr << "Testing: argumentint" << endl; cerr << "Testing: constructor" << endl; @@ -86,5 +88,4 @@ int main(void) { assert(opt_max_val); } - return 0; } diff --git a/src/tests/test_argumentparser.cpp b/src/tests/test_argumentparser.cpp index 5cbac64..dbdb395 100644 --- a/src/tests/test_argumentparser.cpp +++ b/src/tests/test_argumentparser.cpp @@ -1,4 +1,6 @@ +#define CATCH_CONFIG_MAIN +#include #include "../libcatnip/io/argumentparser.hpp" #include "../libcatnip/matrix.hpp" @@ -11,7 +13,7 @@ using namespace catnip; using namespace std; -int main(void) { +TEST_CASE("Argument Parser","[unit]") { cerr << "Testing: ArgumentParser" << endl; cerr << "Testing: constructor" << endl; @@ -190,5 +192,4 @@ int main(void) { assert(sisFileNamePath.compare("testfile.log") == 0); } - return 0; } diff --git a/src/tests/test_argumentstring.cpp b/src/tests/test_argumentstring.cpp index 66e93e3..b12619c 100644 --- a/src/tests/test_argumentstring.cpp +++ b/src/tests/test_argumentstring.cpp @@ -1,4 +1,7 @@ +#define CATCH_CONFIG_MAIN +#include + #include "../libcatnip/io/arguments/argumentstring.hpp" #include #include @@ -6,7 +9,7 @@ using namespace catnip; using namespace std; -int main(void) { +TEST_CASE("Argument String","[unit]") { cerr << "Testing: argumentstring" << endl; cerr << "Testing: constructor" << endl; @@ -122,5 +125,4 @@ int main(void) { assert(opt_choices_val); } - return 0; } diff --git a/src/tests/test_argumentswitch.cpp b/src/tests/test_argumentswitch.cpp index 943c16c..9db01ae 100644 --- a/src/tests/test_argumentswitch.cpp +++ b/src/tests/test_argumentswitch.cpp @@ -1,4 +1,6 @@ +#define CATCH_CONFIG_MAIN +#include #include "../libcatnip/io/arguments/argumentswitch.hpp" #include #include @@ -6,7 +8,7 @@ using namespace catnip; using namespace std; -int main(void) { +TEST_CASE("Argument Switch","[unit]") { cerr << "Testing: argumentswitch" << endl; cerr << "Testing: constructor" << endl; @@ -71,5 +73,4 @@ int main(void) { assert(opt_def_val); } - return 0; } diff --git a/src/tests/test_log.cpp b/src/tests/test_log.cpp index 36446be..fdf3e54 100644 --- a/src/tests/test_log.cpp +++ b/src/tests/test_log.cpp @@ -1,9 +1,10 @@ +#define CATCH_CONFIG_MAIN +#include #include "../libcatnip/log.hpp" using namespace catnip; -int main(void) { +TEST_CASE("Log","[unit]") { LOG("Testing log message", 1); - return 0; } diff --git a/src/tests/test_logreader.cpp b/src/tests/test_logreader.cpp index 784d1a3..09e1286 100644 --- a/src/tests/test_logreader.cpp +++ b/src/tests/test_logreader.cpp @@ -1,4 +1,6 @@ +#define CATCH_CONFIG_MAIN +#include #include #include @@ -13,7 +15,7 @@ using namespace catnip; using namespace std; -int main(void) { +TEST_CASE("Log Reader","[unit]") { cout << "Testing: LogReader Constructor" << endl; { LogReader lr("file.log"); } @@ -443,5 +445,4 @@ int main(void) { cout << x.at(ind) << " " << y.at(ind) << " " << z.at(ind) << endl; } } - return 0; } diff --git a/src/tests/test_parameters.cpp b/src/tests/test_parameters.cpp index 80847c4..50884bb 100644 --- a/src/tests/test_parameters.cpp +++ b/src/tests/test_parameters.cpp @@ -1,10 +1,13 @@ + +#define CATCH_CONFIG_MAIN +#include + #include "../libcatnip/parameters.hpp" using namespace catnip; -int main(void) { +TEST_CASE("Parameters","[unit]") { Parameters Par; - return 0; } diff --git a/src/tests/test_propertydouble.cpp b/src/tests/test_propertydouble.cpp index a70ec8e..c07a655 100644 --- a/src/tests/test_propertydouble.cpp +++ b/src/tests/test_propertydouble.cpp @@ -1,4 +1,7 @@ +#define CATCH_CONFIG_MAIN +#include + #include "../libcatnip/io/arguments/properties/propertydouble.hpp" #include #include @@ -9,7 +12,7 @@ using namespace catnip; using namespace std; -int main(void) { +TEST_CASE("Property Double","[unit]") { cerr << "Testing: PropertyDouble" << endl; cerr << "Testing: constructor" << endl; @@ -64,5 +67,4 @@ int main(void) { } assert(excep); } - return 0; } diff --git a/src/tests/test_propertyfileexist.cpp b/src/tests/test_propertyfileexist.cpp index d405b16..dfb3429 100644 --- a/src/tests/test_propertyfileexist.cpp +++ b/src/tests/test_propertyfileexist.cpp @@ -1,4 +1,7 @@ +#define CATCH_CONFIG_MAIN +#include + #include "../libcatnip/io/arguments/properties/propertyfileexist.hpp" #include #include @@ -9,7 +12,7 @@ using namespace catnip; using namespace std; -int main(void) { +TEST_CASE("Property File Exists","[unit]") { cerr << "Testing: PropertyFileExist" << endl; cerr << "Testing: constructor" << endl; @@ -67,5 +70,4 @@ int main(void) { assert(fileExist == false); } - return 0; } diff --git a/src/tests/test_propertyfileext.cpp b/src/tests/test_propertyfileext.cpp index dc9fc2d..634be72 100644 --- a/src/tests/test_propertyfileext.cpp +++ b/src/tests/test_propertyfileext.cpp @@ -1,4 +1,7 @@ +#define CATCH_CONFIG_MAIN +#include + #include "../libcatnip/io/arguments/properties/propertyfileext.hpp" #include #include @@ -9,7 +12,7 @@ using namespace catnip; using namespace std; -int main(void) { +TEST_CASE("Property File Extension","[unit]") { cerr << "Testing: PropertyFileExt" << endl; cerr << "Testing: constructor" << endl; @@ -78,5 +81,4 @@ int main(void) { } assert(excep); } - return 0; } diff --git a/src/tests/test_propertyint.cpp b/src/tests/test_propertyint.cpp index ecc50fb..54430ae 100644 --- a/src/tests/test_propertyint.cpp +++ b/src/tests/test_propertyint.cpp @@ -1,4 +1,7 @@ +#define CATCH_CONFIG_MAIN +#include + #include "../libcatnip/io/arguments/properties/propertyint.hpp" #include #include @@ -9,7 +12,7 @@ using namespace catnip; using namespace std; -int main(void) { +TEST_CASE("Property Int","[unit]") { cerr << "Testing: PropertyInt" << endl; cerr << "Testing: constructor" << endl; @@ -61,5 +64,4 @@ int main(void) { } assert(excep); } - return 0; } diff --git a/src/tests/test_propertysisterfile.cpp b/src/tests/test_propertysisterfile.cpp index 60b947a..dc3af30 100644 --- a/src/tests/test_propertysisterfile.cpp +++ b/src/tests/test_propertysisterfile.cpp @@ -1,4 +1,7 @@ +#define CATCH_CONFIG_MAIN +#include + #include "../libcatnip/io/arguments/properties/propertysisterfile.hpp" #include #include @@ -10,7 +13,7 @@ using namespace catnip; using namespace std; -int main(void) { +TEST_CASE("Property Sister File","[unit]") { fstream fs; fs.open("testfile.pun", ios::out); fs.close(); @@ -110,5 +113,4 @@ int main(void) { assert(file_path_name.at(0).compare("testfile.pun") == 0); assert(fileExist.at(0).compare("true") == 0); } - return 0; } diff --git a/src/tests/test_propertystring.cpp b/src/tests/test_propertystring.cpp index f0e0ce0..6050966 100644 --- a/src/tests/test_propertystring.cpp +++ b/src/tests/test_propertystring.cpp @@ -1,4 +1,7 @@ +#define CATCH_CONFIG_MAIN +#include + #include "../libcatnip/io/arguments/properties/propertystring.hpp" #include #include @@ -9,7 +12,7 @@ using namespace catnip; using namespace std; -int main(void) { +TEST_CASE("Property String","[unit]") { cerr << "Testing: PropertyString" << endl; cerr << "Testing: constructor" << endl; @@ -63,5 +66,4 @@ int main(void) { } assert(excep); } - return 0; } diff --git a/src/tests/test_propertystringchoice.cpp b/src/tests/test_propertystringchoice.cpp index 7c1cbcc..7e09874 100644 --- a/src/tests/test_propertystringchoice.cpp +++ b/src/tests/test_propertystringchoice.cpp @@ -1,4 +1,6 @@ +#define CATCH_CONFIG_MAIN +#include #include "../libcatnip/io/arguments/properties/propertystringchoice.hpp" #include #include @@ -10,7 +12,7 @@ using namespace catnip; using namespace std; -int main(void) { +TEST_CASE("Property String Choice","[unit]") { cerr << "Testing: PropertyStringChoice" << endl; cerr << "Testing: constructor" << endl; { PropertyStringChoice propStrChoice; } @@ -95,5 +97,4 @@ int main(void) { string on = *(choice_on.begin()); assert(on.compare("true") == 0); } - return 0; } diff --git a/src/tests/test_propertyswitch.cpp b/src/tests/test_propertyswitch.cpp index ec41006..18f40b0 100644 --- a/src/tests/test_propertyswitch.cpp +++ b/src/tests/test_propertyswitch.cpp @@ -1,4 +1,6 @@ +#define CATCH_CONFIG_MAIN +#include #include "../libcatnip/io/arguments/properties/propertyswitch.hpp" #include #include @@ -9,7 +11,7 @@ using namespace catnip; using namespace std; -int main(void) { +TEST_CASE("Property Switch","[unit]") { cerr << "Testing: PropertySwitch" << endl; cerr << "Testing: constructor" << endl; @@ -84,5 +86,4 @@ int main(void) { // } // assert(excep); } - return 0; } diff --git a/src/tests/test_punreader.cpp b/src/tests/test_punreader.cpp index 0893860..3d36a2b 100644 --- a/src/tests/test_punreader.cpp +++ b/src/tests/test_punreader.cpp @@ -1,4 +1,6 @@ +#define CATCH_CONFIG_MAIN +#include #include "../libcatnip/io/file_readers/punreader.hpp" #include #include @@ -9,7 +11,7 @@ using namespace catnip; using namespace std; -int main(void) { +TEST_CASE("Pun Reader","[unit]") { cerr << "Testing: PunReader Constructor" << endl; { PunReader pr("file.pun"); } @@ -23,5 +25,4 @@ int main(void) { assert(m.rows() == 92); assert(pr.restrictedShell()); } - return 0; } diff --git a/src/tests/test_qc_functions.cpp b/src/tests/test_qc_functions.cpp index f4874d6..d0ef8a8 100644 --- a/src/tests/test_qc_functions.cpp +++ b/src/tests/test_qc_functions.cpp @@ -1,3 +1,6 @@ + +#define CATCH_CONFIG_MAIN +#include #include "../libcatnip/qc_functions.hpp" #include "../libcatnip/matrix.hpp" #include @@ -7,7 +10,7 @@ using namespace catnip; using namespace std; -int main(void) { +TEST_CASE("QC Functions","[unit]") { cout << "Testing: unscramble_Coef" << endl; { @@ -291,5 +294,4 @@ int main(void) { } } } - return 0; } diff --git a/src/tests/test_string_support.cpp b/src/tests/test_string_support.cpp index b1f1204..dceedf6 100644 --- a/src/tests/test_string_support.cpp +++ b/src/tests/test_string_support.cpp @@ -1,4 +1,6 @@ +#define CATCH_CONFIG_MAIN +#include #include "../libcatnip/string_support.hpp" #include #include @@ -8,7 +10,7 @@ using namespace catnip; using namespace std; -int main(void) { +TEST_CASE("String Support","[unit]") { cerr << "Testing: splitSt" << endl; { @@ -103,5 +105,4 @@ int main(void) { assert(str3.compare(str) == 0); } - return 0; } From e63c815f10b0a219c854739a9bec4c1f792f18bf Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Thu, 16 Jul 2020 07:34:10 -0600 Subject: [PATCH 40/68] Added elements tests --- src/libcatnip/CMakeLists.txt | 2 +- src/libcatnip/atom.hpp | 6 +- src/libcatnip/atom_group.cpp | 2 +- src/libcatnip/atom_group_container.cpp | 2 +- src/libcatnip/elements.hpp | 126 +++++++++++++++++++++++++ src/tests/CMakeLists.txt | 2 + 6 files changed, 136 insertions(+), 4 deletions(-) diff --git a/src/libcatnip/CMakeLists.txt b/src/libcatnip/CMakeLists.txt index a8f855a..2f4e8d8 100644 --- a/src/libcatnip/CMakeLists.txt +++ b/src/libcatnip/CMakeLists.txt @@ -7,4 +7,4 @@ file(GLOB CATNIP_SOURCE_FILES io/file_readers/*.cpp) add_library(libcatnip ${CATNIP_SOURCE_FILES}) -target_include_directories(libcatnip PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") +target_include_directories(libcatnip PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/src/libcatnip/atom.hpp b/src/libcatnip/atom.hpp index 434579a..84eb703 100644 --- a/src/libcatnip/atom.hpp +++ b/src/libcatnip/atom.hpp @@ -25,7 +25,7 @@ namespace catnip { int getBasisFuncCount() const noexcept { return basis_func_count_; } - bool equal( Atom & atm2 ) const { + bool operator==( const Atom & atm2 ) const { if ( element_ == atm2.element_ ){ if ( xyz_.isApprox(atm2.xyz_)) { return true; @@ -33,6 +33,10 @@ namespace catnip { } return false; } + + bool operator!=( const Atom & atm2 ) const { + return !(*this == atm2); + } }; diff --git a/src/libcatnip/atom_group.cpp b/src/libcatnip/atom_group.cpp index cd5eb95..00524e2 100644 --- a/src/libcatnip/atom_group.cpp +++ b/src/libcatnip/atom_group.cpp @@ -7,7 +7,7 @@ namespace catnip { int AtomGroup::findIndex(std::shared_ptr atom) { int index = 0; for ( std::shared_ptr & atom_ : atoms_){ - if ( atom_->equal(*atom)){ + if ( *atom_ == (*atom)){ return index; } ++index; diff --git a/src/libcatnip/atom_group_container.cpp b/src/libcatnip/atom_group_container.cpp index 6c4dca1..7670c92 100644 --- a/src/libcatnip/atom_group_container.cpp +++ b/src/libcatnip/atom_group_container.cpp @@ -51,7 +51,7 @@ namespace catnip { std::unordered_map paired_atoms; for ( size_t ind1 = 0; ind1 < grp1.size(); ++ind1){ for (size_t ind2 = 0; ind2 < grp2.size(); ++ind2){ - if ( grp1.at(ind1)->equal(*grp2.at(ind2)) ){ + if ( *(grp1.at(ind1)) == *(grp2.at(ind2)) ){ if ( paired_atoms.count(ind1) ) { throw std::runtime_error("Atom in complex has already been paired with an atom in the component, you have two or more atoms in a component that are redundant with an atom in the complex"); } diff --git a/src/libcatnip/elements.hpp b/src/libcatnip/elements.hpp index f5b7a14..6959d7d 100644 --- a/src/libcatnip/elements.hpp +++ b/src/libcatnip/elements.hpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace catnip { @@ -163,7 +164,132 @@ namespace catnip { return Element::Unknown; } + std::string getString(Element element) const noexcept { + return elements_str_sym_.at(static_cast(element)); + } private: + + std::vector elements_str_sym_ = { + "Ac", + "Al", + "Am", + "Sb", + "Ar", + "As", + "At", + "Ba", + "Bk", + "Be", + "Bi", + "Bh", + "B", + "Br", + "Cd", + "Ca", + "Cf", + "C", + "Ce", + "Cs", + "Cl", + "Cr", + "Co", + "Cu", + "Cm", + "Ds", + "Db", + "Dy", + "Es", + "Er", + "Eu", + "Fm", + "F", + "Fr", + "Gd", + "Ga", + "Ge", + "Au", + "Hf", + "Hs", + "He", + "Ho", + "H", + "In", + "I", + "Ir", + "Fe", + "Kr", + "La", + "Lr", + "Pb", + "Li", + "Lu", + "Mg", + "Mn", + "Mt", + "Md", + "Hg", + "Mo", + "Nd", + "Ne", + "Np", + "Ni", + "Nb", + "N", + "No", + "Uuo", + "Os", + "O", + "Pd", + "P", + "Pt", + "Pu", + "Po", + "K", + "Pr", + "Pm", + "Pa", + "Ra", + "Rn", + "Re", + "Rh", + "Rg", + "Rb", + "Ru", + "Rf", + "Sm", + "Sc", + "Sg", + "Se", + "Si", + "Ag", + "Na", + "Sr", + "S", + "Ta", + "Tc", + "Te", + "Tb", + "Tl", + "Th", + "Tm", + "Sn", + "Ti", + "W", + "Uub", + "Uuh", + "Uup", + "Uuq", + "Uus", + "Uut", + "U", + "V", + "Xe", + "Yb", + "Y", + "Zn", + "Zr", + "Unknown"}; + std::map elements_ = { {"actinium", Element::Ac}, {"aluminum", Element::Al}, diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 2326895..7237b9d 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -5,6 +5,8 @@ list( APPEND UNIT_TEST_SOURCE_FILES test_argumentparser test_argumentstring test_argumentswitch + test_atom + test_elements test_log test_parameters test_propertydouble From adeaa09665717882a0a24110faa445ce3c0ec463 Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Thu, 16 Jul 2020 07:34:24 -0600 Subject: [PATCH 41/68] Added elements test --- src/tests/test_elements.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/tests/test_elements.cpp diff --git a/src/tests/test_elements.cpp b/src/tests/test_elements.cpp new file mode 100644 index 0000000..164e8dc --- /dev/null +++ b/src/tests/test_elements.cpp @@ -0,0 +1,20 @@ + +#define CATCH_CONFIG_MAIN +#include + +#include "elements.hpp" + +using namespace catnip; + +TEST_CASE("Elements","[unit]") { + + Elements elements; + Element elem = Element::H; + REQUIRE( elem == elements.getElement("H")); + REQUIRE( elements.getString(elem) == "H"); + REQUIRE( elem == elements.getElement("h")); + + Element unknown = Element::Unknown; + REQUIRE( unknown == elements.getElement("blah")); + REQUIRE( "Unknown" == elements.getString(unknown)); +} From 430cd19f74e93beda2899c6bc6589d0461ee69bf Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Thu, 16 Jul 2020 23:45:03 -0600 Subject: [PATCH 42/68] GroupType assignment completed --- src/libcatnip/atom.hpp | 27 ++++- src/libcatnip/atom_group.cpp | 22 +++- src/libcatnip/atom_group.hpp | 60 ++++++++--- src/libcatnip/atom_group_container.cpp | 134 +++++++++++++++++++----- src/libcatnip/atom_group_container.hpp | 31 ++++-- src/libcatnip/index_map.cpp | 11 +- src/libcatnip/transfer_complex.cpp | 4 +- src/tests/CMakeLists.txt | 2 + src/tests/test_atom.cpp | 23 ++++ src/tests/test_atom_group.cpp | 56 ++++++++++ src/tests/test_atom_group_container.cpp | 52 +++++++++ src/tests/test_index_map.cpp | 16 +++ 12 files changed, 374 insertions(+), 64 deletions(-) create mode 100644 src/tests/test_atom.cpp create mode 100644 src/tests/test_atom_group.cpp create mode 100644 src/tests/test_atom_group_container.cpp create mode 100644 src/tests/test_index_map.cpp diff --git a/src/libcatnip/atom.hpp b/src/libcatnip/atom.hpp index 84eb703..7100708 100644 --- a/src/libcatnip/atom.hpp +++ b/src/libcatnip/atom.hpp @@ -9,16 +9,24 @@ // Third party includes #include +// Standard includes +#include + namespace catnip { class Atom { private: - Element element_; + // Element should not be able to change + const Element element_; Eigen::Vector3d xyz_; int basis_func_count_ = -1; public: Atom(Element element, double x, double y, double z) : element_(element), xyz_(x,y,z) {}; + Element getElement() const noexcept { return element_; } + + Eigen::Vector3d getPos() const noexcept { return xyz_; } + void setBasisFuncCount(int count) { basis_func_count_ = count; } @@ -39,7 +47,22 @@ namespace catnip { } }; - + double round(double N, double n); } +namespace std { + + template <> + struct hash + { + std::size_t operator()(const catnip::Atom& atom) const + { + Eigen::Vector3d pos = atom.getPos(); + return ((((std::hash()(atom.getElement()) + ^ (hash()(catnip::round(pos(0),4)) << 1)) >> 1) + ^ (hash()(catnip::round(pos(1),4)) << 1)) >> 1) + ^ (hash()(catnip::round(pos(2),4)) << 1); + } + }; +} #endif // _CATNIP_ATOM_HPP diff --git a/src/libcatnip/atom_group.cpp b/src/libcatnip/atom_group.cpp index 00524e2..618bff0 100644 --- a/src/libcatnip/atom_group.cpp +++ b/src/libcatnip/atom_group.cpp @@ -2,16 +2,32 @@ #include "atom_group.hpp" #include "atom.hpp" +// Standard includes +#include + namespace catnip { - int AtomGroup::findIndex(std::shared_ptr atom) { + std::vector AtomGroup::find(std::shared_ptr atom) { + std::vector indices; int index = 0; for ( std::shared_ptr & atom_ : atoms_){ if ( *atom_ == (*atom)){ - return index; + indices.push_back(index); + } + ++index; + } + return indices; + } + + std::vector AtomGroup::findStrict(std::shared_ptr atom) { + std::vector indices; + int index = 0; + for ( std::shared_ptr & atom_ : atoms_){ + if ( atom_.get() == atom.get()){ + indices.push_back(index); } ++index; } - return -1; + return indices; } } diff --git a/src/libcatnip/atom_group.hpp b/src/libcatnip/atom_group.hpp index 6647207..4ca8eb7 100644 --- a/src/libcatnip/atom_group.hpp +++ b/src/libcatnip/atom_group.hpp @@ -1,7 +1,11 @@ #pragma once -#ifndef _CATNIP_ATOM_GROUP_HPP -#define _CATNIP_ATOM_GROUP_HPP +#ifndef CATNIP_ATOM_GROUP_HPP +#define CATNIP_ATOM_GROUP_HPP +// Third party libary includes +#include + +// Standard includes #include #include #include @@ -9,20 +13,30 @@ #include #include -#include - namespace catnip { class Atom; /** * @brief Atom groups can either be a component or a complex + * + * Component - all atoms in the atom group have a matching atom in the + * complex, but do not share atoms between other components + * + * Complex - all atoms in this atom group have a matching atom in a component + * + * Unit - non of the atoms appear in any of the other atom groups + * + * Unknown - some combination, may or may not have overlapping components + * + * Unassigned - has not yet been specified */ enum class GroupType { - PotentialComponent, // The atoms in all the components == the num atoms in the complex - Component, // All atoms in the components have a matching atom in the complex + Component, Complex, - Unknown + Unit, + Unknown, + Unassigned }; /** @@ -37,15 +51,23 @@ namespace catnip { std::vector> atoms_; public: AtomGroup(std::string group_name) : name_(group_name) {}; + + std::string getName() const noexcept { return name_; } size_t size() const noexcept { return atoms_.size(); } std::vector>::iterator begin() { return atoms_.begin(); } + std::vector>::const_iterator + begin() const { return atoms_.begin(); } + std::vector>::iterator end() { return atoms_.end(); } + std::vector>::const_iterator + end() const { return atoms_.end(); } + std::shared_ptr at(size_t ind) const { return atoms_.at(ind); } @@ -58,26 +80,32 @@ namespace catnip { atoms_.insert(atoms_.end(),atoms.begin(),atoms.end()); } - size_t numberOfAtoms() const noexcept { - return atoms_.size(); - } - void setType(const GroupType & type) noexcept { type_ = type; } - GroupType getType() const noexcept { return type_; } + const GroupType & getType() const noexcept { return type_; } /** * @brief Find the index of the atom in the group if it exists and return - * the index + * the index, compares atoms + * + * @param atom + * + * @return indeces of atoms that match + */ + std::vector find(std::shared_ptr atom); + + + /** + * @brief Finds the exact matching atom in memory by looking at the address * * @param atom * - * @return index if found -1 if not found + * @return */ - int findIndex(std::shared_ptr atom); + std::vector findStrict(std::shared_ptr atom); }; } // namespace catnip -#endif // _CATNIP_ATOM_GROUP_HPP +#endif // CATNIP_ATOM_GROUP_HPP diff --git a/src/libcatnip/atom_group_container.cpp b/src/libcatnip/atom_group_container.cpp index 7670c92..058ec0a 100644 --- a/src/libcatnip/atom_group_container.cpp +++ b/src/libcatnip/atom_group_container.cpp @@ -1,17 +1,20 @@ - +// Local private includes #include "atom_group_container.hpp" #include "atom.hpp" #include "atom_group.hpp" +// Third party includes +#include + +// Standard includes #include #include #include #include #include #include - -#include +#include namespace catnip { @@ -72,35 +75,112 @@ namespace catnip { index_of_complex_ = -1; } - void AtomGroupContainer::assignAtomGroupTypes(){ - if (group_types_uptodate_ ) return; - std::vector number_atoms; - for( AtomGroup group : atom_groups_){ - number_atoms.push_back(group.numberOfAtoms()); + struct GroupAtomIndex { + int atm_ind; + int grp_ind; + }; + + static std::unordered_map> mapAtomsToGroups( + const std::vector & atom_groups_ ){ + + std::unordered_map> atm_map; + int grp_index = 0; + for ( const AtomGroup & grp : atom_groups_ ){ + int atom_index = 0; + for ( auto & atom_ptr : grp ){ + atm_map[*atom_ptr].push_back(GroupAtomIndex{atom_index,grp_index}); + ++atom_index; + } + ++grp_index; } - auto max_elem_it = max_element(number_atoms.begin(),number_atoms.end()); - size_t max_elem = *max_elem_it; - for( AtomGroup group : atom_groups_){ - group.setType(GroupType::Component); - } - size_t number_atoms_excluding_max = std::accumulate(number_atoms.begin(),number_atoms.end(),-1*max_elem); - if ( std::count(number_atoms.begin(),number_atoms.end(), max_elem) == 1 && - number_atoms_excluding_max == max_elem ){ - for( AtomGroup group : atom_groups_){ - if( group.numberOfAtoms() == max_elem ){ - group.setType(GroupType::Complex); - index_of_complex_ = std::distance(number_atoms.begin(),max_elem_it); + return atm_map; + } + + static const std::map> calculateConnectedGroups( + std::unordered_map> atm_map, + const std::vector & atom_groups_ + ){ + + std::map> grp_indices; + int grp_index = 0; + for ( const AtomGroup & grp : atom_groups_ ){ + for ( const auto & atom_ptr : grp ){ + for ( const GroupAtomIndex & grp_atm_ind : atm_map[*atom_ptr] ){ + if (grp_atm_ind.grp_ind != grp_index ){ + grp_indices[grp_index].push_back(grp_atm_ind.grp_ind); + } + } + } + ++grp_index; + } + return grp_indices; + } + + static void identifyAtomGroupsOfUnitType( + const std::map> & grp_indices, + std::vector & atom_groups_ + ) { + for ( std::pair> grp_groups : grp_indices){ + if(grp_groups.second.size() == 0) { + atom_groups_.at(grp_groups.first).setType(GroupType::Unit); + } + } + } + + static void identifyAtomGroupsOfComponentComplexAndUnknownTypes( + const std::map> & grp_indices, + std::vector & atom_groups_ + ){ + std::vector potential_complexes; + for ( std::pair> grp_groups : grp_indices){ + if( grp_groups.second.size() > 1 ){ + potential_complexes.push_back(grp_groups.first); + } + } + + for( const int & potential_complex : potential_complexes){ + std::vector candidate_components = grp_indices.at(potential_complex); + bool candidate_components_valid = true; + for ( const int & candidate_component : candidate_components){ + if ( grp_indices.at(candidate_component).size() != 1){ + candidate_components_valid = false; + break; // these are not components, and potential complex is not a complex } } + if ( candidate_components_valid){ + atom_groups_.at(potential_complex).setType(GroupType::Complex); + for ( const int & candidate_component : candidate_components){ + atom_groups_.at(candidate_component).setType(GroupType::Component); + } + }else{ + atom_groups_.at(potential_complex).setType(GroupType::Unknown); + for ( const int & candidate_component : candidate_components){ + atom_groups_.at(candidate_component).setType(GroupType::Unknown); + } + } } - group_types_uptodate_ = true; + } +// Create a map with an atom as the key and a vector of indices to indicate +// where there is overlap, the group and index of where the overlap occurs + void AtomGroupContainer::assignGroupTypes(){ + + std::unordered_map> atm_map = mapAtomsToGroups( atom_groups_ ); + // For each atom in a group find out how many other groups share the atoms + // First index is the group index the vector stores the other groups that + // share atoms + const std::map> grp_indices = calculateConnectedGroups(atm_map, atom_groups_ ); + + // Calculate which groups do not share atoms with other groups these are units + identifyAtomGroupsOfUnitType(grp_indices, atom_groups_); + + identifyAtomGroupsOfComponentComplexAndUnknownTypes(grp_indices,atom_groups_ ); } - int AtomGroupContainer::getTotalBasisFunctionCount(const GroupType & type) const { + int AtomGroupContainer::getTotalBasisFunctions(const GroupType & type) const { int total_num_basis = 0; std::vector group_indices = getGroups(type); for ( int ind : group_indices ){ - AtomGroup group = getGroup(ind); + AtomGroup group = atom_groups_.at(ind); for( const std::shared_ptr & atom_ptr : group ) { total_num_basis += atom_ptr->getBasisFuncCount(); } @@ -108,11 +188,11 @@ namespace catnip { return total_num_basis; } - int AtomGroupContainer::getMaxBasisFunctionCount(const GroupType & type) const { + int AtomGroupContainer::getMaxBasisFunctions(const GroupType & type) const { int max_num_basis = 0; std::vector group_indices = getGroups(type); for ( int ind : group_indices ){ - AtomGroup group = getGroup(ind); + AtomGroup group = atom_groups_.at(ind); for( const std::shared_ptr & atom_ptr : group ) { if( atom_ptr->getBasisFuncCount() > max_num_basis){ max_num_basis = atom_ptr->getBasisFuncCount(); @@ -149,7 +229,7 @@ namespace catnip { return all_paired_atoms; } - void AtomGroupContainer::assignBasisFunctionCount( + void AtomGroupContainer::assignBasisFunctions( const std::vector& complex_basis_func_count) { // 1. Check that up to date @@ -157,7 +237,7 @@ namespace catnip { throw std::runtime_error("Cannot assign basis functions to atoms as group types are not up to date!"); } // 2. Check that the number of atoms in the complex is consistent with the number of values provided - if ( complex_basis_func_count.size() != atom_groups_.at(index_of_complex_).numberOfAtoms() ){ + if ( complex_basis_func_count.size() != atom_groups_.at(index_of_complex_).size() ){ throw std::runtime_error("Cannot assign basis function count to atoms as the basis function count vector is not equal to the number of atoms!"); } diff --git a/src/libcatnip/atom_group_container.hpp b/src/libcatnip/atom_group_container.hpp index 4203669..daa4f98 100644 --- a/src/libcatnip/atom_group_container.hpp +++ b/src/libcatnip/atom_group_container.hpp @@ -1,11 +1,14 @@ #pragma once -#ifndef _CATNIP_ATOM_GROUP_CONTAINER_HPP -#define _CATNIP_ATOM_GROUP_CONTAINER_HPP +#ifndef CATNIP_ATOM_GROUP_CONTAINER_HPP +#define CATNIP_ATOM_GROUP_CONTAINER_HPP +// Local private includes #include "atom_group.hpp" +// Third party includes #include +// Standard includes #include #include #include @@ -18,10 +21,14 @@ namespace catnip { class Atom; + /// What we need is a function that will actually create the atom group + /// container so that the state is known, basically you need to pass in the + /// a vector of the atom groups class AtomGroupContainer { std::vector atom_groups_; bool group_types_uptodate_ = false; + /** * @brief Checks to makes sure the group is unique * @@ -57,6 +64,8 @@ namespace catnip { public: void add( AtomGroup atom_group ); + size_t size() const noexcept { return atom_groups_.size(); } + /** * @brief This algorithm determines if a complex exists * @@ -66,7 +75,7 @@ namespace catnip { * * Only a single atom group can be the complex */ - void assignAtomGroupTypes(); + void assignGroupTypes(); /** * @brief Determine if a complex exists within the atom groups @@ -75,7 +84,7 @@ namespace catnip { * * @return */ - bool complexExists() const ; + bool complexExists() const; /** * @brief If a complex exists and we know the number of basis functions @@ -84,11 +93,11 @@ namespace catnip { * * @param complex_basis_func_count */ - void assignBasisFunctionCount(const std::vector& complex_basis_func_count); + void assignBasisFunctions(const std::vector& complex_basis_func_count); - int getTotalBasisFunctionCount(const GroupType & type) const; + int getTotalBasisFunctions(const GroupType & type) const; - int getMaxBasisFunctionCount(const GroupType & type) const; + int getMaxBasisFunctions(const GroupType & type) const; /** * @brief Get the indices of all the groups of the specified group type * @@ -98,10 +107,10 @@ namespace catnip { */ std::vector getGroups(const GroupType & type) const; - AtomGroup getGroup(size_t ind) const { return atom_groups_.at(ind);} - - + AtomGroup & at(size_t ind) { return atom_groups_.at(ind);} }; + + } // namespace catnip -#endif // _CATNIP_ATOM_GROUP_CONTAINER_HPP +#endif // CATNIP_ATOM_GROUP_CONTAINER_HPP diff --git a/src/libcatnip/index_map.cpp b/src/libcatnip/index_map.cpp index 0f71bc4..3d4ad28 100644 --- a/src/libcatnip/index_map.cpp +++ b/src/libcatnip/index_map.cpp @@ -5,17 +5,22 @@ #include "atom.hpp" #include "atom_group.hpp" +// Standard includes +#include + namespace catnip { IndexMap::IndexMap(AtomGroupContainer atom_groups){ std::vector group_indices = atom_groups.getGroups(GroupType::Component); int complex_ind = atom_groups.getGroups(GroupType::Complex).at(0); - AtomGroup complex_group = atom_groups.getGroup(complex_ind); + AtomGroup complex_group = atom_groups.at(complex_ind); int sys_ind = 0; for ( int & group_ind : group_indices) { - AtomGroup component_group = atom_groups.getGroup(group_ind); + AtomGroup component_group = atom_groups.at(group_ind); for( std::shared_ptr & atom : component_group){ - int atom_ind = complex_group.findIndex(atom); + std::vector atom_indices = complex_group.find(atom); + assert(atom_indices.size() == 1); + int atom_ind = atom_indices.at(0); int num_basis = complex_group.at(atom_ind)->getBasisFuncCount(); for ( int ind_temp = 0; ind_temp + +// Local private includes +#include "../libcatnip/atom.hpp" + +#include "../libcatnip/elements.hpp" + +using namespace catnip; + +TEST_CASE("Elements","[unit]") { + + Elements elements; + Element H = elements.getElement("H"); + + Atom atom(H,0.0,0.0,0.0); + Atom atom2(H,1.0,0.0,0.0); + + REQUIRE( atom != atom2); + REQUIRE( atom == atom); + REQUIRE( atom2 == atom2); +} diff --git a/src/tests/test_atom_group.cpp b/src/tests/test_atom_group.cpp new file mode 100644 index 0000000..2ed81ce --- /dev/null +++ b/src/tests/test_atom_group.cpp @@ -0,0 +1,56 @@ + +#define CATCH_CONFIG_MAIN +#include + +// Local private includes +#include "atom_group.hpp" + +#include "atom.hpp" +#include "elements.hpp" + +// Standard includes +#include + +using namespace catnip; + +TEST_CASE("Atom Group","[unit]") { + + AtomGroup atom_grp("CH2"); + + REQUIRE(atom_grp.getType() == GroupType::Unknown ); + REQUIRE(atom_grp.getName() == "CH2"); + + Atom atom1(Element::H, 0.0, 0.0, 0.0); + Atom atom2(Element::H, 2.0, 0.0, 0.0); + Atom atom3(Element::C, 1.0, 1.0, 0.0); + // Same atom different memory location + Atom atom4(Element::H, 0.0, 0.0, 0.0); + + auto atom1_ptr = std::make_shared(atom1); + auto atom2_ptr = std::make_shared(atom2); + auto atom3_ptr = std::make_shared(atom3); + auto atom4_ptr = std::make_shared(atom4); + + atom_grp.add(atom1_ptr); + atom_grp.add(atom2_ptr); + atom_grp.add(atom3_ptr); + + REQUIRE(atom_grp.size() == 3); + + REQUIRE(atom_grp.find(atom1_ptr).size() == 1); + REQUIRE(atom_grp.find(atom2_ptr).size() == 1); + REQUIRE(atom_grp.find(atom3_ptr).size() == 1); + + REQUIRE(atom_grp.find(atom1_ptr).at(0) == 0); + REQUIRE(atom_grp.find(atom2_ptr).at(0) == 1); + REQUIRE(atom_grp.find(atom3_ptr).at(0) == 2); + + atom_grp.add(atom4_ptr); + REQUIRE(atom_grp.find(atom1_ptr).size() == 2); + REQUIRE(atom_grp.find(atom1_ptr).at(0) == 0); + REQUIRE(atom_grp.find(atom1_ptr).at(1) == 3); + + REQUIRE(atom_grp.findStrict(atom4_ptr).size() == 1); + REQUIRE(atom_grp.findStrict(atom4_ptr).at(0) == 3); + +} diff --git a/src/tests/test_atom_group_container.cpp b/src/tests/test_atom_group_container.cpp new file mode 100644 index 0000000..b31a3eb --- /dev/null +++ b/src/tests/test_atom_group_container.cpp @@ -0,0 +1,52 @@ + +#define CATCH_CONFIG_MAIN +#include + +// Local private includes +#include "atom_group_container.hpp" + +#include "atom.hpp" +#include "atom_group.hpp" +#include "elements.hpp" + +// Standard includes +#include + +using namespace catnip; + +TEST_CASE("Atom Group Container","[unit]") { + + AtomGroup atom_grp("CH2"); + + Atom atom1(Element::H, 0.0, 0.0, 0.0); + Atom atom2(Element::H, 2.0, 0.0, 0.0); + Atom atom3(Element::C, 1.0, 1.0, 0.0); + + auto atom1_ptr = std::make_shared(atom1); + auto atom2_ptr = std::make_shared(atom2); + auto atom3_ptr = std::make_shared(atom3); + + atom_grp.add(atom1_ptr); + atom_grp.add(atom2_ptr); + atom_grp.add(atom3_ptr); + + AtomGroup atom_grp2("O2"); + + Atom atom4(Element::O, 3.3, 4.3); + Atom atom5(Element::O, 3.0, 3.9); + + auto atom4_ptr = std::make_shared(atom4); + auto atom5_ptr = std::make_shared(atom5); + + atom_grp2.add(atom4_ptr); + atom_grp2.add(atom5_ptr); + + AtomGroupContainer atom_grp_cont; + + atom_grp_cont.add(atom_grp1); + atom_grp_cont.add(atom_grp2); + + REQUIRE(atom_grp_cont.size() == 2); + + atom_grp_cont.assignGroupTypes(); +} diff --git a/src/tests/test_index_map.cpp b/src/tests/test_index_map.cpp new file mode 100644 index 0000000..504f421 --- /dev/null +++ b/src/tests/test_index_map.cpp @@ -0,0 +1,16 @@ + +#define CATCH_CONFIG_MAIN +#include + +#include "index_map.hpp" + +#include "atom_group_container.hpp" + +using namespace catnip; + +TEST_CASE("Index Map","[unit]") { + + AtomGroupContainer atom_cont; + IndexMap ind_map(atom_cont); + +} From d08e466e89605ee5df6dfc1f6450a613696ffcba Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Fri, 17 Jul 2020 17:43:16 -0600 Subject: [PATCH 43/68] Group assignment test now working --- src/libcatnip/atom.cpp | 31 +++++++++ src/libcatnip/atom_group.hpp | 2 +- src/libcatnip/atom_group_container.cpp | 84 +++++++++++++++++++++++-- src/libcatnip/atom_group_container.hpp | 20 +++--- src/tests/CMakeLists.txt | 1 + src/tests/test_atom_group.cpp | 2 +- src/tests/test_atom_group_container.cpp | 49 ++++++++++++--- 7 files changed, 160 insertions(+), 29 deletions(-) create mode 100644 src/libcatnip/atom.cpp diff --git a/src/libcatnip/atom.cpp b/src/libcatnip/atom.cpp new file mode 100644 index 0000000..1c342e1 --- /dev/null +++ b/src/libcatnip/atom.cpp @@ -0,0 +1,31 @@ +#include "atom.hpp" + +namespace catnip { + double round(double N, double n) + { + int h; + double b, d, e, i, j, m, f; + b = N; + + // Counting the no. of digits to the left of decimal point + // in the given no. + for (i = 0; b >= 1; ++i) + b = b / 10; + + d = n - i; + b = N; + b = b * std::pow(10, d); + e = b + 0.5; + if ((float)e == (float)std::ceil(b)) { + f = (std::ceil(b)); + h = f - 2; + if (h % 2 != 0) { + e = e - 1; + } + } + j = std::floor(e); + m = std::pow(10, d); + j = j / m; + return j; + } +} diff --git a/src/libcatnip/atom_group.hpp b/src/libcatnip/atom_group.hpp index 4ca8eb7..db2a4d2 100644 --- a/src/libcatnip/atom_group.hpp +++ b/src/libcatnip/atom_group.hpp @@ -46,7 +46,7 @@ namespace catnip { */ class AtomGroup { private: - GroupType type_ = GroupType::Unknown; + GroupType type_ = GroupType::Unassigned; std::string name_; std::vector> atoms_; public: diff --git a/src/libcatnip/atom_group_container.cpp b/src/libcatnip/atom_group_container.cpp index 058ec0a..8e29402 100644 --- a/src/libcatnip/atom_group_container.cpp +++ b/src/libcatnip/atom_group_container.cpp @@ -10,6 +10,7 @@ // Standard includes #include #include +#include #include #include #include @@ -67,9 +68,54 @@ namespace catnip { } + bool AtomGroupContainer::isUniqueGroup_( const AtomGroup & atom_group ) const { + // Step 1 check the size of the atom group + if(atom_groups_.size() == 0) return true; + + for ( const AtomGroup & grp : atom_groups_ ){ + if ( grp.size() == atom_group.size() ){ + std::vector matchs(grp.size(),false); + // Determine if a match is found + for ( const auto & atm : atom_group ) { + size_t index = 0; + for ( bool matched : matchs ){ + if ( not matched ){ + // Compare atoms + if ( *atm == *(grp.at(index)) ){ + matchs.at(index) = true; + break; + } + } + ++index; + } + // If an atom was not matched it means that there is at least one + // difference, and so we do not need to cycle through the other + // atoms in this particular group + if(index == grp.size()) break; + } + // Count the number of matches in the vector if all of the elements match + // then the atom group is not unique + for ( bool match : matchs ) { + if ( match == false ) break; + } + return false; + } + } + return true; + } + // As soon as we add a new atom group it should invalidate the labels on + // all the other groups void AtomGroupContainer::add( AtomGroup atom_group ) { + std::cout << "Adding group " << atom_group.getName() << std::endl; if( isUniqueGroup_(atom_group) ){ + std::cout << "Is unique" << std::endl; atom_groups_.push_back(atom_group); + } else { + return; + } + + for ( AtomGroup & grp : atom_groups_ ){ + grp.setType(GroupType::Unassigned); } group_types_uptodate_ = false; index_of_complex_ = -1; @@ -104,14 +150,24 @@ namespace catnip { std::map> grp_indices; int grp_index = 0; for ( const AtomGroup & grp : atom_groups_ ){ + // Initialize + grp_indices[grp_index]; for ( const auto & atom_ptr : grp ){ for ( const GroupAtomIndex & grp_atm_ind : atm_map[*atom_ptr] ){ if (grp_atm_ind.grp_ind != grp_index ){ - grp_indices[grp_index].push_back(grp_atm_ind.grp_ind); + // Check that group has not already been added + if( grp_indices[grp_index].size() > 0 ){ + if( grp_indices[grp_index].back() != grp_atm_ind.grp_ind ) { + grp_indices[grp_index].push_back(grp_atm_ind.grp_ind); + } + }else { + grp_indices[grp_index].push_back(grp_atm_ind.grp_ind); + } } } } ++grp_index; + } return grp_indices; } @@ -122,6 +178,7 @@ namespace catnip { ) { for ( std::pair> grp_groups : grp_indices){ if(grp_groups.second.size() == 0) { + std::cout << "Empty makeing unit, does not share atoms" << std::endl; atom_groups_.at(grp_groups.first).setType(GroupType::Unit); } } @@ -142,6 +199,8 @@ namespace catnip { std::vector candidate_components = grp_indices.at(potential_complex); bool candidate_components_valid = true; for ( const int & candidate_component : candidate_components){ + std::cout << "Candiate component " << candidate_component << std::endl; + std::cout << "number of other groups sharing atoms " << grp_indices.at(candidate_component).size() << std::endl; if ( grp_indices.at(candidate_component).size() != 1){ candidate_components_valid = false; break; // these are not components, and potential complex is not a complex @@ -164,15 +223,30 @@ namespace catnip { // where there is overlap, the group and index of where the overlap occurs void AtomGroupContainer::assignGroupTypes(){ + std::cout << "Assigning group types" << std::endl; std::unordered_map> atm_map = mapAtomsToGroups( atom_groups_ ); + + std::cout << "Size of atom map " << atm_map.size() << std::endl; // For each atom in a group find out how many other groups share the atoms // First index is the group index the vector stores the other groups that // share atoms const std::map> grp_indices = calculateConnectedGroups(atm_map, atom_groups_ ); + for ( const auto & pr : grp_indices ) { + std::cout << "group " << pr.first << std::endl; + for ( auto ind : pr.second ){ + std::cout << "Atoms shared with group " << ind << std::endl; + } + } // Calculate which groups do not share atoms with other groups these are units identifyAtomGroupsOfUnitType(grp_indices, atom_groups_); + for ( const auto & pr : grp_indices ) { + std::cout << "group " << pr.first << std::endl; + for ( auto ind : pr.second ){ + std::cout << "Atoms shared with group " << ind << std::endl; + } + } identifyAtomGroupsOfComponentComplexAndUnknownTypes(grp_indices,atom_groups_ ); } @@ -202,12 +276,12 @@ namespace catnip { return max_num_basis; } - bool AtomGroupContainer::complexExists() const { + bool AtomGroupContainer::exists(GroupType type) const { // First check that all the group types have been assigned - if ( group_types_uptodate_ == false ){ - throw std::runtime_error("Cannot determine if complex exists group types are not up to date"); + for ( const AtomGroup & grp : atom_groups_ ){ + if( grp.getType() == type ) return true; } - return index_of_complex_ > -1; + return false; } std::vector AtomGroupContainer::matchComponentAtomsToComplex_(){ diff --git a/src/libcatnip/atom_group_container.hpp b/src/libcatnip/atom_group_container.hpp index daa4f98..d2b8b32 100644 --- a/src/libcatnip/atom_group_container.hpp +++ b/src/libcatnip/atom_group_container.hpp @@ -32,12 +32,13 @@ namespace catnip { /** * @brief Checks to makes sure the group is unique * + * Does not compare atom addresses just the atoms in the group the size + * Ignores the atom group name in the comparison * @param atom_group * * @return */ - bool isUniqueGroup_( AtomGroup atom_group ); - + bool isUniqueGroup_( const AtomGroup & atom_group ) const; /** * @brief Match the indices of the first atom group with any that share @@ -67,25 +68,18 @@ namespace catnip { size_t size() const noexcept { return atom_groups_.size(); } /** - * @brief This algorithm determines if a complex exists - * - * This algorithm does not compare the atoms in the complex with the - * atoms in the components, so it is not a rigourous algorithm but should - * be sufficient for our purposes. - * - * Only a single atom group can be the complex + * @brief This algorithm assignes a group type to each each of the groups */ void assignGroupTypes(); /** - * @brief Determine if a complex exists within the atom groups - * - * Only a single atom group can be a complex + * @brief Determine if a specified group type exists within the atom groups * * @return */ - bool complexExists() const; + bool exists(GroupType type) const; + GroupType getType(int index) const { return atom_groups_.at(index).getType(); } /** * @brief If a complex exists and we know the number of basis functions * associated with each atom in the complex we can assign the basis function diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index c716fbd..ee82c99 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -7,6 +7,7 @@ list( APPEND UNIT_TEST_SOURCE_FILES test_argumentswitch test_atom test_atom_group + test_atom_group_container test_elements test_index_map test_log diff --git a/src/tests/test_atom_group.cpp b/src/tests/test_atom_group.cpp index 2ed81ce..34de2e4 100644 --- a/src/tests/test_atom_group.cpp +++ b/src/tests/test_atom_group.cpp @@ -17,7 +17,7 @@ TEST_CASE("Atom Group","[unit]") { AtomGroup atom_grp("CH2"); - REQUIRE(atom_grp.getType() == GroupType::Unknown ); + REQUIRE(atom_grp.getType() == GroupType::Unassigned ); REQUIRE(atom_grp.getName() == "CH2"); Atom atom1(Element::H, 0.0, 0.0, 0.0); diff --git a/src/tests/test_atom_group_container.cpp b/src/tests/test_atom_group_container.cpp index b31a3eb..d5b1dff 100644 --- a/src/tests/test_atom_group_container.cpp +++ b/src/tests/test_atom_group_container.cpp @@ -16,8 +16,6 @@ using namespace catnip; TEST_CASE("Atom Group Container","[unit]") { - AtomGroup atom_grp("CH2"); - Atom atom1(Element::H, 0.0, 0.0, 0.0); Atom atom2(Element::H, 2.0, 0.0, 0.0); Atom atom3(Element::C, 1.0, 1.0, 0.0); @@ -26,18 +24,18 @@ TEST_CASE("Atom Group Container","[unit]") { auto atom2_ptr = std::make_shared(atom2); auto atom3_ptr = std::make_shared(atom3); - atom_grp.add(atom1_ptr); - atom_grp.add(atom2_ptr); - atom_grp.add(atom3_ptr); + AtomGroup atom_grp1("CH2"); + atom_grp1.add(atom1_ptr); + atom_grp1.add(atom2_ptr); + atom_grp1.add(atom3_ptr); - AtomGroup atom_grp2("O2"); - - Atom atom4(Element::O, 3.3, 4.3); - Atom atom5(Element::O, 3.0, 3.9); + Atom atom4(Element::O, 3.3, 4.3, 0.0); + Atom atom5(Element::O, 3.0, 3.9, 0.0); auto atom4_ptr = std::make_shared(atom4); auto atom5_ptr = std::make_shared(atom5); + AtomGroup atom_grp2("O2"); atom_grp2.add(atom4_ptr); atom_grp2.add(atom5_ptr); @@ -49,4 +47,37 @@ TEST_CASE("Atom Group Container","[unit]") { REQUIRE(atom_grp_cont.size() == 2); atom_grp_cont.assignGroupTypes(); + + // Because it made a copy these should still be unassigned + REQUIRE(atom_grp1.getType() == GroupType::Unassigned); + REQUIRE(atom_grp2.getType() == GroupType::Unassigned); + + // These should be changed + REQUIRE(atom_grp_cont.getType(0) == GroupType::Unit); + REQUIRE(atom_grp_cont.getType(1) == GroupType::Unit); + REQUIRE(atom_grp_cont.exists(GroupType::Unit)); + + // Now we make a third group that has all the atoms of the first two groups + AtomGroup atom_grp3("O2CH2"); + atom_grp3.add(atom1_ptr); + atom_grp3.add(atom2_ptr); + atom_grp3.add(atom3_ptr); + atom_grp3.add(atom4_ptr); + atom_grp3.add(atom5_ptr); + + atom_grp_cont.add(atom_grp3); + + REQUIRE(atom_grp_cont.getType(0) == GroupType::Unassigned); + REQUIRE(atom_grp_cont.getType(1) == GroupType::Unassigned); + REQUIRE(atom_grp_cont.getType(2) == GroupType::Unassigned); + REQUIRE(atom_grp_cont.exists(GroupType::Unassigned)); + + atom_grp_cont.assignGroupTypes(); + REQUIRE(atom_grp_cont.getType(0) == GroupType::Component); + REQUIRE(atom_grp_cont.getType(1) == GroupType::Component); + REQUIRE(atom_grp_cont.getType(2) == GroupType::Complex); + + REQUIRE(atom_grp_cont.exists(GroupType::Complex)); + REQUIRE(atom_grp_cont.exists(GroupType::Component)); + } From 61b82171e5159f0d812f287d816a35989bac3fe0 Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Sat, 18 Jul 2020 08:48:23 -0600 Subject: [PATCH 44/68] Added atom_system for handling basis functions and other improvements --- src/libcatnip/atom_group.cpp | 4 +- src/libcatnip/atom_group.hpp | 11 +- src/libcatnip/atom_group_container.cpp | 275 ++++++++---------------- src/libcatnip/atom_group_container.hpp | 70 +++--- src/libcatnip/atom_system.cpp | 193 +++++++++++++++++ src/libcatnip/atom_system.hpp | 62 ++++++ src/libcatnip/index_map.cpp | 25 ++- src/libcatnip/index_map.hpp | 6 +- src/tests/test_atom_group_container.cpp | 16 +- 9 files changed, 408 insertions(+), 254 deletions(-) create mode 100644 src/libcatnip/atom_system.cpp create mode 100644 src/libcatnip/atom_system.hpp diff --git a/src/libcatnip/atom_group.cpp b/src/libcatnip/atom_group.cpp index 618bff0..dda5d71 100644 --- a/src/libcatnip/atom_group.cpp +++ b/src/libcatnip/atom_group.cpp @@ -7,10 +7,10 @@ namespace catnip { - std::vector AtomGroup::find(std::shared_ptr atom) { + std::vector AtomGroup::find(std::shared_ptr atom) const { std::vector indices; int index = 0; - for ( std::shared_ptr & atom_ : atoms_){ + for ( const std::shared_ptr & atom_ : atoms_){ if ( *atom_ == (*atom)){ indices.push_back(index); } diff --git a/src/libcatnip/atom_group.hpp b/src/libcatnip/atom_group.hpp index db2a4d2..520b6a2 100644 --- a/src/libcatnip/atom_group.hpp +++ b/src/libcatnip/atom_group.hpp @@ -25,7 +25,7 @@ namespace catnip { * * Complex - all atoms in this atom group have a matching atom in a component * - * Unit - non of the atoms appear in any of the other atom groups + * Island - non of the atoms appear in any of the other atom groups * * Unknown - some combination, may or may not have overlapping components * @@ -34,7 +34,7 @@ namespace catnip { enum class GroupType { Component, Complex, - Unit, + Island, Unknown, Unassigned }; @@ -72,6 +72,10 @@ namespace catnip { return atoms_.at(ind); } + std::shared_ptr & at(size_t ind) { + return atoms_.at(ind); + } + void add(std::shared_ptr atom){ atoms_.push_back(atom); } @@ -93,8 +97,7 @@ namespace catnip { * * @return indeces of atoms that match */ - std::vector find(std::shared_ptr atom); - + std::vector find(std::shared_ptr atom) const; /** * @brief Finds the exact matching atom in memory by looking at the address diff --git a/src/libcatnip/atom_group_container.cpp b/src/libcatnip/atom_group_container.cpp index 8e29402..093d3ac 100644 --- a/src/libcatnip/atom_group_container.cpp +++ b/src/libcatnip/atom_group_container.cpp @@ -19,114 +19,18 @@ namespace catnip { - void AtomGroupContainer::assignBasisFuncCountToComplex_(const std::vector& complex_basis_func_count) { - // Cycle through the atoms in the complex and assign the correct number of - // basis functions - int index = 0; - for( std::shared_ptr & atom_ptr : atom_groups_.at(index_of_complex_) ){ - atom_ptr->setBasisFuncCount(complex_basis_func_count.at(index)); - index++; - } - } - - // Assumes the complex atoms already have been assigned the basis functioncount - void AtomGroupContainer::assignBasisFuncCountToComponents_() { - std::vector paired_atoms = matchComponentAtomsToComplex_(); - for ( AtomMatch atom_match : paired_atoms ) { - int basis_func_count = atom_groups_.at(index_of_complex_).at(atom_match.index_complex_atom)->getBasisFuncCount(); - atom_groups_.at(atom_match.index_component).at(atom_match.index_component_atom)->setBasisFuncCount(basis_func_count); - } - } - - std::vector AtomGroupContainer::getGroups(const GroupType & type) const { - std::vector groups; - int ind1 = 0; - for( const AtomGroup & group : atom_groups_ ){ - if( group.getType() == type){ - groups.push_back(ind1); - } - ++ind1; - } - return groups; - } - std::unordered_map AtomGroupContainer::matchAtoms_( - const AtomGroup & grp1, const AtomGroup & grp2) const { - - std::unordered_map paired_atoms; - for ( size_t ind1 = 0; ind1 < grp1.size(); ++ind1){ - for (size_t ind2 = 0; ind2 < grp2.size(); ++ind2){ - if ( *(grp1.at(ind1)) == *(grp2.at(ind2)) ){ - if ( paired_atoms.count(ind1) ) { - throw std::runtime_error("Atom in complex has already been paired with an atom in the component, you have two or more atoms in a component that are redundant with an atom in the complex"); - } - paired_atoms[ind1] = ind2; - break; - } - } - } - return paired_atoms; - } - - - bool AtomGroupContainer::isUniqueGroup_( const AtomGroup & atom_group ) const { - // Step 1 check the size of the atom group - if(atom_groups_.size() == 0) return true; - - for ( const AtomGroup & grp : atom_groups_ ){ - if ( grp.size() == atom_group.size() ){ - std::vector matchs(grp.size(),false); - // Determine if a match is found - for ( const auto & atm : atom_group ) { - size_t index = 0; - for ( bool matched : matchs ){ - if ( not matched ){ - // Compare atoms - if ( *atm == *(grp.at(index)) ){ - matchs.at(index) = true; - break; - } - } - ++index; - } - // If an atom was not matched it means that there is at least one - // difference, and so we do not need to cycle through the other - // atoms in this particular group - if(index == grp.size()) break; - } - // Count the number of matches in the vector if all of the elements match - // then the atom group is not unique - for ( bool match : matchs ) { - if ( match == false ) break; - } - return false; - } - } - return true; - } - // As soon as we add a new atom group it should invalidate the labels on - // all the other groups - void AtomGroupContainer::add( AtomGroup atom_group ) { - std::cout << "Adding group " << atom_group.getName() << std::endl; - if( isUniqueGroup_(atom_group) ){ - std::cout << "Is unique" << std::endl; - atom_groups_.push_back(atom_group); - } else { - return; - } - - for ( AtomGroup & grp : atom_groups_ ){ - grp.setType(GroupType::Unassigned); - } - group_types_uptodate_ = false; - index_of_complex_ = -1; - } - + /**************************************************************************** + * Local private structs + ****************************************************************************/ struct GroupAtomIndex { int atm_ind; int grp_ind; }; - static std::unordered_map> mapAtomsToGroups( + /**************************************************************************** + * Local private functions + ****************************************************************************/ + static std::unordered_map> mapAtomsToGroups_( const std::vector & atom_groups_ ){ std::unordered_map> atm_map; @@ -142,7 +46,7 @@ namespace catnip { return atm_map; } - static const std::map> calculateConnectedGroups( + static const std::map> calculateConnectedGroups_( std::unordered_map> atm_map, const std::vector & atom_groups_ ){ @@ -172,19 +76,19 @@ namespace catnip { return grp_indices; } - static void identifyAtomGroupsOfUnitType( + static void identifyAtomGroupsOfIslandType_( const std::map> & grp_indices, std::vector & atom_groups_ ) { for ( std::pair> grp_groups : grp_indices){ if(grp_groups.second.size() == 0) { std::cout << "Empty makeing unit, does not share atoms" << std::endl; - atom_groups_.at(grp_groups.first).setType(GroupType::Unit); + atom_groups_.at(grp_groups.first).setType(GroupType::Island); } } } - static void identifyAtomGroupsOfComponentComplexAndUnknownTypes( + static void identifyAtomGroupsOfComponentComplexAndUnknownTypes_( const std::map> & grp_indices, std::vector & atom_groups_ ){ @@ -219,61 +123,93 @@ namespace catnip { } } } -// Create a map with an atom as the key and a vector of indices to indicate -// where there is overlap, the group and index of where the overlap occurs - void AtomGroupContainer::assignGroupTypes(){ - std::cout << "Assigning group types" << std::endl; - std::unordered_map> atm_map = mapAtomsToGroups( atom_groups_ ); - - std::cout << "Size of atom map " << atm_map.size() << std::endl; - // For each atom in a group find out how many other groups share the atoms - // First index is the group index the vector stores the other groups that - // share atoms - const std::map> grp_indices = calculateConnectedGroups(atm_map, atom_groups_ ); + /**************************************************************************** + * Private Methods + ****************************************************************************/ + bool AtomGroupContainer::isUniqueGroup_( const AtomGroup & atom_group ) const { + // Step 1 check the size of the atom group + if(atom_groups_.size() == 0) return true; - for ( const auto & pr : grp_indices ) { - std::cout << "group " << pr.first << std::endl; - for ( auto ind : pr.second ){ - std::cout << "Atoms shared with group " << ind << std::endl; + for ( const AtomGroup & grp : atom_groups_ ){ + if ( grp.size() == atom_group.size() ){ + std::vector matchs(grp.size(),false); + // Determine if a match is found + for ( const auto & atm : atom_group ) { + size_t index = 0; + for ( bool matched : matchs ){ + if ( not matched ){ + // Compare atoms + if ( *atm == *(grp.at(index)) ){ + matchs.at(index) = true; + break; + } + } + ++index; + } + // If an atom was not matched it means that there is at least one + // difference, and so we do not need to cycle through the other + // atoms in this particular group + if(index == grp.size()) break; + } + // Count the number of matches in the vector if all of the elements match + // then the atom group is not unique + for ( bool match : matchs ) { + if ( match == false ) break; + } + return false; } } - // Calculate which groups do not share atoms with other groups these are units - identifyAtomGroupsOfUnitType(grp_indices, atom_groups_); + return true; + } - for ( const auto & pr : grp_indices ) { - std::cout << "group " << pr.first << std::endl; - for ( auto ind : pr.second ){ - std::cout << "Atoms shared with group " << ind << std::endl; + /**************************************************************************** + * Public Methods + ****************************************************************************/ + + std::vector AtomGroupContainer::getGroups(const GroupType & type) const noexcept{ + std::vector groups; + int ind1 = 0; + for( const AtomGroup & group : atom_groups_ ){ + if( group.getType() == type){ + groups.push_back(ind1); } + ++ind1; } - identifyAtomGroupsOfComponentComplexAndUnknownTypes(grp_indices,atom_groups_ ); + return groups; } - int AtomGroupContainer::getTotalBasisFunctions(const GroupType & type) const { - int total_num_basis = 0; - std::vector group_indices = getGroups(type); - for ( int ind : group_indices ){ - AtomGroup group = atom_groups_.at(ind); - for( const std::shared_ptr & atom_ptr : group ) { - total_num_basis += atom_ptr->getBasisFuncCount(); - } - } - return total_num_basis; + // As soon as we add a new atom group it should invalidate the labels on + // all the other groups + void AtomGroupContainer::add( AtomGroup atom_group ) { + std::cout << "Adding group " << atom_group.getName() << std::endl; + if( isUniqueGroup_(atom_group) ){ + std::cout << "Is unique" << std::endl; + atom_groups_.push_back(atom_group); + } else { + return; + } + + group_types_uptodate_ = false; } - int AtomGroupContainer::getMaxBasisFunctions(const GroupType & type) const { - int max_num_basis = 0; - std::vector group_indices = getGroups(type); - for ( int ind : group_indices ){ - AtomGroup group = atom_groups_.at(ind); - for( const std::shared_ptr & atom_ptr : group ) { - if( atom_ptr->getBasisFuncCount() > max_num_basis){ - max_num_basis = atom_ptr->getBasisFuncCount(); - } - } - } - return max_num_basis; +// Create a map with an atom as the key and a vector of indices to indicate +// where there is overlap, the group and index of where the overlap occurs + void AtomGroupContainer::assignGroupTypes(){ + + // If already uptodate do nothing + if( group_types_uptodate_ ) return; + std::unordered_map> atm_map = mapAtomsToGroups_( atom_groups_ ); + + // For each atom in a group find out how many other groups share the atoms + // First index is the group index the vector stores the other groups that + // share atoms + const std::map> grp_indices = calculateConnectedGroups_(atm_map, atom_groups_ ); + + // Calculate which groups do not share atoms with other groups these are units + identifyAtomGroupsOfIslandType_(grp_indices, atom_groups_); + + identifyAtomGroupsOfComponentComplexAndUnknownTypes_(grp_indices,atom_groups_ ); } bool AtomGroupContainer::exists(GroupType type) const { @@ -284,41 +220,4 @@ namespace catnip { return false; } - std::vector AtomGroupContainer::matchComponentAtomsToComplex_(){ - - AtomGroup complex_group = atom_groups_.at(index_of_complex_); - std::vector component_indices = getGroups(GroupType::Component); - std::vector all_paired_atoms; - for ( const int & component_index : component_indices ) { - std::unordered_map paired_atoms = matchAtoms_(complex_group,atom_groups_.at(component_index)); - // Pass to vector - for ( auto pr : paired_atoms ){ - AtomMatch atom_match; - atom_match.index_component = component_index; - atom_match.index_component_atom = pr.second; - atom_match.index_complex_atom = pr.first; - all_paired_atoms.push_back(atom_match); - } - } - return all_paired_atoms; - } - - void AtomGroupContainer::assignBasisFunctions( - const std::vector& complex_basis_func_count) { - - // 1. Check that up to date - if ( group_types_uptodate_ == false ){ - throw std::runtime_error("Cannot assign basis functions to atoms as group types are not up to date!"); - } - // 2. Check that the number of atoms in the complex is consistent with the number of values provided - if ( complex_basis_func_count.size() != atom_groups_.at(index_of_complex_).size() ){ - throw std::runtime_error("Cannot assign basis function count to atoms as the basis function count vector is not equal to the number of atoms!"); - } - - assignBasisFuncCountToComplex_(complex_basis_func_count); - assignBasisFuncCountToComponents_(); - - } - - } // namespace catnip diff --git a/src/libcatnip/atom_group_container.hpp b/src/libcatnip/atom_group_container.hpp index d2b8b32..c57fb0b 100644 --- a/src/libcatnip/atom_group_container.hpp +++ b/src/libcatnip/atom_group_container.hpp @@ -19,11 +19,13 @@ namespace catnip { - class Atom; - - /// What we need is a function that will actually create the atom group - /// container so that the state is known, basically you need to pass in the - /// a vector of the atom groups + /** + * @brief Allows auto detection of atom groups + * + * What this means is that if you pass in atom groups and thier state is not + * known, this class can automatically detect if they are related, if they + * are an island a complex or a component. + */ class AtomGroupContainer { std::vector atom_groups_; @@ -40,29 +42,25 @@ namespace catnip { */ bool isUniqueGroup_( const AtomGroup & atom_group ) const; - /** - * @brief Match the indices of the first atom group with any that share - * coordinates and the same element in atom group 2 - * - * @param grp1 - * @param grp2 - * - * @return map returns indices in group two that match group 1 - */ - std::unordered_map matchAtoms_( const AtomGroup & grp1, const AtomGroup & grp2) const; - void assignBasisFuncCountToComplex_(const std::vector& complex_basis_func_count); - void assignBasisFuncCountToComponents_(); + public: + + // Invalidates groups if non const because cannot ensure that groups are + // not changed + std::vector::iterator + begin() { group_types_uptodate_ = false; return atom_groups_.begin(); } - struct AtomMatch { - int index_component; - int index_component_atom; - int index_complex_atom; - }; + std::vector::const_iterator + begin() const { return atom_groups_.begin(); } + + // Invalidates groups if non const because cannot ensure that groups are + // not changed + std::vector::iterator + end() { group_types_uptodate_ = false; return atom_groups_.end(); } + + std::vector::const_iterator + end() const { return atom_groups_.end(); } - std::vector matchComponentAtomsToComplex_(); - int index_of_complex_ = -1; - public: void add( AtomGroup atom_group ); size_t size() const noexcept { return atom_groups_.size(); } @@ -72,6 +70,8 @@ namespace catnip { */ void assignGroupTypes(); + bool isUpToDate() const noexcept { return group_types_uptodate_; } + /** * @brief Determine if a specified group type exists within the atom groups * @@ -80,18 +80,7 @@ namespace catnip { bool exists(GroupType type) const; GroupType getType(int index) const { return atom_groups_.at(index).getType(); } - /** - * @brief If a complex exists and we know the number of basis functions - * associated with each atom in the complex we can assign the basis function - * number to each of the atoms - * - * @param complex_basis_func_count - */ - void assignBasisFunctions(const std::vector& complex_basis_func_count); - - int getTotalBasisFunctions(const GroupType & type) const; - int getMaxBasisFunctions(const GroupType & type) const; /** * @brief Get the indices of all the groups of the specified group type * @@ -99,9 +88,14 @@ namespace catnip { * * @return */ - std::vector getGroups(const GroupType & type) const; + std::vector getGroups(const GroupType & type) const noexcept; + + AtomGroup & at(size_t ind) { + group_types_uptodate_ = false; + return atom_groups_.at(ind); + } - AtomGroup & at(size_t ind) { return atom_groups_.at(ind);} + const AtomGroup & at(size_t ind) const { return atom_groups_.at(ind);} }; diff --git a/src/libcatnip/atom_system.cpp b/src/libcatnip/atom_system.cpp new file mode 100644 index 0000000..66095d3 --- /dev/null +++ b/src/libcatnip/atom_system.cpp @@ -0,0 +1,193 @@ + +// Local private includes +#include "atom_system.hpp" + +#include "atom.hpp" + +// Standard includes +#include +#include + +namespace catnip { + + /**************************************************************************** + * Local private structs + ****************************************************************************/ +/* struct AtomMatch { + int index_component; + int index_component_atom; + int index_complex_atom; + };*/ + + /**************************************************************************** + * Local private functions + ****************************************************************************/ + + static void assignBasisFuncs_( + int grp_ind, + const std::vector& basis_func_count, + AtomGroupContainer & atm_grp_cont) { + // Cycle through the atoms in the complex and assign the correct number of + // basis functions + int index = 0; + for( std::shared_ptr & atom_ptr : atm_grp_cont.at(grp_ind) ){ + if( atom_ptr->getBasisFuncCount() == -1){ + atom_ptr->setBasisFuncCount(basis_func_count.at(index)); + } else if(atom_ptr->getBasisFuncCount() != basis_func_count.at(index) ){ + // Make sure the new assignment is consistent with the old one + // if not throw an error, because you have a conflicting number of basis + // functions between groups + throw std::runtime_error("Inconsistency detected in the number of " + "basis functions detected between atom groups. Ensure that the " + "basis function count vector is in a consistent order with the " + "atoms in the atom group"); + } + index++; + } + } +/* + static std::vector matchComponentAtomsToComplex_(){ + + AtomGroup complex_group = atom_groups_.at(index_of_complex_); + std::vector component_indices = getGroups(GroupType::Component); + std::vector all_paired_atoms; + for ( const int & component_index : component_indices ) { + std::unordered_map paired_atoms = matchAtoms_(complex_group,atom_groups_.at(component_index)); + // Pass to vector + for ( auto pr : paired_atoms ){ + AtomMatch atom_match; + atom_match.index_component = component_index; + atom_match.index_component_atom = pr.second; + atom_match.index_complex_atom = pr.first; + all_paired_atoms.push_back(atom_match); + } + } + return all_paired_atoms; + }*/ + + static void checkValidSystemCriteria_(AtomGroupContainer & atm_grp_cont){ + std::vector complex_indices = + atm_grp_cont.getGroups(GroupType::Complex); + + if( complex_indices.size() == 0 ){ + throw std::runtime_error("Cannot create atom system, no complexes were " + "found in the atom group container."); + } else if( complex_indices.size() > 1 ){ + throw std::runtime_error("Cannot create atom system, several complexes " + "were found in the atom group. The atom system can only contain a " + "single complex."); + } + + std::vector component_indices = + atm_grp_cont.getGroups(GroupType::Component); + + if ( component_indices.size() < 2){ + throw std::runtime_error("Cannot create atom system, must contain at " + "least two components"); + } + } + + static void synchroniseAtoms_(AtomGroupContainer & atm_grp_cont){ + + // Overwrite any of the pointers in the component that have the same atom + // with the complex, with the atom pointer from the complex + int complex_index = + atm_grp_cont.getGroups(GroupType::Complex).at(0); + + std::vector component_indices = + atm_grp_cont.getGroups(GroupType::Component); + + AtomGroup & atm_complex = atm_grp_cont.at(complex_index); + for ( const int component_ind : component_indices){ + AtomGroup & atm_grp = atm_grp_cont.at(component_ind); + // Cycle atoms in atm_grp + for ( std::shared_ptr & atm : atm_grp){ + std::vector complex_atm_ind = atm_complex.find(atm); + // This vector should be 0 or 1 + if( complex_atm_ind.size() == 1){ + // Change the pointer + atm = atm_complex.at(complex_atm_ind.at(0)); + } + } + } + } + /**************************************************************************** + * Public Methods + ****************************************************************************/ + + /** + * @brief Creates an atom system if possible + * + * The criteria to create an atom system is that the AtomGroupContainer must + * contain only a single complex and the components that belong to that + * complex + * + * @param atm_grp_cont + */ + AtomSystem::AtomSystem(AtomGroupContainer atm_grp_cont) { + atm_grp_cont.assignGroupTypes(); + + checkValidSystemCriteria_(atm_grp_cont); + + // Make atoms consistent between components and the complex, this is done + // by making atoms that share the same location point to the same place + // in memory + synchroniseAtoms_(atm_grp_cont); + + atm_grp_cont_ = atm_grp_cont; + } + + int AtomSystem::getTotalBasisFunctions(const GroupType & type) const { + int total_num_basis = 0; + std::vector group_indices = atm_grp_cont_.getGroups(type); + for ( int ind : group_indices ){ + const AtomGroup & group = atm_grp_cont_.at(ind); + for( const std::shared_ptr & atom_ptr : group ) { + total_num_basis += atom_ptr->getBasisFuncCount(); + } + } + return total_num_basis; + } + + int AtomSystem::getMaxBasisFunctions(const GroupType & type) const { + int max_num_basis = 0; + std::vector group_indices = atm_grp_cont_.getGroups(type); + for ( int ind : group_indices ){ + const AtomGroup & group = atm_grp_cont_.at(ind); + for( const std::shared_ptr & atom_ptr : group ) { + if( atom_ptr->getBasisFuncCount() > max_num_basis){ + max_num_basis = atom_ptr->getBasisFuncCount(); + } + } + } + return max_num_basis; + } + + + void AtomSystem::assignBasisFunctions(int index, + const std::vector& basis_func_count) { + + // 2. Check that the number of atoms in the grp is consistent with + // the number of values provided + if ( basis_func_count.size() != atm_grp_cont_.at(index).size() ){ + throw std::runtime_error("Cannot assign basis function count to atoms " + "as the basis function count vector is not equal to the number of " + "atoms in the group!"); + } + + assignBasisFuncs_(index, basis_func_count, atm_grp_cont_); + } + + bool AtomSystem::systemComplete() const noexcept { + for ( const AtomGroup & grp : atm_grp_cont_){ + for( const std::shared_ptr & atm : grp){ + if(atm->getBasisFuncCount() == -1) return false; + } + } + return true; + } + + const AtomGroup & AtomSystem::at(int ind) const { + return atm_grp_cont_.at(ind); + } +} diff --git a/src/libcatnip/atom_system.hpp b/src/libcatnip/atom_system.hpp new file mode 100644 index 0000000..65ae8f4 --- /dev/null +++ b/src/libcatnip/atom_system.hpp @@ -0,0 +1,62 @@ + +#pragma once +#ifndef CATNIP_ATOM_SYSTEM_HPP +#define CATNIP_ATOM_SYSTEM_HPP +#include "atom_group_container.hpp" + +namespace catnip { + + /** + * @brief Unlike atom group container, this atom system does not allow to + * change group types + * + * It can only be created if there are known group types and there is only + * a single complex, and it's components + */ + class AtomSystem { + + AtomGroupContainer atm_grp_cont_; + public: + + AtomSystem(AtomGroupContainer atm_cont); + + /** + * @brief assign basis functions to atom group + * + * @param complex_basis_func_count + */ + void assignBasisFunctions(int index, const std::vector& basis_funcs); + + /** + * @brief Determine if there is a conflict between the basis functions + * you are attempting to assign and the currently assigned basis functions + * + * This is done by comparing the basis functions on atoms that shared + * between atom groups. + * + * @param index + * @param basis_funcs + * + * @return + */ + bool conflictBasisFunctions(int index, const std::vector & basis_funcs) const; + + int getTotalBasisFunctions(const GroupType & type) const; + + int getMaxBasisFunctions(const GroupType & type) const; + + const AtomGroup & getComplex() const; + std::vector getComponentIndices() const noexcept { atm_grp_cont_.getGroups(GroupType::Component);} + const AtomGroup & at(int ind) const; + /** + * @brief Check that every atom knows how many basis functions are + * assigned to it + * + * @return + */ + bool systemComplete() const noexcept; + } + +}; + +#endif // CATNIP_ATOM_SYSTEM_HPP diff --git a/src/libcatnip/index_map.cpp b/src/libcatnip/index_map.cpp index 3d4ad28..c6a132d 100644 --- a/src/libcatnip/index_map.cpp +++ b/src/libcatnip/index_map.cpp @@ -10,21 +10,20 @@ namespace catnip { - IndexMap::IndexMap(AtomGroupContainer atom_groups){ - std::vector group_indices = atom_groups.getGroups(GroupType::Component); - int complex_ind = atom_groups.getGroups(GroupType::Complex).at(0); - AtomGroup complex_group = atom_groups.at(complex_ind); + IndexMap::IndexMap(AtomSystem atm_sys){ + std::vector comp_indices = atm_sys.getComponentIndices(); + const AtomGroup & complex_grp = atm_sys.getComplex(); int sys_ind = 0; - for ( int & group_ind : group_indices) { - AtomGroup component_group = atom_groups.at(group_ind); - for( std::shared_ptr & atom : component_group){ - std::vector atom_indices = complex_group.find(atom); - assert(atom_indices.size() == 1); - int atom_ind = atom_indices.at(0); - int num_basis = complex_group.at(atom_ind)->getBasisFuncCount(); + for ( int & comp_ind : comp_indices) { + const AtomGroup & comp_grp = atm_sys.at(comp_ind); + for( const std::shared_ptr & atm_ptr : comp_grp){ + std::vector atm_indices = complex_grp.find(atm_ptr); + assert(atm_indices.size() == 1); + int atm_ind = atm_indices.at(0); + int num_basis = comp_grp.at(atm_ind)->getBasisFuncCount(); for ( int ind_temp = 0; ind_temp @@ -15,13 +15,13 @@ namespace catnip { class IndexMap { public: IndexMap() = default; - IndexMap(AtomGroupContainer atom_groups); + IndexMap(AtomSystem atm_sys); // The component rows and colums in their current locations in // in the full system matrix of the complex std::map> row_col_init; // Map indicate where the rows and cols should go in the final state - // Each int in the vector represents the locatin in the full system matrix + // Each int in the vector represents the location in the full system matrix std::map> row_col_final; // Searches the init row for the provided row and returns the group it is diff --git a/src/tests/test_atom_group_container.cpp b/src/tests/test_atom_group_container.cpp index d5b1dff..db95cea 100644 --- a/src/tests/test_atom_group_container.cpp +++ b/src/tests/test_atom_group_container.cpp @@ -46,16 +46,20 @@ TEST_CASE("Atom Group Container","[unit]") { REQUIRE(atom_grp_cont.size() == 2); - atom_grp_cont.assignGroupTypes(); + REQUIRE(atom_grp_cont.getType(0) == GroupType::Unassigned); + REQUIRE(atom_grp_cont.getType(1) == GroupType::Unassigned); + REQUIRE(atom_grp_cont.isUpToDate() == false); + atom_grp_cont.assignGroupTypes(); + REQUIRE(atom_grp_cont.isUpToDate() == true); // Because it made a copy these should still be unassigned REQUIRE(atom_grp1.getType() == GroupType::Unassigned); REQUIRE(atom_grp2.getType() == GroupType::Unassigned); // These should be changed - REQUIRE(atom_grp_cont.getType(0) == GroupType::Unit); - REQUIRE(atom_grp_cont.getType(1) == GroupType::Unit); - REQUIRE(atom_grp_cont.exists(GroupType::Unit)); + REQUIRE(atom_grp_cont.getType(0) == GroupType::Island); + REQUIRE(atom_grp_cont.getType(1) == GroupType::Island); + REQUIRE(atom_grp_cont.exists(GroupType::Island)); // Now we make a third group that has all the atoms of the first two groups AtomGroup atom_grp3("O2CH2"); @@ -66,13 +70,13 @@ TEST_CASE("Atom Group Container","[unit]") { atom_grp3.add(atom5_ptr); atom_grp_cont.add(atom_grp3); + REQUIRE(atom_grp_cont.isUpToDate() == false); - REQUIRE(atom_grp_cont.getType(0) == GroupType::Unassigned); - REQUIRE(atom_grp_cont.getType(1) == GroupType::Unassigned); REQUIRE(atom_grp_cont.getType(2) == GroupType::Unassigned); REQUIRE(atom_grp_cont.exists(GroupType::Unassigned)); atom_grp_cont.assignGroupTypes(); + REQUIRE(atom_grp_cont.isUpToDate() == true); REQUIRE(atom_grp_cont.getType(0) == GroupType::Component); REQUIRE(atom_grp_cont.getType(1) == GroupType::Component); REQUIRE(atom_grp_cont.getType(2) == GroupType::Complex); From 7c4ac40a6c28e392f215e6afc9cdbb3cae5c2d8c Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Sun, 19 Jul 2020 18:17:35 -0600 Subject: [PATCH 45/68] Make handling of basis function assignment more refined, and add checks --- src/libcatnip/atom_group.cpp | 12 +++ src/libcatnip/atom_group.hpp | 14 ++++ src/libcatnip/atom_system.cpp | 152 ++++++++++++++++++++++++++++++++-- src/libcatnip/atom_system.hpp | 25 ++++-- 4 files changed, 191 insertions(+), 12 deletions(-) diff --git a/src/libcatnip/atom_group.cpp b/src/libcatnip/atom_group.cpp index dda5d71..b910eab 100644 --- a/src/libcatnip/atom_group.cpp +++ b/src/libcatnip/atom_group.cpp @@ -7,6 +7,18 @@ namespace catnip { + std::vector AtomGroup::find(const Eigen::Vector3d pos) const { + std::vector indices; + int index = 0; + for ( const std::shared_ptr & atom_ : atoms_){ + if ( atom_->getPos().isApprox( pos )){ + indices.push_back(index); + } + ++index; + } + return indices; + } + std::vector AtomGroup::find(std::shared_ptr atom) const { std::vector indices; int index = 0; diff --git a/src/libcatnip/atom_group.hpp b/src/libcatnip/atom_group.hpp index 520b6a2..badacf3 100644 --- a/src/libcatnip/atom_group.hpp +++ b/src/libcatnip/atom_group.hpp @@ -84,6 +84,10 @@ namespace catnip { atoms_.insert(atoms_.end(),atoms.begin(),atoms.end()); } + bool is(const GroupType & type) const noexcept { + return type == type_; + } + void setType(const GroupType & type) noexcept { type_ = type; } @@ -99,6 +103,16 @@ namespace catnip { */ std::vector find(std::shared_ptr atom) const; + /** + * @brief Find the index of the atom in the group if it shares the provided + * position + * + * @param pos + * + * @return indeces of atoms that match the position + */ + std::vector find(const Eigen::Vector3d pos) const; + /** * @brief Finds the exact matching atom in memory by looking at the address * diff --git a/src/libcatnip/atom_system.cpp b/src/libcatnip/atom_system.cpp index 66095d3..d2ed4e1 100644 --- a/src/libcatnip/atom_system.cpp +++ b/src/libcatnip/atom_system.cpp @@ -22,15 +22,15 @@ namespace catnip { /**************************************************************************** * Local private functions ****************************************************************************/ - - static void assignBasisFuncs_( - int grp_ind, + + static AtomGroup & assignBasisFunctionsToSynchronisedAtoms_( + int grp_ind, const std::vector& basis_func_count, - AtomGroupContainer & atm_grp_cont) { - // Cycle through the atoms in the complex and assign the correct number of - // basis functions + AtomGroup & grp, + AtomGroupContainer & atm_grp_cont ){ + int index = 0; - for( std::shared_ptr & atom_ptr : atm_grp_cont.at(grp_ind) ){ + for( std::shared_ptr & atom_ptr : grp ){ if( atom_ptr->getBasisFuncCount() == -1){ atom_ptr->setBasisFuncCount(basis_func_count.at(index)); } else if(atom_ptr->getBasisFuncCount() != basis_func_count.at(index) ){ @@ -44,6 +44,95 @@ namespace catnip { } index++; } + + } + + static void checkLinkedAtomsInComplexForConsistentBasisFunctionCounts( + int grp_ind, + const AtomGroup & grp, + AtomGroupContainer & atm_grp_cont, + std::map>> linked_atoms ){ + + for ( auto grp_linked_atms : linked_atoms ){ + const AtomGroup & component = atm_grp_cont.at(grp_linked_atms.first); + for( std::pair linked_atoms : grp_linked_atms.second ){ + if ( component.at(linked_atoms.first)->getBasisFuncCount() != -1){ + if ( component.at(linked_atoms.first)->getBasisFuncCount() != grp.at(linked_atoms.second)->getBasisFuncCount()){ + throw std::runtime_error("There are inconsistencies between the " + "the number of basis functions used in a linked atom. Atoms " + "in a component must contain the same number of basis " + "functions as thier linked atoms in the complex"); + } + } + } + } + } + + static void checkLinkedAtomsInComponentForConsistentBasisFunctionCounts( + int grp_ind, + const AtomGroup & grp, + AtomGroupContainer & atm_grp_cont, + std::map>> linked_atoms + ) { + + std::vector complex_grps = atm_grp_cont.getGroups(GroupType::Complex); + assert(complex_grps.size() == 1 && "There must be at least one complex"); + const AtomGroup & complex_grp = atm_grp_cont.at(complex_grps.at(0)); + for( std::pair linked_atoms : linked_atoms[grp_ind] ){ + if ( complex_grp.at(linked_atoms.first)->getBasisFuncCount() != -1){ + if ( complex_grp.at(linked_atoms.first)->getBasisFuncCount() != grp.at(linked_atoms.second)->getBasisFuncCount()){ + throw std::runtime_error("There are inconsistencies between the " + "the number of basis functions used in a linked atom. Atoms " + "in a component must contain the same number of basis " + "functions as thier linked atoms in the complex"); + } + } + } + } + + /** + * @brief Assigns basis function to atoms in group + * + * This fucntions should only be called after the atoms have been syncrhonized + * between atom groups + * + * @param grp_ind + * @param basis_func_count + * @param atm_grp_cont + */ + static void assignBasisFuncs_( + int grp_ind, + const std::vector& basis_func_count, + AtomGroupContainer & atm_grp_cont, + std::map>> linked_atoms + ) { + // Cycle through the atoms in the complex and assign the correct number of + // basis functions + + AtomGroup & grp = atm_grp_cont.at(grp_ind); + + assignBasisFunctionsToSynchronisedAtoms_( + grp_ind, + basis_func_count, + grp, + atm_grp_cont); + // Make sure that there are no inconsistencies between the linked atoms + if ( atm_grp_cont.at(grp_ind).is(GroupType::Complex)){ + // If it is a complex + checkLinkedAtomsInComplexForConsistentBasisFunctionCounts( + grp_ind, + grp, + atm_grp_cont, + linked_atoms); + + }else { + // If it is a component + checkLinkedAtomsInComponentForConsistentBasisFunctionCounts( + grp_ind, + grp, + atm_grp_cont, + linked_atoms); + } } /* static std::vector matchComponentAtomsToComplex_(){ @@ -87,6 +176,51 @@ namespace catnip { } } + // Map + // first int - index of the group + // first int of the pair - index of the atom in the component + // second int of the pair - index of the linked atom in the complex + static std::map>> findNonConsistentAtoms_( + AtomGroupContainer & atm_grp_cont) { + + std::map>> linked_atoms; + // Overwrite any of the pointers in the component that have the same atom + // with the complex, with the atom pointer from the complex + int complex_index = + atm_grp_cont.getGroups(GroupType::Complex).at(0); + + std::vector component_indices = + atm_grp_cont.getGroups(GroupType::Component); + + AtomGroup & atm_complex = atm_grp_cont.at(complex_index); + for ( const int component_ind : component_indices){ + AtomGroup & atm_grp = atm_grp_cont.at(component_ind); + // Cycle atoms in atm_grp + int ind_atm = 0; + for ( std::shared_ptr & atm : atm_grp){ + std::vector complex_atm_ind = atm_complex.find(atm->getPos()); + // This vector must be of size 1 + if( complex_atm_ind.size() == 1){ + // If the elements dont' match it is non-consistent + if( atm_complex.at(complex_atm_ind.at(0))->getElement() != atm_grp.at(ind_atm)->getElement() ){ + linked_atoms[component_ind].push_back(std::pair(ind_atm,complex_atm_ind.at(0))); + } + }else if (complex_atm_ind.size() == 0) { + throw std::runtime_error("A component atom did not have a matching " + "atom in the complex. The component atom does not have to have " + "the same element as the atom in the complex bust must share " + "the same position."); + } else { + throw std::runtime_error("A component atom matches more than a single" + " atom in the complex. There appears to be a problem with the " + "complex, as more than one atom occupies the same location."); + } + ++ind_atm; + } + } + return linked_atoms; + } + static void synchroniseAtoms_(AtomGroupContainer & atm_grp_cont){ // Overwrite any of the pointers in the component that have the same atom @@ -129,6 +263,10 @@ namespace catnip { checkValidSystemCriteria_(atm_grp_cont); + // Searches for atoms that exist in the component that share a position with + // an atom in the complex, but are of a different element + linked_atoms_ = findNonConsistentAtoms_(atm_grp_cont); + // Make atoms consistent between components and the complex, this is done // by making atoms that share the same location point to the same place // in memory diff --git a/src/libcatnip/atom_system.hpp b/src/libcatnip/atom_system.hpp index 65ae8f4..d3b37a5 100644 --- a/src/libcatnip/atom_system.hpp +++ b/src/libcatnip/atom_system.hpp @@ -2,8 +2,14 @@ #pragma once #ifndef CATNIP_ATOM_SYSTEM_HPP #define CATNIP_ATOM_SYSTEM_HPP + +// Local private includes #include "atom_group_container.hpp" +// Standard includes +#include +#include + namespace catnip { /** @@ -11,17 +17,26 @@ namespace catnip { * change group types * * It can only be created if there are known group types and there is only - * a single complex, and it's components + * a single complex, and it's components, + * + * Each atom in a component must only be shared with the complex, the atom of + * a component is allowed to be of a different element then what is in the + * complex, but must have the same position */ class AtomSystem { - + // Atoms in each component that share the same location with atoms in + // the complex but do not share the same element + std::map>> linked_atoms_; AtomGroupContainer atm_grp_cont_; public: AtomSystem(AtomGroupContainer atm_cont); /** - * @brief assign basis functions to atom group + * @brief assign basis functions to atom group + * + * Note that atoms that are linked between component and complex must + * have the exact same number of basis functions. * * @param complex_basis_func_count */ @@ -31,7 +46,7 @@ namespace catnip { * @brief Determine if there is a conflict between the basis functions * you are attempting to assign and the currently assigned basis functions * - * This is done by comparing the basis functions on atoms that shared + * This is done by comparing the basis functions on atoms that are shared * between atom groups. * * @param index @@ -55,7 +70,7 @@ namespace catnip { * @return */ bool systemComplete() const noexcept; - } + }; }; From a4a3ed47704f4fab64ec04f0c67ade59f5200901 Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Thu, 23 Jul 2020 13:02:42 -0600 Subject: [PATCH 46/68] Cleanup swap --- src/libcatnip/atom_group.hpp | 4 +- src/libcatnip/atom_group_container.cpp | 2 + src/libcatnip/atom_group_container.hpp | 2 +- src/libcatnip/atom_system.cpp | 49 +++++- src/libcatnip/atom_system.hpp | 29 +++- src/libcatnip/index_map.cpp | 47 ------ src/libcatnip/index_map.hpp | 34 ---- src/libcatnip/swap_engine.cpp | 218 ++++++++++++++++++++----- src/libcatnip/swap_engine.hpp | 13 +- src/libcatnip/transfer_complex.cpp | 12 +- src/libcatnip/transfer_complex.hpp | 12 +- src/tests/CMakeLists.txt | 6 +- src/tests/test_index_map.cpp | 16 -- 13 files changed, 270 insertions(+), 174 deletions(-) delete mode 100644 src/libcatnip/index_map.cpp delete mode 100644 src/libcatnip/index_map.hpp delete mode 100644 src/tests/test_index_map.cpp diff --git a/src/libcatnip/atom_group.hpp b/src/libcatnip/atom_group.hpp index badacf3..a47069e 100644 --- a/src/libcatnip/atom_group.hpp +++ b/src/libcatnip/atom_group.hpp @@ -68,11 +68,11 @@ namespace catnip { std::vector>::const_iterator end() const { return atoms_.end(); } - std::shared_ptr at(size_t ind) const { + std::shared_ptr & at(size_t ind) { return atoms_.at(ind); } - std::shared_ptr & at(size_t ind) { + const std::shared_ptr & at(size_t ind) const { return atoms_.at(ind); } diff --git a/src/libcatnip/atom_group_container.cpp b/src/libcatnip/atom_group_container.cpp index 093d3ac..4e88000 100644 --- a/src/libcatnip/atom_group_container.cpp +++ b/src/libcatnip/atom_group_container.cpp @@ -210,6 +210,8 @@ namespace catnip { identifyAtomGroupsOfIslandType_(grp_indices, atom_groups_); identifyAtomGroupsOfComponentComplexAndUnknownTypes_(grp_indices,atom_groups_ ); + + group_types_uptodate_ = true; } bool AtomGroupContainer::exists(GroupType type) const { diff --git a/src/libcatnip/atom_group_container.hpp b/src/libcatnip/atom_group_container.hpp index c57fb0b..5570655 100644 --- a/src/libcatnip/atom_group_container.hpp +++ b/src/libcatnip/atom_group_container.hpp @@ -79,7 +79,7 @@ namespace catnip { */ bool exists(GroupType type) const; - GroupType getType(int index) const { return atom_groups_.at(index).getType(); } + const GroupType & getType(int index) const { return atom_groups_.at(index).getType(); } /** * @brief Get the indices of all the groups of the specified group type diff --git a/src/libcatnip/atom_system.cpp b/src/libcatnip/atom_system.cpp index d2ed4e1..3d802b8 100644 --- a/src/libcatnip/atom_system.cpp +++ b/src/libcatnip/atom_system.cpp @@ -5,6 +5,7 @@ #include "atom.hpp" // Standard includes +#include #include #include @@ -23,7 +24,7 @@ namespace catnip { * Local private functions ****************************************************************************/ - static AtomGroup & assignBasisFunctionsToSynchronisedAtoms_( + static void assignBasisFunctionsToSynchronisedAtoms_( int grp_ind, const std::vector& basis_func_count, AtomGroup & grp, @@ -31,6 +32,7 @@ namespace catnip { int index = 0; for( std::shared_ptr & atom_ptr : grp ){ + std::cout << "Assigning basis function atom at index " << index << std::endl; if( atom_ptr->getBasisFuncCount() == -1){ atom_ptr->setBasisFuncCount(basis_func_count.at(index)); } else if(atom_ptr->getBasisFuncCount() != basis_func_count.at(index) ){ @@ -79,8 +81,8 @@ namespace catnip { assert(complex_grps.size() == 1 && "There must be at least one complex"); const AtomGroup & complex_grp = atm_grp_cont.at(complex_grps.at(0)); for( std::pair linked_atoms : linked_atoms[grp_ind] ){ - if ( complex_grp.at(linked_atoms.first)->getBasisFuncCount() != -1){ - if ( complex_grp.at(linked_atoms.first)->getBasisFuncCount() != grp.at(linked_atoms.second)->getBasisFuncCount()){ + if ( complex_grp.at(linked_atoms.second)->getBasisFuncCount() != -1){ + if ( complex_grp.at(linked_atoms.second)->getBasisFuncCount() != grp.at(linked_atoms.first)->getBasisFuncCount()){ throw std::runtime_error("There are inconsistencies between the " "the number of basis functions used in a linked atom. Atoms " "in a component must contain the same number of basis " @@ -110,7 +112,7 @@ namespace catnip { // basis functions AtomGroup & grp = atm_grp_cont.at(grp_ind); - + std::cout << "Assign to Synchronize atoms" << std::endl; assignBasisFunctionsToSynchronisedAtoms_( grp_ind, basis_func_count, @@ -119,6 +121,7 @@ namespace catnip { // Make sure that there are no inconsistencies between the linked atoms if ( atm_grp_cont.at(grp_ind).is(GroupType::Complex)){ // If it is a complex + std::cout << "Assign to Linked atoms in complex" << std::endl; checkLinkedAtomsInComplexForConsistentBasisFunctionCounts( grp_ind, grp, @@ -127,6 +130,7 @@ namespace catnip { }else { // If it is a component + std::cout << "Assign to Linked atoms in component" << std::endl; checkLinkedAtomsInComponentForConsistentBasisFunctionCounts( grp_ind, grp, @@ -206,10 +210,12 @@ namespace catnip { linked_atoms[component_ind].push_back(std::pair(ind_atm,complex_atm_ind.at(0))); } }else if (complex_atm_ind.size() == 0) { - throw std::runtime_error("A component atom did not have a matching " - "atom in the complex. The component atom does not have to have " - "the same element as the atom in the complex bust must share " - "the same position."); + std::string error_msg = "A component atom did not have a matching " + "atom in the complex (" + atm_complex.getName() + "). The " + "atom in the component (" + atm_grp.getName() + ") does not have " + "to have the same element as the atom in the complex but must " + "share the same position."; + throw std::runtime_error(error_msg); } else { throw std::runtime_error("A component atom matches more than a single" " atom in the complex. There appears to be a problem with the " @@ -263,6 +269,9 @@ namespace catnip { checkValidSystemCriteria_(atm_grp_cont); + std::vector complex_indices = + atm_grp_cont.getGroups(GroupType::Complex); + index_complex_ = complex_indices.at(0); // Searches for atoms that exist in the component that share a position with // an atom in the complex, but are of a different element linked_atoms_ = findNonConsistentAtoms_(atm_grp_cont); @@ -313,7 +322,7 @@ namespace catnip { "atoms in the group!"); } - assignBasisFuncs_(index, basis_func_count, atm_grp_cont_); + assignBasisFuncs_(index, basis_func_count, atm_grp_cont_, linked_atoms_); } bool AtomSystem::systemComplete() const noexcept { @@ -328,4 +337,26 @@ namespace catnip { const AtomGroup & AtomSystem::at(int ind) const { return atm_grp_cont_.at(ind); } + + std::vector AtomSystem::getLinkedAtomsWithDifferentElements() const noexcept { + + std::vector links; + std::string complex_name = atm_grp_cont_.at(index_complex_).getName(); + for ( std::pair>> grp_links : linked_atoms_){ + int component_ind = grp_links.first; + std::string component_name = atm_grp_cont_.at(component_ind).getName(); + for ( std::pair atm1_atm2 : grp_links.second){ + Link link{ + component_name, // Component name + component_ind, // Component index + atm1_atm2.first, // Component atom index + complex_name, // Complex name + index_complex_, // Complex index + atm1_atm2.second }; // Complex atom index + + links.push_back(link); + } + } + return links; + } } diff --git a/src/libcatnip/atom_system.hpp b/src/libcatnip/atom_system.hpp index d3b37a5..2cfb1a7 100644 --- a/src/libcatnip/atom_system.hpp +++ b/src/libcatnip/atom_system.hpp @@ -28,8 +28,18 @@ namespace catnip { // the complex but do not share the same element std::map>> linked_atoms_; AtomGroupContainer atm_grp_cont_; + int index_complex_; public: + struct Link { + std::string component_name; + int component_ind; + int component_atm_ind; + std::string complex_name; + int complex_ind; + int complex_atm_ind; + }; + AtomSystem(AtomGroupContainer atm_cont); /** @@ -60,8 +70,23 @@ namespace catnip { int getMaxBasisFunctions(const GroupType & type) const; - const AtomGroup & getComplex() const; - std::vector getComponentIndices() const noexcept { atm_grp_cont_.getGroups(GroupType::Component);} + const AtomGroup & getComplex() const { + return atm_grp_cont_.at(index_complex_); + } + + std::vector getComponentIndices() const noexcept { + return atm_grp_cont_.getGroups(GroupType::Component); + } + + + /** + * @brief Gets atoms that are linked because they share the same position + * but don't share the same element + * + * @return + */ + std::vector getLinkedAtomsWithDifferentElements() const noexcept; + const AtomGroup & at(int ind) const; /** * @brief Check that every atom knows how many basis functions are diff --git a/src/libcatnip/index_map.cpp b/src/libcatnip/index_map.cpp deleted file mode 100644 index c6a132d..0000000 --- a/src/libcatnip/index_map.cpp +++ /dev/null @@ -1,47 +0,0 @@ - - -#include "index_map.hpp" - -#include "atom.hpp" -#include "atom_group.hpp" - -// Standard includes -#include - -namespace catnip { - - IndexMap::IndexMap(AtomSystem atm_sys){ - std::vector comp_indices = atm_sys.getComponentIndices(); - const AtomGroup & complex_grp = atm_sys.getComplex(); - int sys_ind = 0; - for ( int & comp_ind : comp_indices) { - const AtomGroup & comp_grp = atm_sys.at(comp_ind); - for( const std::shared_ptr & atm_ptr : comp_grp){ - std::vector atm_indices = complex_grp.find(atm_ptr); - assert(atm_indices.size() == 1); - int atm_ind = atm_indices.at(0); - int num_basis = comp_grp.at(atm_ind)->getBasisFuncCount(); - for ( int ind_temp = 0; ind_temp IndexMap::findLocation(int row){ - for( std::pair> group_rows : row_col_init){ - int row_ind = 0; - for ( int row_ : group_rows.second ){ - if (row_ == row){ - return std::pair(group_rows.first, row_ind); - } - ++row_ind; - } - } - return std::pair(); - } - -} // namespace catnip diff --git a/src/libcatnip/index_map.hpp b/src/libcatnip/index_map.hpp deleted file mode 100644 index 6bdb530..0000000 --- a/src/libcatnip/index_map.hpp +++ /dev/null @@ -1,34 +0,0 @@ - -#pragma once -#ifndef _CATNIP_INDEX_MAP_HPP -#define _CATNIP_INDEX_MAP_HPP - -// Local private includes -#include "atom_system.hpp" - -// Standard includes -#include -#include - -namespace catnip { - - class IndexMap { - public: - IndexMap() = default; - IndexMap(AtomSystem atm_sys); - // The component rows and colums in their current locations in - // in the full system matrix of the complex - std::map> row_col_init; - - // Map indicate where the rows and cols should go in the final state - // Each int in the vector represents the location in the full system matrix - std::map> row_col_final; - - // Searches the init row for the provided row and returns the group it is - // in as well as its current index - std::pair findLocation(int row); - }; - - -} // namespace catnip -#endif // _CATNIP_INDEX_MAP_HPP diff --git a/src/libcatnip/swap_engine.cpp b/src/libcatnip/swap_engine.cpp index 0ce44e0..1c6ef44 100644 --- a/src/libcatnip/swap_engine.cpp +++ b/src/libcatnip/swap_engine.cpp @@ -1,35 +1,119 @@ - +// Local private includes #include "swap_engine.hpp" #include "atom.hpp" #include "atom_group.hpp" +#include "basis_map.hpp" #include "size_type.hpp" +// Standard includes +#include + namespace catnip { - // Swaps rows columns and keeps up with how future swaps should be updated - SwapEngine::SwapEngine(IndexMap ind_map, Size size) : - size_(size), ind_map_(ind_map) { - scratch_ = Eigen::MatrixXd::Zero(size, 1); - - - // Already have enough information to calculate the correct swap order - // Note the order of swaps is important. - for ( std::pair> group_row : ind_map_.row_col_init ){ - int group_ind = group_row.first; - for ( int row : group_row.second ) { - int final_row = ind_map_.row_col_final[group_ind].at(row); - std::pair swap(row,final_row); - // Now we need to update index map, the row located at the final - // position has now been moved - auto group_and_row_ind = ind_map_.findLocation(final_row); - // Final row location needs to be pointed to the starting row - ind_map_.row_col_init[group_and_row_ind.first].at(group_and_row_ind.second) = row; + /** + * @brief Serves as scracth space + * + * Can store two rows at a time, the order they are loaded and unloaded is + * FIFO - first in first out + */ + class Scratch { + private: + Eigen::MatrixXd scratch_; + int size_; + bool empty_ = true; + public: + Scratch(int size) : size_(size) { + scratch_ = Eigen::MatrixXd::Zero(1,size_); + } + + bool empty() const noexcept { return empty_; } + + void loadFromRow(const Eigen::MatrixXd & mat, int row){ + for ( int i = 0; i < size_ ; ++i ){ + scratch_(0, i) = mat(row,i); + } + empty_ = false; + } + + void loadFromCol(const Eigen::MatrixXd & mat, int col){ + for ( int i = 0; i < size_ ; ++i ){ + scratch_(0, i) = mat(i,col); + } + empty_ = false; + } + void unloadToCol(Eigen::MatrixXd & mat, int col) { + for ( int i = 0; i < size_ ; ++i ){ + mat(i,col) = scratch_(0, i); + } + empty_ = true; + } + void unloadToRow(Eigen::MatrixXd & mat, int row) { + for ( int i = 0; i < size_ ; ++i ){ + mat(row, i) = scratch_(0, i); } + empty_ = true; } + + }; + + // Swaps rows columns and keeps up with how future swaps should be updated + SwapEngine::SwapEngine(BasisMap basis_map) { + + size_ = 0; + // The with the largest index will tell us the size we need to allocate + for ( std::pair> grp_rows : basis_map.row_col_final ){ + size_t max_value = *(std::max_element(grp_rows.second.begin(), grp_rows.second.end())); + size_ = std::max( max_value+1 , size_ ); + } + + // Want to order these + // 4 + // 3 + // 1 + // 2 + + // How can we order + // 4 <-> 2 2 <-> 3 3 <-> 1 + // + // > 2 > 3 > 1 + // 3 2 2 + // 1 1 3 + // 4 4 4 + // + + // Already have enough information to calculate the correct swap order + // Note the order of swaps is important. + for ( std::pair> & group_row : basis_map.row_col_current ){ + int group_ind = group_row.first; + size_t index = 0; + + assert(group_row.second.size()>0 && "ERROR a component has no rows."); + do { + int current_row_in_complex = group_row.second.at(index); + int final_row_in_complex = basis_map.row_col_final[group_ind].at(index); + + + if ( current_row_in_complex != final_row_in_complex ){ + // Row that currently occupies the location where the current row should + // go + auto group_and_row_ind = basis_map.findLocation(final_row_in_complex); + int replacement_row = basis_map.row_col_current[group_and_row_ind.first].at(group_and_row_ind.second); + std::pair swap(replacement_row, current_row_in_complex); + + // Final row location needs to be pointed to the starting row + basis_map.row_col_current[group_ind].at(index) = replacement_row; + basis_map.row_col_current[group_and_row_ind.first].at(group_and_row_ind.second) = current_row_in_complex; + + swap_order_.push_back(swap); + } else { + ++index; + } + } while (index < group_row.second.size()); } + } // This method of swapping was chosen to keep the memory footprint // reasonable. // Will correctly sort the rows and columns of the matrix @@ -39,37 +123,81 @@ namespace catnip { if( mat.rows() != mat.cols() ) { throw std::runtime_error("Can only arrange square matrices"); } - if( mat.rows() != size_ ) { - throw std::runtime_error("Index map has different number of basis functions to matrix"); + if( mat.rows() != static_cast(size_) ) { + throw std::runtime_error("Scratch space, swap procedure is not " + "consistent with the matrix."); } + + arrangeRows(mat); + // Repeat for columns + arrangeCols(mat); + } - for ( std::pair> group_row : ind_map_.row_col_init ){ - int group_ind = group_row.first; - for ( int row : group_row.second ) { - int final_row = ind_map_.row_col_final[group_ind].at(row); - if(final_row == row ) continue; - // Copy the data at the final row into the scratch space - scratch_.col(0) = mat.row(final_row); - // Copy the data from the initial row into the final row - mat.row(final_row) = mat.row(row); - // Copy the data from the temporary row into the initial row - mat.row(row) = scratch_.col(0); + void SwapEngine::arrangeCols(Eigen::MatrixXd & mat) { + // Check that matrix is square + if( mat.rows() != mat.cols() ) { + throw std::runtime_error("Can only arrange square matrices"); + } + if( mat.rows() != static_cast(size_) ) { + throw std::runtime_error("Scratch space, swap procedure is not " + "consistent with the matrix."); + } + arrangeCols_(mat); + } + + void SwapEngine::arrangeCols_(Eigen::MatrixXd & mat) { + + Scratch scratch(size_); + for ( size_t swap_ind = 0; swap_ind < swap_order_.size(); ++swap_ind ){ + + auto swap = swap_order_.at(swap_ind); + if (scratch.empty() ) { + scratch.loadFromCol(mat, swap.first); } + // Write too the first instance + mat.col(swap.first) = mat.col(swap.second); + // If the next swap involves the row we just loaded don't bother writing + // it back into mat just keep it in scratch + if ( swap_ind + 1 < swap_order_.size() ){ + if( swap_order_.at(swap_ind+1).first == swap.second ) continue; + } + scratch.unloadToCol(mat, swap.second); } + } - // Repeat for columns - for ( std::pair> group_col : ind_map_.row_col_init ){ - int group_ind = group_col.first; - for ( int col : group_col.second ) { - int final_col = ind_map_.row_col_final[group_ind].at(col); - if(final_col == col ) continue; - // Copy the data at the final row into the scratch space - scratch_.col(0) = mat.col(final_col); - // Copy the data from the initial row into the final row - mat.col(final_col) = mat.col(col); - // Copy the data from the temporary row into the initial row - mat.col(col) = scratch_.col(0); + void SwapEngine::arrangeRows(Eigen::MatrixXd & mat) { + // Check that matrix is square + if( mat.rows() != mat.cols() ) { + throw std::runtime_error("Can only arrange square matrices"); + } + if( mat.rows() != static_cast(size_) ) { + std::string error_msg = "Scratch space, swap procedure is not " + "consistent with the matrix. Rows in matrix " + + std::to_string(mat.rows()) + " size of scratch space " + + std::to_string(size_); + throw std::runtime_error(error_msg); + } + arrangeRows_(mat); + } + + void SwapEngine::arrangeRows_(Eigen::MatrixXd & mat) { + + Scratch scratch(size_); + for ( size_t swap_ind = 0; swap_ind < swap_order_.size(); ++swap_ind ){ + + auto swap = swap_order_.at(swap_ind); + if (scratch.empty() ) { + scratch.loadFromRow(mat, swap.first); } + // Write too the first instance + mat.row(swap.first) = mat.row(swap.second); + // If the next swap involves the row we just loaded don't bother writing + // it back into mat just keep it in scratch + if ( swap_ind + 1 < swap_order_.size() ){ + if( swap_order_.at(swap_ind+1).first == swap.second ) continue; + } + scratch.unloadToRow(mat, swap.second); } - } + + } } // namespace catnip diff --git a/src/libcatnip/swap_engine.hpp b/src/libcatnip/swap_engine.hpp index e5d7d6e..8f4c1eb 100644 --- a/src/libcatnip/swap_engine.hpp +++ b/src/libcatnip/swap_engine.hpp @@ -5,7 +5,7 @@ #include "atom.hpp" #include "atom_group.hpp" -#include "index_map.hpp" +#include "basis_map.hpp" #include "size_type.hpp" namespace catnip { @@ -13,14 +13,17 @@ namespace catnip { // Swaps rows columns and keeps up with how future swaps should be updated class SwapEngine { private: - Size size_; - IndexMap ind_map_; - Eigen::MatrixXd scratch_; + size_t size_; + std::vector> swap_order_; + void arrangeRows_(Eigen::MatrixXd & mat); + void arrangeCols_(Eigen::MatrixXd & mat); public: - SwapEngine(IndexMap ind_map, Size size); + SwapEngine(BasisMap basis_map); void arrange(Eigen::MatrixXd & mat); + void arrangeRows(Eigen::MatrixXd & mat); + void arrangeCols(Eigen::MatrixXd & mat); }; diff --git a/src/libcatnip/transfer_complex.cpp b/src/libcatnip/transfer_complex.cpp index 21134ad..3638ac8 100644 --- a/src/libcatnip/transfer_complex.cpp +++ b/src/libcatnip/transfer_complex.cpp @@ -4,18 +4,18 @@ #include "atom.hpp" #include "atom_group.hpp" -#include "index_map.hpp" +#include "basis_map.hpp" #include "swap_engine.hpp" namespace catnip { - void TransferComplex::unscramble(AtomGroupContainer atom_groups) { + void TransferComplex::unscramble(AtomSystem atom_sys) { // We should figure out how all the rows and columns should be // rearranged before moving any of the coefficients in the matrix - IndexMap ind_map = IndexMap(atom_groups); + BasisMap basis_map = BasisMap(atom_sys); - size_t total_basis = atom_groups.getTotalBasisFunctions(GroupType::Component); - size_t total_basis_comp = atom_groups.getTotalBasisFunctions(GroupType::Complex); + size_t total_basis = atom_sys.getTotalBasisFunctions(GroupType::Component); + size_t total_basis_comp = atom_sys.getTotalBasisFunctions(GroupType::Complex); // If the total number of basis functions in the components is greater than // the total number of basis functions in the complex, throw an error @@ -23,7 +23,7 @@ namespace catnip { throw std::runtime_error("Sum of basis functions in components does not equal the number of basis functions in the complex"); } - auto swap_eng = SwapEngine(ind_map,total_basis); + auto swap_eng = SwapEngine(basis_map); swap_eng.arrange(*(params_->complex_coefs)); swap_eng.arrange(*(params_->S_AO)); diff --git a/src/libcatnip/transfer_complex.hpp b/src/libcatnip/transfer_complex.hpp index 632725b..e580efd 100644 --- a/src/libcatnip/transfer_complex.hpp +++ b/src/libcatnip/transfer_complex.hpp @@ -2,17 +2,19 @@ #ifndef _CATNIP_TRANSFER_COMPLEX_HPP #define _CATNIP_TRANSFER_COMPLEX_HPP -#include "atom_group_container.hpp" +// Local private includes +#include "atom_system.hpp" +// Third party includes +#include + +// Standard includes #include #include #include #include #include -//#include "matrix.hpp" -#include - namespace catnip { class TransferComplex { @@ -44,7 +46,7 @@ class TransferComplex { TransferComplex(Parameters * params) : params_(params) {}; - void unscramble(AtomGroupContainer atom_groups); + void unscramble(AtomSystem atm_sys); // Orbital type and a map of the corresponding number // E.g. diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index ee82c99..63b41bf 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -8,8 +8,9 @@ list( APPEND UNIT_TEST_SOURCE_FILES test_atom test_atom_group test_atom_group_container + test_atom_system + test_basis_map test_elements - test_index_map test_log test_parameters test_propertydouble @@ -21,7 +22,8 @@ list( APPEND UNIT_TEST_SOURCE_FILES test_propertystring test_propertyswitch test_qc_functions - test_string_support) + test_string_support + test_swap_engine) if(CODE_COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") find_library (GCOV gcov) diff --git a/src/tests/test_index_map.cpp b/src/tests/test_index_map.cpp deleted file mode 100644 index 504f421..0000000 --- a/src/tests/test_index_map.cpp +++ /dev/null @@ -1,16 +0,0 @@ - -#define CATCH_CONFIG_MAIN -#include - -#include "index_map.hpp" - -#include "atom_group_container.hpp" - -using namespace catnip; - -TEST_CASE("Index Map","[unit]") { - - AtomGroupContainer atom_cont; - IndexMap ind_map(atom_cont); - -} From b8119b84667f4cf5c58c4ce718e497e5151c3485 Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Fri, 24 Jul 2020 08:17:30 -0600 Subject: [PATCH 47/68] Add test files --- src/tests/test_atom_system.cpp | 234 ++++++++++++++++++ src/tests/test_basis_map.cpp | 268 ++++++++++++++++++++ src/tests/test_swap_engine.cpp | 437 +++++++++++++++++++++++++++++++++ 3 files changed, 939 insertions(+) create mode 100644 src/tests/test_atom_system.cpp create mode 100644 src/tests/test_basis_map.cpp create mode 100644 src/tests/test_swap_engine.cpp diff --git a/src/tests/test_atom_system.cpp b/src/tests/test_atom_system.cpp new file mode 100644 index 0000000..31602b1 --- /dev/null +++ b/src/tests/test_atom_system.cpp @@ -0,0 +1,234 @@ + +#define CATCH_CONFIG_MAIN +#include + +// Local private includes +#include "atom_system.hpp" + +#include "atom.hpp" +#include "atom_group.hpp" +#include "atom_group_container.hpp" +#include "elements.hpp" + +// Standard includes +#include + +using namespace catnip; + +TEST_CASE("Atom System","[unit]") { + + Atom atom1(Element::H, 0.0, 0.0, 0.0); + Atom atom2(Element::H, 2.0, 0.0, 0.0); + Atom atom3(Element::C, 1.0, 1.0, 0.0); + Atom atom4(Element::O, 3.3, 4.3, 0.0); + Atom atom5(Element::O, 3.0, 3.9, 0.0); + // Same position as atom5 but different element + Atom atom6(Element::C, 3.0, 3.9, 0.0); + + auto atom1_ptr = std::make_shared(atom1); + auto atom2_ptr = std::make_shared(atom2); + auto atom3_ptr = std::make_shared(atom3); + auto atom4_ptr = std::make_shared(atom4); + auto atom5_ptr = std::make_shared(atom5); + auto atom6_ptr = std::make_shared(atom6); + + SECTION("Building component without atom 5") { + // Extra atoms are allowed in the complex but not in the componets + AtomGroup component1("CH2"); + component1.add(atom1_ptr); + component1.add(atom2_ptr); + component1.add(atom3_ptr); + + AtomGroup component2("O2"); + component2.add(atom4_ptr); + + AtomGroup complex1("O2CH2"); + complex1.add(atom1_ptr); + complex1.add(atom2_ptr); + complex1.add(atom3_ptr); + complex1.add(atom4_ptr); + complex1.add(atom5_ptr); + + AtomGroupContainer atom_grp_cont; + atom_grp_cont.add(component1); + atom_grp_cont.add(component2); + atom_grp_cont.add(complex1); + + REQUIRE_NOTHROW(AtomSystem(atom_grp_cont) ); + } + + SECTION("Building complex without atom 5") { + // Extra atoms are allowed in the complex but not in the componets + AtomGroup component1("CH2"); + component1.add(atom1_ptr); + component1.add(atom2_ptr); + component1.add(atom3_ptr); + + AtomGroup component2("O2"); + component2.add(atom4_ptr); + component2.add(atom5_ptr); + + AtomGroup complex1("O2CH2"); + complex1.add(atom1_ptr); + complex1.add(atom2_ptr); + complex1.add(atom3_ptr); + complex1.add(atom4_ptr); + + AtomGroupContainer atom_grp_cont; + atom_grp_cont.add(component1); + atom_grp_cont.add(component2); + atom_grp_cont.add(complex1); + + REQUIRE_THROWS(AtomSystem(atom_grp_cont) ); + } + + SECTION("Building with atom 5") { + AtomGroup component1("CH2"); + component1.add(atom1_ptr); // H + component1.add(atom2_ptr); // H + component1.add(atom3_ptr); // C + + AtomGroup component2("O2"); + component2.add(atom4_ptr); // O + component2.add(atom5_ptr); // O + + AtomGroup complex1("O2CH2"); + complex1.add(atom1_ptr); // H + complex1.add(atom2_ptr); // H + complex1.add(atom3_ptr); // C + complex1.add(atom4_ptr); // O + complex1.add(atom5_ptr); // O + + AtomGroupContainer atom_grp_cont; + atom_grp_cont.add(component1); + atom_grp_cont.add(component2); + atom_grp_cont.add(complex1); + + AtomSystem atm_sys(atom_grp_cont); + REQUIRE(atm_sys.getComplex().getType() == GroupType::Complex ); + REQUIRE(atm_sys.getComplex().getName() == "O2CH2" ); + + std::vector component_indices = atm_sys.getComponentIndices(); + REQUIRE(component_indices.size() == 2); + REQUIRE(component_indices.at(0) == 0); + REQUIRE(component_indices.at(1) == 1); + + std::vector linked_atms = atm_sys.getLinkedAtomsWithDifferentElements(); + REQUIRE(linked_atms.size() == 0); + + // Basis functions + std::vector basis_comp1{ 1, 1, 4}; + std::vector basis_comp2{ 5, 5}; + // should be 5, 5 at the end + std::vector wrong_basis_complex{ 1, 1, 4, 3, 3}; + + atm_sys.assignBasisFunctions( 0, basis_comp1 ); + atm_sys.assignBasisFunctions( 1, basis_comp2 ); + + // Should be complete at this point + REQUIRE( atm_sys.systemComplete() ); + + // By using the basis functions for the complex we ensure that basis + // functions between the components and the complex are consistent + REQUIRE_THROWS( atm_sys.assignBasisFunctions( 2, wrong_basis_complex )); + + std::vector basis_complex{ 1, 1, 4, 5, 5}; + REQUIRE_NOTHROW( atm_sys.assignBasisFunctions( 2, basis_complex )); + + REQUIRE( atm_sys.at(0).size() == 3); + REQUIRE( atm_sys.at(0).at(0)->getBasisFuncCount() == 1); // H + REQUIRE( atm_sys.at(0).at(1)->getBasisFuncCount() == 1); // H + REQUIRE( atm_sys.at(0).at(2)->getBasisFuncCount() == 4); // C + + REQUIRE( atm_sys.at(1).size() == 2); + REQUIRE( atm_sys.at(1).at(0)->getBasisFuncCount() == 5); // O + REQUIRE( atm_sys.at(1).at(1)->getBasisFuncCount() == 5); // O + + REQUIRE( atm_sys.at(2).size() == 5); + REQUIRE( atm_sys.at(2).at(0)->getBasisFuncCount() == 1); // H + REQUIRE( atm_sys.at(2).at(1)->getBasisFuncCount() == 1); // H + REQUIRE( atm_sys.at(2).at(2)->getBasisFuncCount() == 4); // C + REQUIRE( atm_sys.at(2).at(3)->getBasisFuncCount() == 5); // O + REQUIRE( atm_sys.at(2).at(4)->getBasisFuncCount() == 5); // O + } + + SECTION("Building complex with atom 6") { + AtomGroup component1("CH2"); + component1.add(atom1_ptr); + component1.add(atom2_ptr); + component1.add(atom3_ptr); + + AtomGroup component2("O2"); + component2.add(atom4_ptr); + component2.add(atom5_ptr); + + AtomGroup complex1("OC2H2"); + complex1.add(atom1_ptr); + complex1.add(atom2_ptr); + complex1.add(atom3_ptr); + complex1.add(atom4_ptr); + complex1.add(atom6_ptr); // Carbon instead of Oxygen + + AtomGroupContainer atom_grp_cont; + atom_grp_cont.add(component1); + atom_grp_cont.add(component2); + atom_grp_cont.add(complex1); + + AtomSystem atm_sys(atom_grp_cont); + REQUIRE(atm_sys.getComplex().getType() == GroupType::Complex ); + REQUIRE(atm_sys.getComplex().getName() == "OC2H2" ); + + std::vector component_indices = atm_sys.getComponentIndices(); + REQUIRE(component_indices.size() == 2); + REQUIRE(component_indices.at(0) == 0); + REQUIRE(component_indices.at(1) == 1); + + std::vector linked_atms = atm_sys.getLinkedAtomsWithDifferentElements(); + REQUIRE(linked_atms.size() == 1); + AtomSystem::Link link = linked_atms.at(0); + // atm5 from component 2 should be linked with atom 5 of complex + REQUIRE(link.component_name == "O2"); + REQUIRE(link.component_ind == 1); + REQUIRE(link.component_atm_ind == 1); + REQUIRE(link.complex_name == "OC2H2"); + REQUIRE(link.complex_ind == 2); + REQUIRE(link.complex_atm_ind == 4); + + // Basis functions + std::vector basis_comp1{ 1, 1, 4}; + std::vector basis_comp2{ 5, 5}; + // should be 5, 5 at the end + std::vector wrong_basis_complex{ 1, 1, 4, 3, 3}; + + atm_sys.assignBasisFunctions( 0, basis_comp1 ); + atm_sys.assignBasisFunctions( 1, basis_comp2 ); + + // Should NOT be complete at this point, as atom 5 and 6 though positionally + // linked are not in the same memory space + REQUIRE( atm_sys.systemComplete() == false ); + + // By using the basis functions for the complex we ensure that basis + // functions between the components and the complex are consistent + REQUIRE_THROWS( atm_sys.assignBasisFunctions( 2, wrong_basis_complex )); + + std::vector basis_complex{ 1, 1, 4, 5, 5}; + REQUIRE_NOTHROW( atm_sys.assignBasisFunctions( 2, basis_complex )); + REQUIRE( atm_sys.systemComplete() ); + + REQUIRE( atm_sys.at(0).size() == 3); + REQUIRE( atm_sys.at(0).at(0)->getBasisFuncCount() == 1); // H + REQUIRE( atm_sys.at(0).at(1)->getBasisFuncCount() == 1); // H + REQUIRE( atm_sys.at(0).at(2)->getBasisFuncCount() == 4); // C + + REQUIRE( atm_sys.at(1).size() == 2); + REQUIRE( atm_sys.at(1).at(0)->getBasisFuncCount() == 5); // O + REQUIRE( atm_sys.at(1).at(1)->getBasisFuncCount() == 5); // O + + REQUIRE( atm_sys.at(2).size() == 5); + REQUIRE( atm_sys.at(2).at(0)->getBasisFuncCount() == 1); // H + REQUIRE( atm_sys.at(2).at(1)->getBasisFuncCount() == 1); // H + REQUIRE( atm_sys.at(2).at(2)->getBasisFuncCount() == 4); // C + REQUIRE( atm_sys.at(2).at(3)->getBasisFuncCount() == 5); // O + REQUIRE( atm_sys.at(2).at(4)->getBasisFuncCount() == 5); // O + } +} diff --git a/src/tests/test_basis_map.cpp b/src/tests/test_basis_map.cpp new file mode 100644 index 0000000..4b1e248 --- /dev/null +++ b/src/tests/test_basis_map.cpp @@ -0,0 +1,268 @@ + +#define CATCH_CONFIG_MAIN +#include + +// Local private includes +#include "basis_map.hpp" + +#include "atom.hpp" +#include "atom_group_container.hpp" +#include "atom_system.hpp" +#include "elements.hpp" + +using namespace catnip; + +TEST_CASE("Basis Map Unscrambled","[integration]") { + + Atom atom1(Element::H, 0.0, 0.0, 0.0); + Atom atom2(Element::H, 2.0, 0.0, 0.0); + Atom atom3(Element::C, 1.0, 1.0, 0.0); + Atom atom4(Element::O, 3.3, 4.3, 0.0); + Atom atom5(Element::O, 3.0, 3.9, 0.0); + + auto atom1_ptr = std::make_shared(atom1); + auto atom2_ptr = std::make_shared(atom2); + auto atom3_ptr = std::make_shared(atom3); + auto atom4_ptr = std::make_shared(atom4); + auto atom5_ptr = std::make_shared(atom5); + + // Extra atoms are allowed in the complex but not in the componets + AtomGroup component1("CH2"); + component1.add(atom1_ptr); + component1.add(atom2_ptr); + component1.add(atom3_ptr); + + AtomGroup component2("O2"); + component2.add(atom4_ptr); + component2.add(atom5_ptr); + + AtomGroup complex1("O2CH2"); + complex1.add(atom1_ptr); + complex1.add(atom2_ptr); + complex1.add(atom3_ptr); + complex1.add(atom4_ptr); + complex1.add(atom5_ptr); + + AtomGroupContainer atom_grp_cont; + atom_grp_cont.add(component1); + atom_grp_cont.add(component2); + atom_grp_cont.add(complex1); + + AtomSystem atm_sys(atom_grp_cont); + + std::vector basis_complex{ 1, 1, 4, 5, 5}; + + int index_complex = 2; + atm_sys.assignBasisFunctions( index_complex, basis_complex); + BasisMap basis_map(atm_sys); + + // Equal to the total number of basis in the group + REQUIRE( basis_map.row_col_current[0].size() == 6); + // comp1 atm 1 should map to location 0 in the complex at least currentially + REQUIRE( basis_map.row_col_current[0].at(0) == 0); + // comp1 atm 2 should map to location 1 in the complex at least currentially + REQUIRE( basis_map.row_col_current[0].at(1) == 1); + // comp1 atm 3 should map to location 2-5 in the complex at least currentially + REQUIRE( basis_map.row_col_current[0].at(2) == 2); + REQUIRE( basis_map.row_col_current[0].at(3) == 3); + REQUIRE( basis_map.row_col_current[0].at(4) == 4); + REQUIRE( basis_map.row_col_current[0].at(5) == 5); + + REQUIRE( basis_map.row_col_current[1].size() == 10); + // comp2 atm 1 should map to location 4 in the complex at least currentially + REQUIRE( basis_map.row_col_current[1].at(0) == 6); + // comp2 atm 2 should map to location 5 in the complex at least currentially + REQUIRE( basis_map.row_col_current[1].at(1) == 7); + REQUIRE( basis_map.row_col_current[1].at(2) == 8); + REQUIRE( basis_map.row_col_current[1].at(3) == 9); + REQUIRE( basis_map.row_col_current[1].at(4) == 10); + REQUIRE( basis_map.row_col_current[1].at(5) == 11); + REQUIRE( basis_map.row_col_current[1].at(6) == 12); + REQUIRE( basis_map.row_col_current[1].at(7) == 13); + REQUIRE( basis_map.row_col_current[1].at(8) == 14); + REQUIRE( basis_map.row_col_current[1].at(9) == 15); + + // In this case the final and currential version should be the same + // Equal to the total number of basis in the group + REQUIRE( basis_map.row_col_final[0].size() == 6); + // comp1 atm 1 should map to location 0 in the complex at least finalially + REQUIRE( basis_map.row_col_final[0].at(0) == 0); + // comp1 atm 2 should map to location 1 in the complex at least finalially + REQUIRE( basis_map.row_col_final[0].at(1) == 1); + // comp1 atm 3 should map to location 2-5 in the complex at least finalially + REQUIRE( basis_map.row_col_final[0].at(2) == 2); + REQUIRE( basis_map.row_col_final[0].at(3) == 3); + REQUIRE( basis_map.row_col_final[0].at(4) == 4); + REQUIRE( basis_map.row_col_final[0].at(5) == 5); + + REQUIRE( basis_map.row_col_final[1].size() == 10); + // comp2 atm 1 should map to location 4 in the complex at least finalially + REQUIRE( basis_map.row_col_final[1].at(0) == 6); + // comp2 atm 2 should map to location 5 in the complex at least finalially + REQUIRE( basis_map.row_col_final[1].at(1) == 7); + REQUIRE( basis_map.row_col_final[1].at(2) == 8); + REQUIRE( basis_map.row_col_final[1].at(3) == 9); + REQUIRE( basis_map.row_col_final[1].at(4) == 10); + REQUIRE( basis_map.row_col_final[1].at(5) == 11); + REQUIRE( basis_map.row_col_final[1].at(6) == 12); + REQUIRE( basis_map.row_col_final[1].at(7) == 13); + REQUIRE( basis_map.row_col_final[1].at(8) == 14); + REQUIRE( basis_map.row_col_final[1].at(9) == 15); + + std::pair location = basis_map.findLocation(0); + REQUIRE( location.first == 0 ); + REQUIRE( location.second == 0 ); + location = basis_map.findLocation(1); + REQUIRE( location.first == 0 ); + REQUIRE( location.second == 1 ); + location = basis_map.findLocation(2); + REQUIRE( location.first == 0 ); + REQUIRE( location.second == 2 ); + + location = basis_map.findLocation(6); + REQUIRE( location.first == 1 ); + REQUIRE( location.second == 0 ); + location = basis_map.findLocation(7); + REQUIRE( location.first == 1 ); + REQUIRE( location.second == 1 ); + location = basis_map.findLocation(15); + REQUIRE( location.first == 1 ); + REQUIRE( location.second == 9 ); +} + + +/** + * @brief In this test some of the atoms added to the complex will be added + * in a different order from how they were added to each of the components + * + * @param Scrambled" + * @param "[integration]" + */ +TEST_CASE("Basis Map Scrambled","[integration]") { + + std::vector basis_comp1{ 1, 1, 4}; + std::vector basis_comp2{ 5, 5}; + + Atom atom1(Element::H, 0.0, 0.0, 0.0); + Atom atom2(Element::H, 2.0, 0.0, 0.0); + Atom atom3(Element::C, 1.0, 1.0, 0.0); + Atom atom4(Element::O, 3.3, 4.3, 0.0); + Atom atom5(Element::O, 3.0, 3.9, 0.0); + + auto atom1_ptr = std::make_shared(atom1); + auto atom2_ptr = std::make_shared(atom2); + auto atom3_ptr = std::make_shared(atom3); + auto atom4_ptr = std::make_shared(atom4); + auto atom5_ptr = std::make_shared(atom5); + + // Extra atoms are allowed in the complex but not in the componets + AtomGroup component1("CH2"); + component1.add(atom1_ptr); + component1.add(atom2_ptr); + component1.add(atom3_ptr); + + AtomGroup component2("O2"); + component2.add(atom4_ptr); + component2.add(atom5_ptr); + + // HERE: the order has been changed + AtomGroup complex1("O2CH2"); + complex1.add(atom4_ptr); // The basis functions of atom 4 : 0 - 4 + complex1.add(atom1_ptr); // The basis functiosn of atom 1 : 5 - 5 + complex1.add(atom3_ptr); // The basis functiosn of atom 3 : 6 - 9 + complex1.add(atom5_ptr); // The basis functiosn of atom 5 : 10 - 14 + complex1.add(atom2_ptr); // The basis functions of atom 2 : 15 - 15 + + AtomGroupContainer atom_grp_cont; + atom_grp_cont.add(component1); + atom_grp_cont.add(component2); + atom_grp_cont.add(complex1); + + AtomSystem atm_sys(atom_grp_cont); + + + int index_component1 = 0; + int index_component2 = 1; + atm_sys.assignBasisFunctions( index_component1, basis_comp1); + atm_sys.assignBasisFunctions( index_component2, basis_comp2); + + BasisMap basis_map(atm_sys); + + // The row_col_current will now be different but the row_col_final should remail + // the same + + // The basis functions of atom 4 : 0 - 4 + // The basis functiosn of atom 1 : 5 - 5 + // The basis functiosn of atom 3 : 6 - 9 + // The basis functiosn of atom 5 : 10 - 14 + // The basis functions of atom 2 : 15 - 15 + + // Equal to the total number of basis in the group + REQUIRE( basis_map.row_col_current[0].size() == 6); + REQUIRE( basis_map.row_col_current[0].at(0) == 5); // atom 1 + REQUIRE( basis_map.row_col_current[0].at(1) == 15); // atom 2 + REQUIRE( basis_map.row_col_current[0].at(2) == 6); // atom 3 + REQUIRE( basis_map.row_col_current[0].at(3) == 7); + REQUIRE( basis_map.row_col_current[0].at(4) == 8); + REQUIRE( basis_map.row_col_current[0].at(5) == 9); + + REQUIRE( basis_map.row_col_current[1].size() == 10); + REQUIRE( basis_map.row_col_current[1].at(0) == 0); // atom 4 + REQUIRE( basis_map.row_col_current[1].at(1) == 1); + REQUIRE( basis_map.row_col_current[1].at(2) == 2); + REQUIRE( basis_map.row_col_current[1].at(3) == 3); + REQUIRE( basis_map.row_col_current[1].at(4) == 4); + REQUIRE( basis_map.row_col_current[1].at(5) == 10); // atom 5 + REQUIRE( basis_map.row_col_current[1].at(6) == 11); + REQUIRE( basis_map.row_col_current[1].at(7) == 12); + REQUIRE( basis_map.row_col_current[1].at(8) == 13); + REQUIRE( basis_map.row_col_current[1].at(9) == 14); + + // In this case the final and currential version should be the same + // Equal to the total number of basis in the group + REQUIRE( basis_map.row_col_final[0].size() == 6); + // comp1 atm 1 should map to location 0 in the complex at least finalially + REQUIRE( basis_map.row_col_final[0].at(0) == 0); + // comp1 atm 2 should map to location 1 in the complex at least finalially + REQUIRE( basis_map.row_col_final[0].at(1) == 1); + // comp1 atm 3 should map to location 2-5 in the complex at least finalially + REQUIRE( basis_map.row_col_final[0].at(2) == 2); + REQUIRE( basis_map.row_col_final[0].at(3) == 3); + REQUIRE( basis_map.row_col_final[0].at(4) == 4); + REQUIRE( basis_map.row_col_final[0].at(5) == 5); + + REQUIRE( basis_map.row_col_final[1].size() == 10); + // comp2 atm 1 should map to location 4 in the complex at least finalially + REQUIRE( basis_map.row_col_final[1].at(0) == 6); + // comp2 atm 2 should map to location 5 in the complex at least finalially + REQUIRE( basis_map.row_col_final[1].at(1) == 7); + REQUIRE( basis_map.row_col_final[1].at(2) == 8); + REQUIRE( basis_map.row_col_final[1].at(3) == 9); + REQUIRE( basis_map.row_col_final[1].at(4) == 10); + REQUIRE( basis_map.row_col_final[1].at(5) == 11); + REQUIRE( basis_map.row_col_final[1].at(6) == 12); + REQUIRE( basis_map.row_col_final[1].at(7) == 13); + REQUIRE( basis_map.row_col_final[1].at(8) == 14); + REQUIRE( basis_map.row_col_final[1].at(9) == 15); + + // Look for where in the currential rows the row of the complex can be found + std::pair location = basis_map.findLocation(0); + REQUIRE( location.first == 1 ); + REQUIRE( location.second == 0 ); + location = basis_map.findLocation(1); + REQUIRE( location.first == 1 ); + REQUIRE( location.second == 1 ); + location = basis_map.findLocation(2); + REQUIRE( location.first == 1 ); + REQUIRE( location.second == 2 ); + + location = basis_map.findLocation(6); + REQUIRE( location.first == 0 ); + REQUIRE( location.second == 2 ); + location = basis_map.findLocation(7); + REQUIRE( location.first == 0 ); + REQUIRE( location.second == 3 ); + location = basis_map.findLocation(15); + REQUIRE( location.first == 0 ); + REQUIRE( location.second == 1 ); +} diff --git a/src/tests/test_swap_engine.cpp b/src/tests/test_swap_engine.cpp new file mode 100644 index 0000000..6fdd2de --- /dev/null +++ b/src/tests/test_swap_engine.cpp @@ -0,0 +1,437 @@ + +#define CATCH_CONFIG_MAIN +#include + +// Local private includes +#include "swap_engine.hpp" + +#include "atom.hpp" +#include "atom_group_container.hpp" +#include "atom_system.hpp" +#include "basis_map.hpp" +#include "elements.hpp" + +// Third party includes +#include + +// Standard includes +#include +#include + +using namespace catnip; +/* +TEST_CASE("Basis Map Unscrambled","[integration]") { + + Atom atom1(Element::H, 0.0, 0.0, 0.0); + Atom atom2(Element::H, 2.0, 0.0, 0.0); + Atom atom3(Element::C, 1.0, 1.0, 0.0); + Atom atom4(Element::O, 3.3, 4.3, 0.0); + Atom atom5(Element::O, 3.0, 3.9, 0.0); + + auto atom1_ptr = std::make_shared(atom1); + auto atom2_ptr = std::make_shared(atom2); + auto atom3_ptr = std::make_shared(atom3); + auto atom4_ptr = std::make_shared(atom4); + auto atom5_ptr = std::make_shared(atom5); + + // Extra atoms are allowed in the complex but not in the componets + AtomGroup component1("CH2"); + component1.add(atom1_ptr); + component1.add(atom2_ptr); + component1.add(atom3_ptr); + + AtomGroup component2("O2"); + component2.add(atom4_ptr); + component2.add(atom5_ptr); + + AtomGroup complex1("O2CH2"); + complex1.add(atom1_ptr); + complex1.add(atom2_ptr); + complex1.add(atom3_ptr); + complex1.add(atom4_ptr); + complex1.add(atom5_ptr); + + AtomGroupContainer atom_grp_cont; + atom_grp_cont.add(component1); + atom_grp_cont.add(component2); + atom_grp_cont.add(complex1); + + AtomSystem atm_sys(atom_grp_cont); + + std::vector basis_complex{ 1, 1, 4, 5, 5}; + + int index_complex = 2; + atm_sys.assignBasisFunctions( index_complex, basis_complex); + BasisMap basis_map(atm_sys); + +} +*/ + +/** + * @brief In this test some of the atoms added to the complex will be added + * in a different order from how they were added to each of the components + * + * @param Scrambled" + * @param "[integration]" + */ +TEST_CASE("Basis Map Scrambled","[integration]") { + + std::vector basis_comp1{ 1, 1, 4}; + std::vector basis_comp2{ 5, 5}; + + Atom atom1(Element::H, 0.0, 0.0, 0.0); + Atom atom2(Element::H, 2.0, 0.0, 0.0); + Atom atom3(Element::C, 1.0, 1.0, 0.0); + Atom atom4(Element::O, 3.3, 4.3, 0.0); + Atom atom5(Element::O, 3.0, 3.9, 0.0); + + auto atom1_ptr = std::make_shared(atom1); + auto atom2_ptr = std::make_shared(atom2); + auto atom3_ptr = std::make_shared(atom3); + auto atom4_ptr = std::make_shared(atom4); + auto atom5_ptr = std::make_shared(atom5); + + // Extra atoms are allowed in the complex but not in the componets + AtomGroup component1("CH2"); + component1.add(atom1_ptr); + component1.add(atom2_ptr); + component1.add(atom3_ptr); + + AtomGroup component2("O2"); + component2.add(atom4_ptr); + component2.add(atom5_ptr); + + // HERE: the order has been changed + AtomGroup complex1("O2CH2"); + complex1.add(atom4_ptr); // The basis functions of atom 4 : 0 - 4 + complex1.add(atom1_ptr); // The basis functiosn of atom 1 : 5 - 5 + complex1.add(atom3_ptr); // The basis functiosn of atom 3 : 6 - 9 + complex1.add(atom5_ptr); // The basis functiosn of atom 5 : 10 - 14 + complex1.add(atom2_ptr); // The basis functions of atom 2 : 15 - 15 + + AtomGroupContainer atom_grp_cont; + atom_grp_cont.add(component1); + atom_grp_cont.add(component2); + atom_grp_cont.add(complex1); + + AtomSystem atm_sys(atom_grp_cont); + + + int index_component1 = 0; + int index_component2 = 1; + atm_sys.assignBasisFunctions( index_component1, basis_comp1); + atm_sys.assignBasisFunctions( index_component2, basis_comp2); + + BasisMap basis_map(atm_sys); + +} + +TEST_CASE("QC Functions","[integration]") { + + std::cout << "Testing: unscramble_Coef" << std::endl; + { + Eigen::MatrixXd dimerCoef = Eigen::MatrixXd::Zero(8, 8); + for (int i = 0; i < 8; ++i) { + dimerCoef(i, 0) = 1.3; + dimerCoef(i, 2) = 0.2; + dimerCoef(i, 3) = 82.4; + dimerCoef(i, 4) = 9.4; + dimerCoef(i, 5) = 3.4; + dimerCoef(i, 7) = -3.0; + } + + // Our coefficient matrix should look like this + // + // col 0 col 1 col 2 col 3 col 4 col 5 col 6 col 7 + // _______________________________________________________ + // row 0 | 1.3 0.0 0.2 82.4 9.4 3.4 0.0 -3.0 + // row 1 | 1.3 0.0 0.2 82.4 9.4 3.4 0.0 -3.0 + // row 2 | 1.3 0.0 0.2 82.4 9.4 3.4 0.0 -3.0 + // row 3 | 1.3 0.0 0.2 82.4 9.4 3.4 0.0 -3.0 + // row 4 | 1.3 0.0 0.2 82.4 9.4 3.4 0.0 -3.0 + // row 5 | 1.3 0.0 0.2 82.4 9.4 3.4 0.0 -3.0 + // row 6 | 1.3 0.0 0.2 82.4 9.4 3.4 0.0 -3.0 + // row 7 | 1.3 0.0 0.2 82.4 9.4 3.4 0.0 -3.0 + // atm3 atm1 atm1 atm5 atm4 atm4 atm2 atm2 + + Atom atom1(Element::H, 1.0, 1.0, 1.0); + Atom atom2(Element::H, 0.0, 0.0, 0.0); + + auto atom1_ptr = std::make_shared(atom1); + auto atom2_ptr = std::make_shared(atom2); + + AtomGroup componentA("A"); + componentA.add(atom1_ptr); + componentA.add(atom2_ptr); + + Atom atom3(Element::C, 1.0, 0.0, 0.0); + Atom atom4(Element::O, 2.0, 0.0, 0.0); + Atom atom5(Element::O, 3.0, 0.0, 0.0); + + auto atom3_ptr = std::make_shared(atom3); + auto atom4_ptr = std::make_shared(atom4); + auto atom5_ptr = std::make_shared(atom5); + + AtomGroup componentB("B"); + componentB.add(atom3_ptr); + componentB.add(atom4_ptr); + componentB.add(atom5_ptr); + + // Arrange atoms in the dimer so they do not appear in the + // same order as the monomers + + // Atom 3 1.0, 0.0, 0.0 + // Atom 1 1.0, 1.0, 1.0 + // Atom 5 3.0, 0.0, 0.0 + // Atom 4 2.0, 0.0, 0.0 + // Atom 2 0.0, 0.0, 0.0 + + AtomGroup complexAB("AB"); + complexAB.add(atom3_ptr); + complexAB.add(atom1_ptr); + complexAB.add(atom5_ptr); + complexAB.add(atom4_ptr); + complexAB.add(atom2_ptr); + + // Combine atom groups + AtomGroupContainer atom_grp_cont; + atom_grp_cont.add(componentA); + atom_grp_cont.add(componentB); + atom_grp_cont.add(complexAB); + + // Basis functions per atom + // + // Atom 1 2 + // Atom 2 2 + // Atom 3 1 + // Atom 4 2 + // Atom 5 1 + + // According to the dimer coordinates they will appear in the following + // order + // Atom 3 1 + // Atom 1 2 + // Atom 5 1 + // Atom 4 2 + // Atom 2 2 + + std::vector basisFuncDimer; + basisFuncDimer.push_back(1); + basisFuncDimer.push_back(2); + basisFuncDimer.push_back(1); + basisFuncDimer.push_back(2); + basisFuncDimer.push_back(2); + + AtomSystem atm_sys(atom_grp_cont); + + // Assign the basis functions to the atoms that are in the complex + int index_complex = 2; + atm_sys.assignBasisFunctions( index_complex, basisFuncDimer); + BasisMap basis_map(atm_sys); + + // According to the basis functions and the atom positions the current + // coef table for monomer A should look like this + // col 0 col 1 col 2 col 3 + // ____________________________ + // row 0 | 0.0 0.2 0.0 -3.0 + // row 1 | 0.0 0.2 0.0 -3.0 + // row 2 | 0.0 0.2 0.0 -3.0 + // row 3 | 0.0 0.2 0.0 -3.0 + // row 4 | 0.0 0.2 0.0 -3.0 + // row 5 | 0.0 0.2 0.0 -3.0 + // row 6 | 0.0 0.2 0.0 -3.0 + // row 7 | 0.0 0.2 0.0 -3.0 + // atm1 atm1 atm2 atm2 + + auto swap_eng = SwapEngine(basis_map); + + std::cout << "Before arranging dimer coef" << std::endl; + std::cout << dimerCoef << std::endl; + + swap_eng.arrangeCols(dimerCoef); + + std::cout << "Expected output" << std::endl; + std::cout << " Col 1 Col 1 Col 2 Col 3 Col 4 Col 5 Col 6 Col 7 " << std::endl; + std::cout << "Row 0 0.0 0.2 0.0 -3.0 1.3 9.4 3.4 82.4" << std::endl; + std::cout << "Row 1 0.0 0.2 0.0 -3.0 1.3 9.4 3.4 82.4" << std::endl; + std::cout << "Row 2 0.0 0.2 0.0 -3.0 1.3 9.4 3.4 82.4" << std::endl; + std::cout << "Row 3 0.0 0.2 0.0 -3.0 1.3 9.4 3.4 82.4" << std::endl; + std::cout << "Row 4 0.0 0.2 0.0 -3.0 1.3 9.4 3.4 82.4" << std::endl; + std::cout << "Row 5 0.0 0.2 0.0 -3.0 1.3 9.4 3.4 82.4" << std::endl; + std::cout << "Row 6 0.0 0.2 0.0 -3.0 1.3 9.4 3.4 82.4" << std::endl; + std::cout << "Row 7 0.0 0.2 0.0 -3.0 1.3 9.4 3.4 82.4" << std::endl; + + std::cout << "After arranging dimer coef" << std::endl; + std::cout << dimerCoef << std::endl; + + for (int i = 0; i < 8; ++i) { + REQUIRE(dimerCoef(i, 0) == Approx(0.0)); + REQUIRE(dimerCoef(i, 1) == Approx(0.2)); + REQUIRE(dimerCoef(i, 2) == Approx(0.0)); + REQUIRE(dimerCoef(i, 3) == Approx(-3.0)); + REQUIRE(dimerCoef(i, 4) == Approx(1.3)); + REQUIRE(dimerCoef(i, 5) == Approx(9.4)); + REQUIRE(dimerCoef(i, 6) == Approx(3.4)); + REQUIRE(dimerCoef(i, 7) == Approx(82.4)); + } + } + + std::cout << "Testing: unscramble SCoef" << std::endl; + { + Eigen::MatrixXd SCoef = Eigen::MatrixXd::Zero(8, 8); + for (int i = 0; i < 8; ++i) { + SCoef(i, 1) = 1.3; + SCoef(i, 2) = 1.3; + SCoef(i, 3) = 4.0; + } + + for (int i = 0; i < 8; ++i) { + SCoef(1, i) = 1.3; + SCoef(2, i) = 1.3; + SCoef(3, i) = 4.0; + } + + SCoef(1, 3) = 6.0; + SCoef(2, 3) = 6.0; + SCoef(3, 1) = 6.0; + SCoef(3, 2) = 6.0; + + // Our coefficient matrix should look like this + // + // col 0 col 1 col 2 col 3 col 4 col 5 col 6 col 7 + // _______________________________________________________ + // atm 3 row 0 | 0.0 1.3 1.3 4.0 0.0 0.0 0.0 0.0 + // atm 1 row 1 | 1.3 1.3 1.3 6.0 1.3 1.3 1.3 1.3 + // atm 1 row 2 | 1.3 1.3 1.3 6.0 1.3 1.3 1.3 1.3 + // atm 5 row 3 | 4.0 6.0 6.0 4.0 4.0 4.0 4.0 4.0 + // atm 4 row 4 | 0.0 1.3 1.3 4.0 0.0 0.0 0.0 0.0 + // atm 4 row 5 | 0.0 1.3 1.3 4.0 0.0 0.0 0.0 0.0 + // atm 2 row 6 | 0.0 1.3 1.3 4.0 0.0 0.0 0.0 0.0 + // atm 2 row 7 | 0.0 1.3 1.3 4.0 0.0 0.0 0.0 0.0 + // atm3 atm1 atm1 atm5 atm4 atm4 atm2 atm2 + + // Contains the x y and z position of atoms in monomer A + Atom atom1(Element::H, 1.0, 1.0, 1.0); + Atom atom2(Element::H, 0.0, 0.0, 0.0); + + auto atom1_ptr = std::make_shared(atom1); + auto atom2_ptr = std::make_shared(atom2); + + AtomGroup componentB("B"); + componentB.add(atom1_ptr); + componentB.add(atom2_ptr); + + // Contains the x y and z position of atoms in monomer B + Atom atom3(Element::C, 1.0, 0.0, 0.0); + Atom atom4(Element::O, 2.0, 0.0, 0.0); + Atom atom5(Element::O, 3.0, 0.0, 0.0); + + auto atom3_ptr = std::make_shared(atom3); + auto atom4_ptr = std::make_shared(atom4); + auto atom5_ptr = std::make_shared(atom5); + + AtomGroup componentA("A"); + componentA.add(atom3_ptr); + componentA.add(atom4_ptr); + componentA.add(atom5_ptr); + + // Positions of atoms in the complex + AtomGroup complexAB("AB"); + complexAB.add(atom3_ptr); + complexAB.add(atom1_ptr); + complexAB.add(atom5_ptr); + complexAB.add(atom4_ptr); + complexAB.add(atom2_ptr); + + // Combine atom groups + AtomGroupContainer atom_grp_cont; + atom_grp_cont.add(componentA); + atom_grp_cont.add(componentB); + atom_grp_cont.add(complexAB); + + AtomSystem atm_sys(atom_grp_cont); + + // Basis functions per atom + // + // Atom 1 2 + // Atom 2 2 + // Atom 3 1 + // Atom 4 2 + // Atom 5 1 + + // According to the dimer coordinates they will appear in the following + // order + // Atom 3 1 + // Atom 1 2 + // Atom 5 1 + // Atom 4 2 + // Atom 2 2 + + std::vector basisFuncDimer; + basisFuncDimer.push_back(1); + basisFuncDimer.push_back(2); + basisFuncDimer.push_back(1); + basisFuncDimer.push_back(2); + basisFuncDimer.push_back(2); + + // Assign the basis functions to the atoms that are in the complex + int index_complex = 2; + atm_sys.assignBasisFunctions( index_complex, basisFuncDimer); + BasisMap basis_map(atm_sys); + + // If we correct the dimer coefficient matrix to line up with the + // coefficients of the monomers it should look like this + // + // Col 0 Col 1 Col 2 Col 3 Col 4 Col 5 Col 6 Col 7 + // Row 0 0 0 0 4 1.3 1.3 0 0 + // Row 1 0 0 0 4 1.3 1.3 0 0 + // Row 2 0 0 0 4 1.3 1.3 0 0 + // Row 3 4 4 4 4 6 6 4 4 + // Row 4 1.3 1.3 1.3 6 1.3 1.3 1.3 1.3 + // Row 5 1.3 1.3 1.3 6 1.3 1.3 1.3 1.3 + // Row 6 0 0 0 4 1.3 1.3 0 0 + // Row 7 0 0 0 4 1.3 1.3 0 0 + // atm3 atm4 atm3 atm5 atm1 atm1 atm2 atm2 + + auto swap_eng = SwapEngine(basis_map); + + std::cout << "Before arranging S" << std::endl; + std::cout << SCoef << std::endl; + + swap_eng.arrange(SCoef); + + std::cout << "Expected output" << std::endl; + std::cout << " Col 1 Col 1 Col 2 Col 3 Col 4 Col 5 Col 6 Col 7 " << std::endl; + std::cout << "Row 0 0 0 0 4 1.3 1.3 0 0 " << std::endl; + std::cout << "Row 1 0 0 0 4 1.3 1.3 0 0 " << std::endl; + std::cout << "Row 2 0 0 0 4 1.3 1.3 0 0 " << std::endl; + std::cout << "Row 3 4 4 4 4 6 6 4 4 " << std::endl; + std::cout << "Row 4 1.3 1.3 1.3 6 1.3 1.3 1.3 1.3" << std::endl; + std::cout << "Row 5 1.3 1.3 1.3 6 1.3 1.3 1.3 1.3" << std::endl; + std::cout << "Row 6 0 0 0 4 1.3 1.3 0 0 " << std::endl; + std::cout << "Row 7 0 0 0 4 1.3 1.3 0 0 " << std::endl; + + std::cout << "After arranging dimer coef" << std::endl; + std::cout << SCoef << std::endl; + + for (int i = 0; i < 8; ++i) { + if (i != 3) { + REQUIRE(SCoef(i, 4) == Approx(1.3)); + REQUIRE(SCoef(i, 5) == Approx(1.3)); + + REQUIRE(SCoef(4, i) == Approx(1.3)); + REQUIRE(SCoef(5, i) == Approx(1.3)); + } + } + + for (int i = 0; i < 8; ++i) { + if (i == 4 || i == 5) { + REQUIRE(SCoef(i, 3) == Approx(6)); + REQUIRE(SCoef(3, i) == Approx(6)); + } else { + REQUIRE(SCoef(3, i) == Approx(4)); + REQUIRE(SCoef(i, 3) == Approx(4)); + } + } + } +} From e9f9fd3dd432d300b19c1b503c014784ed6b8279 Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Fri, 24 Jul 2020 21:47:01 -0600 Subject: [PATCH 48/68] Add missing header file --- src/libcatnip/swap_engine.hpp | 84 +++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 src/libcatnip/swap_engine.hpp diff --git a/src/libcatnip/swap_engine.hpp b/src/libcatnip/swap_engine.hpp new file mode 100644 index 0000000..a673b17 --- /dev/null +++ b/src/libcatnip/swap_engine.hpp @@ -0,0 +1,84 @@ + + +#include "swap_engine.hpp" + +#include "atom.hpp" +#include "atom_group.hpp" + +namespace catnip { + + // Swaps rows columns and keeps up with how future swaps should be updated + class SwapEngine { + private: + size_t size_; + IndexMap ind_map_; + Eigen::MatrixXd scratch_; + + public: + SwapEngine(IndexMap ind_map, size_t size) : + size_(size), ind_map_(ind_map) { + scratch_ = Eigen::MatrixXd::Zero(size, 1); + + + // Already have enough information to calculate the correct swap order + // Note the order of swaps is important. + for ( std::pair> group_row : ind_map_.row_col_init ){ + int group_ind = group_row.first; + for ( int row : group_row.second ) { + int final_row = ind_map_.row_col_final[group_ind].at(row); + std::pair swap(row,final_row); + // Now we need to update index map, the row located at the final + // position has now been moved + auto group_and_row_ind = ind_map_.findLocation(final_row); + + // Final row location needs to be pointed to the starting row + ind_map_.row_col_init[group_and_row_ind.first].at(group_and_row_ind.second) = row; + } + } + }; + + + // This method of swapping was chosen to keep the memory footprint + // reasonable. + // Will correctly sort the rows and columns of the matrix + void arrange(Eigen::MatrixXd & mat) { + + // Check that matrix is square + if( mat.rows() != mat.cols() ) { + throw std::runtime_error("Can only arrange square matrices"); + } + if( mat.rows() != size_ ) { + throw std::runtime_error("Index map has different number of basis functions to matrix"); + } + + for ( std::pair> group_row : ind_map_.row_col_init ){ + int group_ind = group_row.first; + for ( int row : group_row.second ) { + int final_row = ind_map_.row_col_final[group_ind].at(row); + if(final_row == row ) continue; + // Copy the data at the final row into the scratch space + scratch_.col(0) = mat.row(final_row); + // Copy the data from the initial row into the final row + mat.row(final_row) = mat.row(row); + // Copy the data from the temporary row into the initial row + mat.row(row) = scratch_.col(0); + } + } + + // Repeat for columns + for ( std::pair> group_col : ind_map_.row_col_init ){ + int group_ind = group_col.first; + for ( int col : group_col.second ) { + int final_col = ind_map_.row_col_final[group_ind].at(col); + if(final_col == col ) continue; + // Copy the data at the final row into the scratch space + scratch_.col(0) = mat.col(final_col); + // Copy the data from the initial row into the final row + mat.col(final_col) = mat.col(col); + // Copy the data from the temporary row into the initial row + mat.col(col) = scratch_.col(0); + } + } + } + }; +} // namespace catnip From 7d18f35f2356fe3cc83a7219105d307c02d0bb22 Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Fri, 24 Jul 2020 21:47:23 -0600 Subject: [PATCH 49/68] Small fix to CMakeLists.txt --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 93d229e..0498611 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ set(calcJ_TITLE "\"CATNIP\"") set(calcJ_URL "\"https://github.com/JoshuaSBrown/QC_Tools\"" ) set(COVERAGE_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") set(COMMON_LIBRARIES stdc++ m) -set(LOG_LEVEL 0 CACHE INT "Choose the log level" ) +set(LOG_LEVEL 0 CACHE STRING "Choose the log level" ) # Prevents multiple file extensions from being appended one after the other # important for using gcov .o.gcno or .cpp.gcno now will be .gcno set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1) From 7c6d40e2950a08fcf0fceeba1624999c31e4c874 Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Fri, 24 Jul 2020 21:58:43 -0600 Subject: [PATCH 50/68] Add back missing executable --- src/tools/calcJ.cpp | 172 ++++++++++++++++++++++++++++++++++++++++++++ src/tools/main.cpp | 172 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 344 insertions(+) create mode 100644 src/tools/calcJ.cpp create mode 100644 src/tools/main.cpp diff --git a/src/tools/calcJ.cpp b/src/tools/calcJ.cpp new file mode 100644 index 0000000..51098f2 --- /dev/null +++ b/src/tools/calcJ.cpp @@ -0,0 +1,172 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../libcatnip/io/argumentparser.hpp" +#include "../libcatnip/io/file_readers/logreader.hpp" +#include "../libcatnip/io/file_readers/punreader.hpp" +#include "../libcatnip/io/io.hpp" +#include "../libcatnip/log.hpp" +#include "../libcatnip/parameters.hpp" +#include "../libcatnip/qc_functions.hpp" +#include "../libcatnip/matrix.hpp" +#include "../libcatnip/calcJconfig.hpp" + +#include + +using namespace catnip; +using namespace std; + +int main(int argc, const char *argv[]) { + cout << endl; + cout << "Running calc_J VERSION " << calcJ_VERSION_MAJOR << "."; + cout << calcJ_VERSION_MINOR << endl; + + string line; + LOG("Preparing parser", 1); + auto ArgPars = prepareParser(); + LOG("Parsing arguments", 1); + ArgPars->parse(argv, argc); + LOG("Preparing parameter object", 1); + auto par = prepareParameters(ArgPars); + + cout << "log file for first monomer is: " + par->getLog1() + '\n'; + cout << "log file for second monomer is: " + par->getLog2() + '\n'; + cout << "log file for dimer is: " + par->getLogP() + '\n'; + cout << "pun file for the first monomer is: " + par->getPun1() + '\n'; + cout << "pun file for the second monomer is: " + par->getPun2() + '\n'; + cout << "pun file for the dimer is: " + par->getPunP() + '\n'; + + // Open the .pun file find the total number of molecular orbitals + + LOG("Reading pun files", 1); + LOG("Reading pun file: " + par->getPunP(), 2); + PunReader pr_P(par->getPunP()); + pr_P.read(); + LOG("Reading pun file: " + par->getPun1(), 2); + PunReader pr_1(par->getPun1()); + pr_1.read(); + LOG("Reading pun file: " + par->getPun2(), 2); + PunReader pr_2(par->getPun2()); + pr_2.read(); + + LOG("Reading log files", 1); + LOG("Reading log file: " + par->getLogP(), 2); + LogReader lr_P(par->getLogP()); + lr_P.read(); + LOG("Reading log file: " + par->getLog1(), 2); + LogReader lr_1(par->getLog1()); + lr_1.read(); + LOG("Reading log file: " + par->getLog2(), 2); + LogReader lr_2(par->getLog2()); + lr_2.read(); + // Load in general coefficients + + // If there are only alpha orbitals then we can assume that restricted HF + // was used + + // No need to worry about beta orbitals + + { + Eigen::MatrixXd mat_S = lr_P.getOverlapMatrix(); + + Eigen::MatrixXd mat_P_Coef = pr_P.getCoefsMatrix(par->getSpinP()); + + Eigen::VectorXd vec_P_OE = Eigen::VectorXd(lr_P.getOE(par->getSpinP())); + + int HOMO1 = lr_1.getHOMOLevel(par->getSpin1()); + LOG("Getting " + par->getSpin1() + " of monomer 1", 2); + Eigen::MatrixXd mat_1_Coef = pr_1.getCoefsMatrix(par->getSpin1()); + Eigen::VectorXd vec_1_OE = lr_1.getOE(par->getSpin1()); + + int HOMO2 = lr_2.getHOMOLevel(par->getSpin2()); + LOG("Getting " + par->getSpin2() + " of monomer 2", 2); + Eigen::MatrixXd mat_2_Coef = pr_2.getCoefsMatrix(par->getSpin2()); + Eigen::VectorXd vec_2_OE = lr_2.getOE(par->getSpin2()); + + // Unscramble dimer coef and energies first need to see how the dimer + // and monomer coefficients line up. To determine how the ceofficients + // line up we will first look at how the atoms appear in each of the + // .gjf files. We will also check to see how many coefficients are + // assocaited with each of the atoms by checking the .log files. Given + // the position of the atoms in the monomer unit and the positions of + // the atoms in the dimer we can determine how the coefficients need + // to be rearranged. + vector> coord_P = lr_P.getCoords(); + vector> coord_1 = lr_1.getCoords(); + vector> coord_2 = lr_2.getCoords(); + + // Convert coords to matrices + Eigen::MatrixXd coord_P_mat = convert(coord_P); + Eigen::MatrixXd coord_1_mat = convert(coord_1); + Eigen::MatrixXd coord_2_mat = convert(coord_2); + + vector basis_P = lr_P.getBasisFuncCount(); + vector basis_1 = lr_1.getBasisFuncCount(); + vector basis_2 = lr_2.getBasisFuncCount(); + + LOG("Creating transfercomplex", 1); + TransferComplex TC(mat_1_Coef, mat_2_Coef, mat_P_Coef, HOMO1, HOMO2, mat_S, + vec_P_OE, par->getCounterPoise()); + + // Set the transfer complex to counterpoise if it is the case. + // If the basis function search returns 0 for any of the components then + // we cannot automatically determine what the transfer integral is + if (basis_1.size() != 0 && basis_2.size() != 0 && basis_P.size() != 0) { + LOG("Unscrambling matrices", 1); + TC.unscramble(coord_1_mat, coord_2_mat, coord_P_mat, basis_P, basis_2); + } + + cout << endl; + cout << "Dimer Spin " << par->getSpinP() << endl; + + cout << "Monomer 1 Spin " << par->getSpin1() << " "; + if (par->getOrbNum1() == 0) { + cout << "Orbital " << par->getOrbType1() << endl; + } else if (par->getOrbNum1() > 0) { + cout << "Orbital " << par->getOrbType1(); + cout << "+" << par->getOrbNum1() << endl; + } else { + cout << "Orbital " << par->getOrbType1(); + cout << par->getOrbNum1() << endl; + } + + cout << "Monomer 2 Spin " << par->getSpin2() << " "; + if (par->getOrbNum2() == 0) { + cout << "Orbital " << par->getOrbType2() << endl; + } else if (par->getOrbNum2() > 0) { + cout << "Orbital " << par->getOrbType2(); + cout << "+" << par->getOrbNum2() << endl; + } else { + cout << "Orbital " << par->getOrbType2(); + cout << par->getOrbNum2() << endl; + } + + map orbitaltypes; + map orbitalnums; + orbitaltypes["mon1"] = par->getOrbType1(); + orbitaltypes["mon2"] = par->getOrbType2(); + orbitalnums["mon1"] = par->getOrbNum1(); + orbitalnums["mon2"] = par->getOrbNum2(); + + LOG("Calculating transfer integral", 1); + TC.calcJ(); + if(par->getPrintSwitch()){ + TC.printAll(); + }else{ + TC.printTransferIntegral(orbitaltypes, orbitalnums); + } + } + + return 0; +} diff --git a/src/tools/main.cpp b/src/tools/main.cpp new file mode 100644 index 0000000..51098f2 --- /dev/null +++ b/src/tools/main.cpp @@ -0,0 +1,172 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../libcatnip/io/argumentparser.hpp" +#include "../libcatnip/io/file_readers/logreader.hpp" +#include "../libcatnip/io/file_readers/punreader.hpp" +#include "../libcatnip/io/io.hpp" +#include "../libcatnip/log.hpp" +#include "../libcatnip/parameters.hpp" +#include "../libcatnip/qc_functions.hpp" +#include "../libcatnip/matrix.hpp" +#include "../libcatnip/calcJconfig.hpp" + +#include + +using namespace catnip; +using namespace std; + +int main(int argc, const char *argv[]) { + cout << endl; + cout << "Running calc_J VERSION " << calcJ_VERSION_MAJOR << "."; + cout << calcJ_VERSION_MINOR << endl; + + string line; + LOG("Preparing parser", 1); + auto ArgPars = prepareParser(); + LOG("Parsing arguments", 1); + ArgPars->parse(argv, argc); + LOG("Preparing parameter object", 1); + auto par = prepareParameters(ArgPars); + + cout << "log file for first monomer is: " + par->getLog1() + '\n'; + cout << "log file for second monomer is: " + par->getLog2() + '\n'; + cout << "log file for dimer is: " + par->getLogP() + '\n'; + cout << "pun file for the first monomer is: " + par->getPun1() + '\n'; + cout << "pun file for the second monomer is: " + par->getPun2() + '\n'; + cout << "pun file for the dimer is: " + par->getPunP() + '\n'; + + // Open the .pun file find the total number of molecular orbitals + + LOG("Reading pun files", 1); + LOG("Reading pun file: " + par->getPunP(), 2); + PunReader pr_P(par->getPunP()); + pr_P.read(); + LOG("Reading pun file: " + par->getPun1(), 2); + PunReader pr_1(par->getPun1()); + pr_1.read(); + LOG("Reading pun file: " + par->getPun2(), 2); + PunReader pr_2(par->getPun2()); + pr_2.read(); + + LOG("Reading log files", 1); + LOG("Reading log file: " + par->getLogP(), 2); + LogReader lr_P(par->getLogP()); + lr_P.read(); + LOG("Reading log file: " + par->getLog1(), 2); + LogReader lr_1(par->getLog1()); + lr_1.read(); + LOG("Reading log file: " + par->getLog2(), 2); + LogReader lr_2(par->getLog2()); + lr_2.read(); + // Load in general coefficients + + // If there are only alpha orbitals then we can assume that restricted HF + // was used + + // No need to worry about beta orbitals + + { + Eigen::MatrixXd mat_S = lr_P.getOverlapMatrix(); + + Eigen::MatrixXd mat_P_Coef = pr_P.getCoefsMatrix(par->getSpinP()); + + Eigen::VectorXd vec_P_OE = Eigen::VectorXd(lr_P.getOE(par->getSpinP())); + + int HOMO1 = lr_1.getHOMOLevel(par->getSpin1()); + LOG("Getting " + par->getSpin1() + " of monomer 1", 2); + Eigen::MatrixXd mat_1_Coef = pr_1.getCoefsMatrix(par->getSpin1()); + Eigen::VectorXd vec_1_OE = lr_1.getOE(par->getSpin1()); + + int HOMO2 = lr_2.getHOMOLevel(par->getSpin2()); + LOG("Getting " + par->getSpin2() + " of monomer 2", 2); + Eigen::MatrixXd mat_2_Coef = pr_2.getCoefsMatrix(par->getSpin2()); + Eigen::VectorXd vec_2_OE = lr_2.getOE(par->getSpin2()); + + // Unscramble dimer coef and energies first need to see how the dimer + // and monomer coefficients line up. To determine how the ceofficients + // line up we will first look at how the atoms appear in each of the + // .gjf files. We will also check to see how many coefficients are + // assocaited with each of the atoms by checking the .log files. Given + // the position of the atoms in the monomer unit and the positions of + // the atoms in the dimer we can determine how the coefficients need + // to be rearranged. + vector> coord_P = lr_P.getCoords(); + vector> coord_1 = lr_1.getCoords(); + vector> coord_2 = lr_2.getCoords(); + + // Convert coords to matrices + Eigen::MatrixXd coord_P_mat = convert(coord_P); + Eigen::MatrixXd coord_1_mat = convert(coord_1); + Eigen::MatrixXd coord_2_mat = convert(coord_2); + + vector basis_P = lr_P.getBasisFuncCount(); + vector basis_1 = lr_1.getBasisFuncCount(); + vector basis_2 = lr_2.getBasisFuncCount(); + + LOG("Creating transfercomplex", 1); + TransferComplex TC(mat_1_Coef, mat_2_Coef, mat_P_Coef, HOMO1, HOMO2, mat_S, + vec_P_OE, par->getCounterPoise()); + + // Set the transfer complex to counterpoise if it is the case. + // If the basis function search returns 0 for any of the components then + // we cannot automatically determine what the transfer integral is + if (basis_1.size() != 0 && basis_2.size() != 0 && basis_P.size() != 0) { + LOG("Unscrambling matrices", 1); + TC.unscramble(coord_1_mat, coord_2_mat, coord_P_mat, basis_P, basis_2); + } + + cout << endl; + cout << "Dimer Spin " << par->getSpinP() << endl; + + cout << "Monomer 1 Spin " << par->getSpin1() << " "; + if (par->getOrbNum1() == 0) { + cout << "Orbital " << par->getOrbType1() << endl; + } else if (par->getOrbNum1() > 0) { + cout << "Orbital " << par->getOrbType1(); + cout << "+" << par->getOrbNum1() << endl; + } else { + cout << "Orbital " << par->getOrbType1(); + cout << par->getOrbNum1() << endl; + } + + cout << "Monomer 2 Spin " << par->getSpin2() << " "; + if (par->getOrbNum2() == 0) { + cout << "Orbital " << par->getOrbType2() << endl; + } else if (par->getOrbNum2() > 0) { + cout << "Orbital " << par->getOrbType2(); + cout << "+" << par->getOrbNum2() << endl; + } else { + cout << "Orbital " << par->getOrbType2(); + cout << par->getOrbNum2() << endl; + } + + map orbitaltypes; + map orbitalnums; + orbitaltypes["mon1"] = par->getOrbType1(); + orbitaltypes["mon2"] = par->getOrbType2(); + orbitalnums["mon1"] = par->getOrbNum1(); + orbitalnums["mon2"] = par->getOrbNum2(); + + LOG("Calculating transfer integral", 1); + TC.calcJ(); + if(par->getPrintSwitch()){ + TC.printAll(); + }else{ + TC.printTransferIntegral(orbitaltypes, orbitalnums); + } + } + + return 0; +} From 2dc07653ee8fa0734313bae4f877045fd325122b Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Sat, 25 Jul 2020 18:52:38 -0600 Subject: [PATCH 51/68] Add CMakeLists.txt file for binary --- src/tools/CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/tools/CMakeLists.txt diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt new file mode 100644 index 0000000..30e0830 --- /dev/null +++ b/src/tools/CMakeLists.txt @@ -0,0 +1,5 @@ +add_executable(calcJ calcJ.cpp) +target_link_libraries(calcJ libcatnip) +install(TARGETS calcJ EXPORT VOTCA_CSG_Targets RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +add_executable(CATNIP::calcJ ALIAS calcJ) +set_property(TARGET catnip APPEND PROPERTY BINARIES "calcJ") From 89d55e7d3f37b44fca88857e741b0b8814b0f3ba Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Sat, 25 Jul 2020 18:53:53 -0600 Subject: [PATCH 52/68] Switch project name to catnip as opposed to calcJ --- CMakeLists.txt | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0498611..6cf6edb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,13 +13,13 @@ option(CODE_COVERAGE "Enable coverage reporting" OFF) ############################################################################## # Defining settings ############################################################################## -set(calcJ_VERSION_MAJOR 2 ) -set(calcJ_VERSION_MINOR 0 ) -set(calcJ_YEAR_PUBLISHED 2018 ) -set(calcJ_AUTHOR_SURNAME "\"Brown\"" ) -set(calcJ_AUTHOR_INITIALS "\"J. S.\"" ) -set(calcJ_TITLE "\"CATNIP\"") -set(calcJ_URL "\"https://github.com/JoshuaSBrown/QC_Tools\"" ) +set(catnip_VERSION_MAJOR 2 ) +set(catnip_VERSION_MINOR 0 ) +set(catnip_YEAR_PUBLISHED 2018 ) +set(catnip_AUTHOR_SURNAME "\"Brown\"" ) +set(catnip_AUTHOR_INITIALS "\"J. S.\"" ) +set(catnip_TITLE "\"CATNIP\"") +set(catnip_URL "\"https://github.com/JoshuaSBrown/QC_Tools\"" ) set(COVERAGE_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") set(COMMON_LIBRARIES stdc++ m) set(LOG_LEVEL 0 CACHE STRING "Choose the log level" ) @@ -32,8 +32,8 @@ set(CMAKE_CXX_FLAGS "-Wall -std=c++11 -Werror") ############################################################################## # Configure header file to pass some of the CMake settings to the source code configure_file( - "${PROJECT_SOURCE_DIR}/src/libcatnip/calcJconfig.hpp.in" - "${PROJECT_SOURCE_DIR}/src/libcatnip/calcJconfig.hpp" + "${PROJECT_SOURCE_DIR}/src/libcatnip/catnipconfig.hpp.in" + "${PROJECT_SOURCE_DIR}/src/libcatnip/catnipconfig.hpp" ) ############################################################################## @@ -103,7 +103,7 @@ endif() # Compiling build tree/paths ############################################################################## # Add the binary tree to the search path for include files -# so that we will find calcJconfig.hpp +# so that we will find catnipconfig.hpp #target_include_directories(calc_J "${PROJECT_BINARY_DIR}/src") #target_link_directories(calc_J "${PROJECT_BINARY_DIR}/src") From 2b084ae293acc01298d3b277ebe10a8274b20ac4 Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Sat, 25 Jul 2020 18:55:12 -0600 Subject: [PATCH 53/68] move calcJ config file to catnip config file --- src/libcatnip/catnip_config.hpp.in | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 src/libcatnip/catnip_config.hpp.in diff --git a/src/libcatnip/catnip_config.hpp.in b/src/libcatnip/catnip_config.hpp.in new file mode 100644 index 0000000..4632328 --- /dev/null +++ b/src/libcatnip/catnip_config.hpp.in @@ -0,0 +1,18 @@ +// Configured options and settings for catnip + +#ifndef CATNIP_CONFIG_HPP +#define CATNIP_CONFIG_HPP + +#include + +namespace catnip { + const int catnip_VERSION_MAJOR = @catnip_VERSION_MAJOR@; + const int catnip_VERSION_MINOR = @catnip_VERSION_MINOR@; + const int catnip_YEAR_PUBLISHED = @catnip_YEAR_PUBLISHED@; + const std::string catnip_AUTHOR_SURNAME = @catnip_AUTHOR_SURNAME@; + const std::string catnip_AUTHOR_INITIALS = @catnip_AUTHOR_INITIALS@; + const std::string catnip_TITLE = @catnip_TITLE@; + const std::string catnip_URL = @catnip_URL@; +} // namespace catnip + +#endif // CATNIP_CONFIG_HPP From f007e82f73c6759c79c76c13234553a9d3a4c15c Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Sat, 25 Jul 2020 19:06:31 -0600 Subject: [PATCH 54/68] bump cmake version --- CMakeLists.txt | 8 ++++---- src/libcatnip/calcJconfig.hpp | 18 ------------------ 2 files changed, 4 insertions(+), 22 deletions(-) delete mode 100644 src/libcatnip/calcJconfig.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 6cf6edb..d987fa0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ -cmake_minimum_required (VERSION 2.8) -project (calc_J) +cmake_minimum_required (VERSION 3.14) +project (catnip) ############################################################################## # Defining options @@ -32,8 +32,8 @@ set(CMAKE_CXX_FLAGS "-Wall -std=c++11 -Werror") ############################################################################## # Configure header file to pass some of the CMake settings to the source code configure_file( - "${PROJECT_SOURCE_DIR}/src/libcatnip/catnipconfig.hpp.in" - "${PROJECT_SOURCE_DIR}/src/libcatnip/catnipconfig.hpp" + "${PROJECT_SOURCE_DIR}/src/libcatnip/catnip_config.hpp.in" + "${PROJECT_SOURCE_DIR}/src/libcatnip/catnip_config.hpp" ) ############################################################################## diff --git a/src/libcatnip/calcJconfig.hpp b/src/libcatnip/calcJconfig.hpp deleted file mode 100644 index e574fe9..0000000 --- a/src/libcatnip/calcJconfig.hpp +++ /dev/null @@ -1,18 +0,0 @@ -// Configured options and settings for calcJ - -#ifndef CATNIP_CONFIG_HPP -#define CATNIP_CONFIG_HPP - -#include - -namespace catnip { -const int calcJ_VERSION_MAJOR = 2; -const int calcJ_VERSION_MINOR = 0; -const int calcJ_YEAR_PUBLISHED = 2018; -const std::string calcJ_AUTHOR_SURNAME = "Brown"; -const std::string calcJ_AUTHOR_INITIALS = "J. S."; -const std::string calcJ_TITLE = "CATNIP"; -const std::string calcJ_URL = "https://github.com/JoshuaSBrown/QC_Tools"; -} // namespace catnip - -#endif // CATNIP_CONFIG_HPP From 489e6256df9b978a039a99be29c91bb50ab79239 Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Sat, 25 Jul 2020 19:14:11 -0600 Subject: [PATCH 55/68] Fix small issues --- src/libcatnip/atom_group.hpp | 20 +++++++++++++++++++- src/libcatnip/transfer_complex.cpp | 8 ++++++++ src/libcatnip/transfer_complex.hpp | 10 +++++++--- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/libcatnip/atom_group.hpp b/src/libcatnip/atom_group.hpp index a47069e..e998fa9 100644 --- a/src/libcatnip/atom_group.hpp +++ b/src/libcatnip/atom_group.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include namespace catnip { @@ -39,6 +40,11 @@ namespace catnip { Unassigned }; + enum class MatrixType { + Overlap, + Coefficients, + MolecularOrbitalsEnergies + }; /** * @brief Stores the name of the atom group, the group type and the atoms in * the group @@ -48,10 +54,22 @@ namespace catnip { private: GroupType type_ = GroupType::Unassigned; std::string name_; + // Files associated with this atom_group + std::vector file_names_; + // Matries associated with the atom group + std::unordered_map> matrices_; std::vector> atoms_; public: AtomGroup(std::string group_name) : name_(group_name) {}; - + + void addFile(const std::string file_name) { file_names_.push_back(file_name); } + + void addMatrix(const MatrixType type, std::unique_ptr mat) { matrices_[type] = std::move(mat); } + + // Attempt to load overlap matrix hopefully a log file exists which can do + // this + void loadOverlapMatrix() {}; + std::string getName() const noexcept { return name_; } size_t size() const noexcept { return atoms_.size(); } diff --git a/src/libcatnip/transfer_complex.cpp b/src/libcatnip/transfer_complex.cpp index 3638ac8..03e090c 100644 --- a/src/libcatnip/transfer_complex.cpp +++ b/src/libcatnip/transfer_complex.cpp @@ -28,6 +28,14 @@ namespace catnip { swap_eng.arrange(*(params_->complex_coefs)); swap_eng.arrange(*(params_->S_AO)); + auto dimension = mat_1_Coef.cols()+mat_2_Coef.cols(); + Eigen::MatrixXd zetaA(mat_1_Coef.rows(),dimension); + Eigen::MatrixXd zetaB(mat_2_Coef.rows(),dimension); + if (params_->counter_poise) { + + } else { + + } } void TransferComplex::calcJ() {}; diff --git a/src/libcatnip/transfer_complex.hpp b/src/libcatnip/transfer_complex.hpp index e580efd..2dbd63a 100644 --- a/src/libcatnip/transfer_complex.hpp +++ b/src/libcatnip/transfer_complex.hpp @@ -23,13 +23,17 @@ class TransferComplex { class Parameters { public: - const std::vector> monomers_coefs; - const std::unique_ptr complex_coefs; + + // It actually makes more sense to place these in the atom groups + //const std::vector> monomers_coefs; + //const std::unique_ptr complex_coefs; /// Location of each of the homo_orbitals in each of the monomers - const std::vector homo_orbitals; + //const std::vector homo_orbitals; //HOMO_A; //const int HOMO_B; /// Atomic Orbital overlap matrix + + // The Overlap matrix can be added simply when it is needed const std::unique_ptr S_AO; const std::unique_ptr complex_orbital_energies; /// Counter poise flag From 271ebee54988220e8b81eaad79edc27b10104ef9 Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Sat, 25 Jul 2020 19:14:33 -0600 Subject: [PATCH 56/68] Add missing files --- src/libcatnip/basis_map.cpp | 79 +++++++++++++++++++++++++++++++++++++ src/libcatnip/basis_map.hpp | 45 +++++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 src/libcatnip/basis_map.cpp create mode 100644 src/libcatnip/basis_map.hpp diff --git a/src/libcatnip/basis_map.cpp b/src/libcatnip/basis_map.cpp new file mode 100644 index 0000000..67e639e --- /dev/null +++ b/src/libcatnip/basis_map.cpp @@ -0,0 +1,79 @@ + + +#include "basis_map.hpp" + +#include "atom.hpp" +#include "atom_system.hpp" + +// Standard includes +#include +#include + +namespace catnip { + + BasisMap::BasisMap(AtomSystem atm_sys){ + if ( not atm_sys.systemComplete() ) { + throw std::runtime_error("Cannot build an index map from an incomplete " + "atom system."); + } + + // 1. map each of the atoms in complex to an offset based on the number + // of basis functions up to that point, + // E.g. + // atom1 2 basis functs + // atom2 3 basis functs + // atom3 1 basis functs + // + // offset_map[0] = 0; // atom1 + // offset_map[1] = 2; // atom2 + // offset_map[2] = 5; // atom3 + + std::unordered_map offset_map; + const AtomGroup & complex_grp = atm_sys.getComplex(); + int offset = 0; + int complex_atm_ind = 0; + for ( const std::shared_ptr & atm_ptr : complex_grp){ + offset_map[complex_atm_ind] = offset; + offset += atm_ptr->getBasisFuncCount(); + ++complex_atm_ind; + } + + std::vector component_indices = atm_sys.getComponentIndices(); + int sys_ind = 0; + for ( int & component_ind : component_indices) { + const AtomGroup & component_grp = atm_sys.at(component_ind); + std::cout << "Component grp " << component_grp.getName() << " component ind " << component_ind << " size " << component_grp.size() << std::endl; + for( const std::shared_ptr & atm_ptr : component_grp){ + std::vector atm_indices = complex_grp.find(atm_ptr->getPos()); + assert(atm_indices.size() == 1); + int atm_ind = atm_indices.at(0); + int num_basis = complex_grp.at(atm_ind)->getBasisFuncCount(); + int complex_offset = offset_map[atm_ind]; + + for ( int ind_temp = 0; ind_temp BasisMap::findLocation(int row){ + for( std::pair> group_rows : row_col_current){ + int row_ind = 0; + for ( int row_ : group_rows.second ){ + if (row_ == row){ + return std::pair(group_rows.first, row_ind); + } + ++row_ind; + } + } + return std::pair(); + } + +} // namespace catnip diff --git a/src/libcatnip/basis_map.hpp b/src/libcatnip/basis_map.hpp new file mode 100644 index 0000000..42517ab --- /dev/null +++ b/src/libcatnip/basis_map.hpp @@ -0,0 +1,45 @@ + +#pragma once +#ifndef _CATNIP_INDEX_MAP_HPP +#define _CATNIP_INDEX_MAP_HPP + +// Local private includes +#include "atom_system.hpp" + +// Standard includes +#include +#include + +namespace catnip { + + + /** + * @brief This class tracks how the basis functions map to the rows in the + * complex + */ + class BasisMap { + public: + BasisMap() = default; + BasisMap(AtomSystem atm_sys); + // The component rows and colums in their current locations in + // in the full system matrix of the complex + std::map> row_col_current; + + // Map indicate where the rows and cols should go in the final state + // Each int in the vector represents the location in the full system matrix + std::map> row_col_final; + + /** + * @brief Given a row of the complex finds it's location in one of the + * components + * + * @param row_complex + * + * @return + */ + std::pair findLocation(int row_complex); + }; + + +} // namespace catnip +#endif // _CATNIP_INDEX_MAP_HPP From 15bcb8fb63cb4f148875c779f077348aa3be9fb0 Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Sat, 25 Jul 2020 19:17:14 -0600 Subject: [PATCH 57/68] Small fix --- src/libcatnip/atom_group.hpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/libcatnip/atom_group.hpp b/src/libcatnip/atom_group.hpp index 6647207..1d8e6de 100644 --- a/src/libcatnip/atom_group.hpp +++ b/src/libcatnip/atom_group.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -25,6 +26,16 @@ namespace catnip { Unknown }; + enum class FileType { + pun, + log + }; + + enum class MatrixType { + Overlap, + Coefficients, + MolecularOrbitalEnergies + }; /** * @brief Stores the name of the atom group, the group type and the atoms in * the group @@ -35,9 +46,15 @@ namespace catnip { GroupType type_ = GroupType::Unknown; std::string name_; std::vector> atoms_; + std::unordered_map files_; + std::unordered_map> matrices_; public: AtomGroup(std::string group_name) : name_(group_name) {}; + void addFile(FileType type, std::string file_name) { + files_[type] = file_name; + } + size_t size() const noexcept { return atoms_.size(); } std::vector>::iterator From 781dc20405bd793aba9ff25e65dd7709b29c5b87 Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Sat, 25 Jul 2020 19:45:21 -0600 Subject: [PATCH 58/68] Move to unique_ptrs to help with Memory issues because of large EIgen matrices --- src/libcatnip/atom_group.hpp | 1 + src/libcatnip/atom_group_container.cpp | 2 +- src/libcatnip/atom_group_container.hpp | 14 ++-- src/libcatnip/atom_system.cpp | 110 ++++++++++++------------- src/libcatnip/atom_system.hpp | 13 +-- 5 files changed, 71 insertions(+), 69 deletions(-) diff --git a/src/libcatnip/atom_group.hpp b/src/libcatnip/atom_group.hpp index 293503a..6f0ca80 100644 --- a/src/libcatnip/atom_group.hpp +++ b/src/libcatnip/atom_group.hpp @@ -67,6 +67,7 @@ namespace catnip { std::unordered_map files_; std::unordered_map> matrices_; public: + AtomGroup() = default; AtomGroup(std::string group_name) : name_(group_name) {}; void addFile(const std::string file_name) { file_names_.push_back(file_name); } diff --git a/src/libcatnip/atom_group_container.cpp b/src/libcatnip/atom_group_container.cpp index 4e88000..1a61a4d 100644 --- a/src/libcatnip/atom_group_container.cpp +++ b/src/libcatnip/atom_group_container.cpp @@ -185,7 +185,7 @@ namespace catnip { std::cout << "Adding group " << atom_group.getName() << std::endl; if( isUniqueGroup_(atom_group) ){ std::cout << "Is unique" << std::endl; - atom_groups_.push_back(atom_group); + atom_groups_.push_back(std::move(atom_group)); } else { return; } diff --git a/src/libcatnip/atom_group_container.hpp b/src/libcatnip/atom_group_container.hpp index 5570655..84697a1 100644 --- a/src/libcatnip/atom_group_container.hpp +++ b/src/libcatnip/atom_group_container.hpp @@ -27,7 +27,7 @@ namespace catnip { * are an island a complex or a component. */ class AtomGroupContainer { - std::vector atom_groups_; + std::vector> atom_groups_; bool group_types_uptodate_ = false; @@ -47,18 +47,18 @@ namespace catnip { // Invalidates groups if non const because cannot ensure that groups are // not changed - std::vector::iterator + std::vector>::iterator begin() { group_types_uptodate_ = false; return atom_groups_.begin(); } - std::vector::const_iterator + std::vector>::const_iterator begin() const { return atom_groups_.begin(); } // Invalidates groups if non const because cannot ensure that groups are // not changed - std::vector::iterator + std::vector>::iterator end() { group_types_uptodate_ = false; return atom_groups_.end(); } - std::vector::const_iterator + std::vector>::const_iterator end() const { return atom_groups_.end(); } void add( AtomGroup atom_group ); @@ -90,12 +90,12 @@ namespace catnip { */ std::vector getGroups(const GroupType & type) const noexcept; - AtomGroup & at(size_t ind) { + std::unique_ptr & at(size_t ind) { group_types_uptodate_ = false; return atom_groups_.at(ind); } - const AtomGroup & at(size_t ind) const { return atom_groups_.at(ind);} + const std::unique_ptr & at(size_t ind) const { return atom_groups_.at(ind);} }; diff --git a/src/libcatnip/atom_system.cpp b/src/libcatnip/atom_system.cpp index 3d802b8..0043f74 100644 --- a/src/libcatnip/atom_system.cpp +++ b/src/libcatnip/atom_system.cpp @@ -27,11 +27,11 @@ namespace catnip { static void assignBasisFunctionsToSynchronisedAtoms_( int grp_ind, const std::vector& basis_func_count, - AtomGroup & grp, - AtomGroupContainer & atm_grp_cont ){ + std::unique_ptr & grp, + std::unique_ptr & atm_grp_cont ){ int index = 0; - for( std::shared_ptr & atom_ptr : grp ){ + for( std::shared_ptr & atom_ptr : *grp ){ std::cout << "Assigning basis function atom at index " << index << std::endl; if( atom_ptr->getBasisFuncCount() == -1){ atom_ptr->setBasisFuncCount(basis_func_count.at(index)); @@ -51,15 +51,15 @@ namespace catnip { static void checkLinkedAtomsInComplexForConsistentBasisFunctionCounts( int grp_ind, - const AtomGroup & grp, - AtomGroupContainer & atm_grp_cont, + const std::unique_ptr & grp, + std::unique_ptr & atm_grp_cont, std::map>> linked_atoms ){ for ( auto grp_linked_atms : linked_atoms ){ - const AtomGroup & component = atm_grp_cont.at(grp_linked_atms.first); + const std::unique_ptr & component = atm_grp_cont->at(grp_linked_atms.first); for( std::pair linked_atoms : grp_linked_atms.second ){ - if ( component.at(linked_atoms.first)->getBasisFuncCount() != -1){ - if ( component.at(linked_atoms.first)->getBasisFuncCount() != grp.at(linked_atoms.second)->getBasisFuncCount()){ + if ( component->at(linked_atoms.first)->getBasisFuncCount() != -1){ + if ( component->at(linked_atoms.first)->getBasisFuncCount() != grp->at(linked_atoms.second)->getBasisFuncCount()){ throw std::runtime_error("There are inconsistencies between the " "the number of basis functions used in a linked atom. Atoms " "in a component must contain the same number of basis " @@ -72,17 +72,17 @@ namespace catnip { static void checkLinkedAtomsInComponentForConsistentBasisFunctionCounts( int grp_ind, - const AtomGroup & grp, - AtomGroupContainer & atm_grp_cont, + const std::unique_ptr & grp, + std::unique_ptr & atm_grp_cont, std::map>> linked_atoms ) { - std::vector complex_grps = atm_grp_cont.getGroups(GroupType::Complex); + std::vector complex_grps = atm_grp_cont->getGroups(GroupType::Complex); assert(complex_grps.size() == 1 && "There must be at least one complex"); - const AtomGroup & complex_grp = atm_grp_cont.at(complex_grps.at(0)); + const std::unique_ptr & complex_grp = atm_grp_cont->at(complex_grps.at(0)); for( std::pair linked_atoms : linked_atoms[grp_ind] ){ - if ( complex_grp.at(linked_atoms.second)->getBasisFuncCount() != -1){ - if ( complex_grp.at(linked_atoms.second)->getBasisFuncCount() != grp.at(linked_atoms.first)->getBasisFuncCount()){ + if ( complex_grp->at(linked_atoms.second)->getBasisFuncCount() != -1){ + if ( complex_grp->at(linked_atoms.second)->getBasisFuncCount() != grp->at(linked_atoms.first)->getBasisFuncCount()){ throw std::runtime_error("There are inconsistencies between the " "the number of basis functions used in a linked atom. Atoms " "in a component must contain the same number of basis " @@ -105,13 +105,13 @@ namespace catnip { static void assignBasisFuncs_( int grp_ind, const std::vector& basis_func_count, - AtomGroupContainer & atm_grp_cont, + std::unique_ptr & atm_grp_cont, std::map>> linked_atoms ) { // Cycle through the atoms in the complex and assign the correct number of // basis functions - AtomGroup & grp = atm_grp_cont.at(grp_ind); + std::unique_ptr & grp = atm_grp_cont->at(grp_ind); std::cout << "Assign to Synchronize atoms" << std::endl; assignBasisFunctionsToSynchronisedAtoms_( grp_ind, @@ -119,7 +119,7 @@ namespace catnip { grp, atm_grp_cont); // Make sure that there are no inconsistencies between the linked atoms - if ( atm_grp_cont.at(grp_ind).is(GroupType::Complex)){ + if ( atm_grp_cont->at(grp_ind)->is(GroupType::Complex)){ // If it is a complex std::cout << "Assign to Linked atoms in complex" << std::endl; checkLinkedAtomsInComplexForConsistentBasisFunctionCounts( @@ -158,9 +158,9 @@ namespace catnip { return all_paired_atoms; }*/ - static void checkValidSystemCriteria_(AtomGroupContainer & atm_grp_cont){ + static void checkValidSystemCriteria_(std::unique_ptr & atm_grp_cont){ std::vector complex_indices = - atm_grp_cont.getGroups(GroupType::Complex); + atm_grp_cont->getGroups(GroupType::Complex); if( complex_indices.size() == 0 ){ throw std::runtime_error("Cannot create atom system, no complexes were " @@ -172,7 +172,7 @@ namespace catnip { } std::vector component_indices = - atm_grp_cont.getGroups(GroupType::Component); + atm_grp_cont->getGroups(GroupType::Component); if ( component_indices.size() < 2){ throw std::runtime_error("Cannot create atom system, must contain at " @@ -185,34 +185,34 @@ namespace catnip { // first int of the pair - index of the atom in the component // second int of the pair - index of the linked atom in the complex static std::map>> findNonConsistentAtoms_( - AtomGroupContainer & atm_grp_cont) { + std::unique_ptr & atm_grp_cont) { std::map>> linked_atoms; // Overwrite any of the pointers in the component that have the same atom // with the complex, with the atom pointer from the complex int complex_index = - atm_grp_cont.getGroups(GroupType::Complex).at(0); + atm_grp_cont->getGroups(GroupType::Complex).at(0); std::vector component_indices = - atm_grp_cont.getGroups(GroupType::Component); + atm_grp_cont->getGroups(GroupType::Component); - AtomGroup & atm_complex = atm_grp_cont.at(complex_index); + std::unique_ptr & atm_complex = atm_grp_cont->at(complex_index); for ( const int component_ind : component_indices){ - AtomGroup & atm_grp = atm_grp_cont.at(component_ind); + std::unique_ptr & atm_grp = atm_grp_cont->at(component_ind); // Cycle atoms in atm_grp int ind_atm = 0; - for ( std::shared_ptr & atm : atm_grp){ - std::vector complex_atm_ind = atm_complex.find(atm->getPos()); + for ( std::shared_ptr & atm : *atm_grp){ + std::vector complex_atm_ind = atm_complex->find(atm->getPos()); // This vector must be of size 1 if( complex_atm_ind.size() == 1){ // If the elements dont' match it is non-consistent - if( atm_complex.at(complex_atm_ind.at(0))->getElement() != atm_grp.at(ind_atm)->getElement() ){ + if( atm_complex->at(complex_atm_ind.at(0))->getElement() != atm_grp->at(ind_atm)->getElement() ){ linked_atoms[component_ind].push_back(std::pair(ind_atm,complex_atm_ind.at(0))); } }else if (complex_atm_ind.size() == 0) { std::string error_msg = "A component atom did not have a matching " - "atom in the complex (" + atm_complex.getName() + "). The " - "atom in the component (" + atm_grp.getName() + ") does not have " + "atom in the complex (" + atm_complex->getName() + "). The " + "atom in the component (" + atm_grp->getName() + ") does not have " "to have the same element as the atom in the complex but must " "share the same position."; throw std::runtime_error(error_msg); @@ -227,26 +227,26 @@ namespace catnip { return linked_atoms; } - static void synchroniseAtoms_(AtomGroupContainer & atm_grp_cont){ + static void synchroniseAtoms_(std::unique_ptr & atm_grp_cont){ // Overwrite any of the pointers in the component that have the same atom // with the complex, with the atom pointer from the complex int complex_index = - atm_grp_cont.getGroups(GroupType::Complex).at(0); + atm_grp_cont->getGroups(GroupType::Complex).at(0); std::vector component_indices = - atm_grp_cont.getGroups(GroupType::Component); + atm_grp_cont->getGroups(GroupType::Component); - AtomGroup & atm_complex = atm_grp_cont.at(complex_index); + std::unique_ptr & atm_complex = atm_grp_cont->at(complex_index); for ( const int component_ind : component_indices){ - AtomGroup & atm_grp = atm_grp_cont.at(component_ind); + std::unique_ptr & atm_grp = atm_grp_cont->at(component_ind); // Cycle atoms in atm_grp - for ( std::shared_ptr & atm : atm_grp){ - std::vector complex_atm_ind = atm_complex.find(atm); + for ( std::shared_ptr & atm : *atm_grp){ + std::vector complex_atm_ind = atm_complex->find(atm); // This vector should be 0 or 1 if( complex_atm_ind.size() == 1){ // Change the pointer - atm = atm_complex.at(complex_atm_ind.at(0)); + atm = atm_complex->at(complex_atm_ind.at(0)); } } } @@ -264,13 +264,13 @@ namespace catnip { * * @param atm_grp_cont */ - AtomSystem::AtomSystem(AtomGroupContainer atm_grp_cont) { - atm_grp_cont.assignGroupTypes(); + AtomSystem::AtomSystem(std::unique_ptr atm_grp_cont) { + atm_grp_cont->assignGroupTypes(); checkValidSystemCriteria_(atm_grp_cont); std::vector complex_indices = - atm_grp_cont.getGroups(GroupType::Complex); + atm_grp_cont->getGroups(GroupType::Complex); index_complex_ = complex_indices.at(0); // Searches for atoms that exist in the component that share a position with // an atom in the complex, but are of a different element @@ -281,15 +281,15 @@ namespace catnip { // in memory synchroniseAtoms_(atm_grp_cont); - atm_grp_cont_ = atm_grp_cont; + atm_grp_cont_ = std::move(atm_grp_cont); } int AtomSystem::getTotalBasisFunctions(const GroupType & type) const { int total_num_basis = 0; - std::vector group_indices = atm_grp_cont_.getGroups(type); + std::vector group_indices = atm_grp_cont_->getGroups(type); for ( int ind : group_indices ){ - const AtomGroup & group = atm_grp_cont_.at(ind); - for( const std::shared_ptr & atom_ptr : group ) { + const std::unique_ptr & group = atm_grp_cont_->at(ind); + for( const std::shared_ptr & atom_ptr : *group ) { total_num_basis += atom_ptr->getBasisFuncCount(); } } @@ -298,10 +298,10 @@ namespace catnip { int AtomSystem::getMaxBasisFunctions(const GroupType & type) const { int max_num_basis = 0; - std::vector group_indices = atm_grp_cont_.getGroups(type); + std::vector group_indices = atm_grp_cont_->getGroups(type); for ( int ind : group_indices ){ - const AtomGroup & group = atm_grp_cont_.at(ind); - for( const std::shared_ptr & atom_ptr : group ) { + const std::unique_ptr & group = atm_grp_cont_->at(ind); + for( const std::shared_ptr & atom_ptr : *group ) { if( atom_ptr->getBasisFuncCount() > max_num_basis){ max_num_basis = atom_ptr->getBasisFuncCount(); } @@ -316,7 +316,7 @@ namespace catnip { // 2. Check that the number of atoms in the grp is consistent with // the number of values provided - if ( basis_func_count.size() != atm_grp_cont_.at(index).size() ){ + if ( basis_func_count.size() != atm_grp_cont_->at(index)->size() ){ throw std::runtime_error("Cannot assign basis function count to atoms " "as the basis function count vector is not equal to the number of " "atoms in the group!"); @@ -326,25 +326,25 @@ namespace catnip { } bool AtomSystem::systemComplete() const noexcept { - for ( const AtomGroup & grp : atm_grp_cont_){ - for( const std::shared_ptr & atm : grp){ + for ( const std::unique_ptr & grp : *atm_grp_cont_){ + for( const std::shared_ptr & atm : *grp){ if(atm->getBasisFuncCount() == -1) return false; } } return true; } - const AtomGroup & AtomSystem::at(int ind) const { - return atm_grp_cont_.at(ind); + const std::unique_ptr & AtomSystem::at(int ind) const { + return atm_grp_cont_->at(ind); } std::vector AtomSystem::getLinkedAtomsWithDifferentElements() const noexcept { std::vector links; - std::string complex_name = atm_grp_cont_.at(index_complex_).getName(); + std::string complex_name = atm_grp_cont_->at(index_complex_)->getName(); for ( std::pair>> grp_links : linked_atoms_){ int component_ind = grp_links.first; - std::string component_name = atm_grp_cont_.at(component_ind).getName(); + std::string component_name = atm_grp_cont_->at(component_ind)->getName(); for ( std::pair atm1_atm2 : grp_links.second){ Link link{ component_name, // Component name diff --git a/src/libcatnip/atom_system.hpp b/src/libcatnip/atom_system.hpp index 2cfb1a7..ddc301c 100644 --- a/src/libcatnip/atom_system.hpp +++ b/src/libcatnip/atom_system.hpp @@ -8,6 +8,7 @@ // Standard includes #include +#include #include namespace catnip { @@ -27,7 +28,7 @@ namespace catnip { // Atoms in each component that share the same location with atoms in // the complex but do not share the same element std::map>> linked_atoms_; - AtomGroupContainer atm_grp_cont_; + std::unique_ptr atm_grp_cont_; int index_complex_; public: @@ -40,7 +41,7 @@ namespace catnip { int complex_atm_ind; }; - AtomSystem(AtomGroupContainer atm_cont); + AtomSystem(std::unique_ptr atm_cont); /** * @brief assign basis functions to atom group @@ -70,12 +71,12 @@ namespace catnip { int getMaxBasisFunctions(const GroupType & type) const; - const AtomGroup & getComplex() const { - return atm_grp_cont_.at(index_complex_); + const std::unique_ptr & getComplex() const { + return atm_grp_cont_->at(index_complex_); } std::vector getComponentIndices() const noexcept { - return atm_grp_cont_.getGroups(GroupType::Component); + return atm_grp_cont_->getGroups(GroupType::Component); } @@ -87,7 +88,7 @@ namespace catnip { */ std::vector getLinkedAtomsWithDifferentElements() const noexcept; - const AtomGroup & at(int ind) const; + const std::unique_ptr & at(int ind) const; /** * @brief Check that every atom knows how many basis functions are * assigned to it From a1855d1b0af93f0c68feef9b6732d6e3c23f982c Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Thu, 30 Jul 2020 23:26:08 -0600 Subject: [PATCH 59/68] Move to c++17 standard --- src/libcatnip/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcatnip/CMakeLists.txt b/src/libcatnip/CMakeLists.txt index 2f4e8d8..f5e395f 100644 --- a/src/libcatnip/CMakeLists.txt +++ b/src/libcatnip/CMakeLists.txt @@ -7,4 +7,5 @@ file(GLOB CATNIP_SOURCE_FILES io/file_readers/*.cpp) add_library(libcatnip ${CATNIP_SOURCE_FILES}) +set_property(TARGET libcatnip PROPERTY CXX_STANDARD 17) target_include_directories(libcatnip PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) From c5e08ee91ad14b1010ceb8a890fb2c18c1939a9b Mon Sep 17 00:00:00 2001 From: JoshuaSBrown Date: Thu, 30 Jul 2020 23:45:19 -0600 Subject: [PATCH 60/68] First step to refactor argumenent parsing --- .../arguments/properties/propertyobject.hpp | 62 ++++++++----------- 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/src/libcatnip/io/arguments/properties/propertyobject.hpp b/src/libcatnip/io/arguments/properties/propertyobject.hpp index 584c662..e28af14 100644 --- a/src/libcatnip/io/arguments/properties/propertyobject.hpp +++ b/src/libcatnip/io/arguments/properties/propertyobject.hpp @@ -2,6 +2,7 @@ #ifndef _CATNIP_PROPERTY_OBJECT_HPP #define _CATNIP_PROPERTY_OBJECT_HPP +#include #include #include #include @@ -13,70 +14,61 @@ namespace catnip { -template +enum class PropertyType { + UNKNOWN +}; + +enum class Option { + NO_OPTIONS +}; + class PropertyObject { protected: // Map key is the option name and the type "int, double etc" // void * points to the correct value for that type - std::map options_; + std::map options_; - bool propOptionValid_(const std::string &option) const { - for (const auto &opt : options_) { - if (opt.first.compare(option) == 0) return true; - } - return false; + bool propOptionValid_(const Option &option) const { + return options_.count(option); } - void setPropOption_(const std::string &option, const T &val) { - - if (options_.count(option) == 0) { - T *opt = new T(val); - options_[option] = static_cast(opt); - } else { - T *opt = static_cast(options_[option]); - *opt = val; - } + void setPropOption_(const Option &option, const std::any &val) { + options_[option] = val; } - virtual std::string getName_(void) const { return "UNKNOWN"; } + virtual PropertyType getPropertyType_(void) const noexcept + { return PropertyType::UNKNOWN; } - virtual std::vector getOpts_(void) const { - std::vector options{"NO_OPTIONS"}; + virtual std::vector