Skip to content

Files

This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Latest commit

b24451a · Jul 13, 2020

History

History
252 lines (212 loc) · 7.22 KB

step8-solution.md

File metadata and controls

252 lines (212 loc) · 7.22 KB

Note that this is only the code for the main() function. The Eigen package, which provides the Matrix class and associated diagonalization capabilities is described in a hint.

#include "molecule.h"
#include "masses.h"
 
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdio>
#include <cmath>
 
#include "Eigen/Dense"
#include "Eigen/Eigenvalues"
#include "Eigen/Core"
 
typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> Matrix;
typedef Eigen::Matrix<double, Eigen::Dynamic, 1> Vector;
 
using namespace std;
 
int main()
{
  Molecule mol("geom.dat", 0);
 
  cout << "Number of atoms: " << mol.natom << endl;
  cout << "Input Cartesian coordinates:\n";
  mol.print_geom();
 
  cout << "Interatomic distances (bohr):\n";
  for(int i=0; i < mol.natom; i++)
    for(int j=0; j < i; j++)
      printf("%d %d %8.5f\n", i, j, mol.bond(i,j));
 
  cout << "\nBond angles:\n";
  for(int i=0; i < mol.natom; i++) {
    for(int j=0; j < i; j++) {
      for(int k=0; k < j; k++) {
        if(mol.bond(i,j) < 4.0 && mol.bond(j,k) < 4.0)
          printf("%2d-%2d-%2d %10.6f\n", i, j, k, mol.angle(i,j,k)*(180.0/acos(-1.0)));
      }
    }
  }
 
  cout << "\nOut-of-Plane angles:\n";
  for(int i=0; i < mol.natom; i++) {
    for(int k=0; k < mol.natom; k++) {
      for(int j=0; j < mol.natom; j++) {
        for(int l=0; l < j; l++) {
          if(i!=j && i!=k && i!=l && j!=k && k!=l && mol.bond(i,k) < 4.0 && mol.bond(k,j) < 4.0 && mol.bond(k,l) < 4.0)
              printf("%2d-%2d-%2d-%2d %10.6f\n", i, j, k, l, mol.oop(i,j,k,l)*(180.0/acos(-1.0)));
        }
      }
    }
  }
 
  cout << "\nTorsional angles:\n\n";
  for(int i=0; i < mol.natom; i++) {
    for(int j=0; j < i; j++) {
      for(int k=0; k < j; k++) {
        for(int l=0; l < k; l++) {
          if(mol.bond(i,j) < 4.0 && mol.bond(j,k) < 4.0 && mol.bond(k,l) < 4.0)
            printf("%2d-%2d-%2d-%2d %10.6f\n", i, j, k, l, mol.torsion(i,j,k,l)*(180.0/acos(-1.0)));
        }
      }
    }
  }
 
  /* find the center of mass (COM) */
  double M = 0.0;
  for(int i=0; i < natom; i++) M += an2masses[(int) mol.zvals[i]];
 
  double xcm=0.0;
  double ycm=0.0;
  double zcm=0.0;
  double mi;
  for(int i=0; i < natom; i++) {
    mi = an2masses[(int) mol.zvals[i]];
    xcm += mi * mol.geom[i][0];
    ycm += mi * mol.geom[i][1];
    zcm += mi * mol.geom[i][2];
  }
  xcm /= M;
  ycm /= M;
  zcm /= M;
  printf("\nMolecular center of mass: %12.8f %12.8f %12.8f\n", xcm, ycm, zcm);
 
  mol.translate(-xcm, -ycm, -zcm);
 
  Matrix I(3,3);
 
  for(int i=0; i < mol.natom; i++) {
    mi = masses[(int) mol.zvals[i]];
    I(0,0) += mi * (mol.geom[i][1]*mol.geom[i][1] + mol.geom[i][2]*mol.geom[i][2]);
    I(1,1) += mi * (mol.geom[i][0]*mol.geom[i][0] + mol.geom[i][2]*mol.geom[i][2]);
    I(2,2) += mi * (mol.geom[i][0]*mol.geom[i][0] + mol.geom[i][1]*mol.geom[i][1]);
    I(0,1) -= mi * mol.geom[i][0]*mol.geom[i][1];
    I(0,2) -= mi * mol.geom[i][0]*mol.geom[i][2];
    I(1,2) -= mi * mol.geom[i][1]*mol.geom[i][2];
  }
 
  I(1,0) = I(0,1);
  I(2,0) = I(0,2);
  I(2,1) = I(1,2);
 
  cout << "\nMoment of inertia tensor (amu bohr^2):\n";
  cout << I << endl;
 
  // find the principal moments
  Eigen::SelfAdjointEigenSolver<Matrix> solver(I);
  Matrix evecs = solver.eigenvectors();
  Matrix evals = solver.eigenvalues();
 
  cout << "\nPrincipal moments of inertia (amu * bohr^2):\n";
  cout << evals << endl;
 
  double conv = 0.529177249 * 0.529177249;
  cout << "\nPrincipal moments of inertia (amu * AA^2):\n";
  cout << evals * conv << endl;
 
  conv = 1.6605402E-24 * 0.529177249E-8 * 0.529177249E-8;
  cout << "\nPrincipal moments of inertia (g * cm^2):\n";
  cout << evals * conv << endl;
 
  // classify the rotor 
  if(mol.natom == 2) cout << "\nMolecule is diatomic.\n";
  else if(evals(0) < 1e-4) cout << "\nMolecule is linear.\n";
  else if((fabs(evals(0) - evals(1)) < 1e-4) && (fabs(evals(1) - evals(2)) < 1e-4))
    cout << "\nMolecule is a spherical top.\n";
  else if((fabs(evals(0) - evals(1)) < 1e-4) && (fabs(evals(1) - evals(2)) > 1e-4))
    cout << "\nMolecule is an oblate symmetric top.\n";
  else if((fabs(evals(0) - evals(1)) > 1e-4) && (fabs(evals(1) - evals(2)) < 1e-4))
    cout << "\nMolecule is a prolate symmetric top.\n";
  else cout << "\nMolecule is an asymmetric top.\n";
 
  // compute the rotational constants 
  double _pi = acos(-1.0);
  conv = 6.6260755E-34/(8.0 * _pi * _pi);
  conv /= 1.6605402E-27 * 0.529177249E-10 * 0.529177249E-10;
  conv *= 1e-6;
  cout << "\nRotational constants (MHz):\n";
  cout << "\tA = " << conv/evals(0) << "\t B = " << conv/evals(1) << "\t C = " << conv/evals(2) << endl;
 
  conv = 6.6260755E-34/(8.0 * _pi * _pi);
  conv /= 1.6605402E-27 * 0.529177249E-10 * 0.529177249E-10;
  conv /= 2.99792458E10;
  cout << "\nRotational constants (cm-1):\n";
  cout << "\tA = " << conv/evals(0) << "\t B = " << conv/evals(1) << "\t C = " << conv/evals(2) << endl;
 
  return 0;
}

The above code produces the following output for the acetaldehyde test case:

Number of atoms: 7
Input Cartesian coordinates:
6       0.000000000000       0.000000000000       0.000000000000
6       0.000000000000       0.000000000000       2.845112131228
8       1.899115961744       0.000000000000       4.139062527233
1      -1.894048308506       0.000000000000       3.747688672216
1       1.942500819960       0.000000000000      -0.701145981971
1      -1.007295466862      -1.669971842687      -0.705916966833
1      -1.007295466862       1.669971842687      -0.705916966833
Interatomic distances (bohr):
1 0  2.84511
2 0  4.55395
2 1  2.29803
3 0  4.19912
3 1  2.09811
3 2  3.81330
4 0  2.06517
4 1  4.04342
4 2  4.84040
4 3  5.87463
5 0  2.07407
5 1  4.05133
5 2  5.89151
5 3  4.83836
5 4  3.38971
6 0  2.07407
6 1  4.05133
6 2  5.89151
6 3  4.83836
6 4  3.38971
6 5  3.33994

Bond angles:
 0- 1- 2 124.268308
 0- 1- 3 115.479341
 0- 4- 5  35.109529
 0- 4- 6  35.109529
 0- 5- 6  36.373677
 1- 2- 3  28.377448
 4- 5- 6  60.484476

Out-of-plane angles:
 0- 3- 1- 2  -0.000000
 0- 6- 4- 5  19.939726
 0- 6- 5- 4 -19.850523
 0- 5- 6- 4  19.850523
 1- 5- 0- 4  53.678778
 1- 6- 0- 4 -53.678778
 1- 6- 0- 5  54.977064
 2- 3- 1- 0   0.000000
 3- 2- 1- 0  -0.000000
 4- 5- 0- 1 -53.651534
 4- 6- 0- 1  53.651534
 4- 6- 0- 5 -54.869992
 4- 6- 5- 0  29.885677
 4- 5- 6- 0 -29.885677
 5- 4- 0- 1  53.626323
 5- 6- 0- 1 -56.277112
 5- 6- 0- 4  56.194621
 5- 6- 4- 0 -30.558964
 5- 4- 6- 0  31.064344
 6- 4- 0- 1 -53.626323
 6- 5- 0- 1  56.277112
 6- 5- 0- 4 -56.194621
 6- 5- 4- 0  30.558964
 6- 4- 5- 0 -31.064344

Torsional angles:

 3- 2- 1- 0 180.000000
 6- 5- 4- 0  36.366799

Molecular center of mass:   0.64494926   0.00000000   2.31663792

Moment of inertia tensor (amu bohr^2):
    156.154091561645       0.000000000000     -52.855584120568
      0.000000000000     199.371126996236       0.000000000000
    -52.855584120568       0.000000000000      54.459548882464

Principal moments of inertia (amu * bohr^2):
      31.964078  178.649562  199.371127

Principal moments of inertia (amu * AA^2):
       8.950855   50.026980   55.829610

Principal moments of inertia (g * cm^2):
    1.486325e-39 8.307181e-39 9.270731e-39

Molecule is an asymmetric top.

Rotational constants (MHz):
    A = 56461.542    B = 10102.130   C =  9052.169

Rotational constants (cm-1):
    A = 1.8834   B = 0.3370  C = 0.3019