/*************************************************************************************
* *
* ***** OpenThermo ***** *
* Calculation of thermodynamic functions from molecular data *
* Copyright 2008 Konstantin Tokarev <annulen@users.sourceforge.net> *
* and others *
* *
*************************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License. See COPYING for *
* more details *
* *
*************************************************************************************
* Module name : atom.cpp *
* Author : Tokarev. K *
* Last modification : 2008/07/23 *
* Description : This module contains definitions of class 'Atom', *
* which is used for storage of atomic symbols, coordinates, *
* weights and other properties *
* *
*************************************************************************************/
#include "atom.hpp"
#include <fstream>
#include <iomanip>
#include <cstring>
#include <string>
#include <map>
using namespace std;
bool CreateTable();
bool InitializeTable();
struct Element
{
int Number;
double Weight;
double Spin;
};
bool isInitialized = 0;
const char ElementsFileName[] = "elements.dat";
int NElements;
map <string,Element> PeriodicTable;
// Definitions of Atom
void Atom::SetAtom (double x, double y, double z, char * Name)
{
itsX = x;
itsY = y;
itsZ = z;
#ifndef SILENT
if (strlen(Name) > ATOM_NAME_LENGTH)
cerr << "# WARNING : Strange atom name encountered! Truncating to "<< ATOM_NAME_LENGTH << " symbols..." << endl;
#endif
strncpy (itsName,Name, ATOM_NAME_LENGTH);
if(!InitializeTable())
{
throw GenericError("## ERROR : Periodic Table not found or corrupted!");
return;
}
itsWeight = PeriodicTable[Name].Weight;
if (!itsWeight)
{
string e = "## ERROR : Element \"";
e += Name;
e += "\" wasn't fount in ";
e += ElementsFileName;
e += " or has zero mass";
throw GenericError(e);
return;
}
itsAtomicNumber = PeriodicTable[Name].Number;
itsNuclearSpin = PeriodicTable[Name].Spin;
}
void Atom::SetCoordinates (double x, double y, double z)
{
itsX = x;
itsY = y;
itsZ = z;
}
void Atom::GetCoordinates (double & x, double & y, double & z) const
{
x = itsX;
y = itsY;
z = itsZ;
}
double Atom::GetWeight () const
{
return itsWeight;
}
int Atom::GetAtomicNumber () const
{
return itsAtomicNumber;
}
const char * Atom::GetName () const
{
return itsName;
}
double Atom::GetNuclearSpin () const
{
return itsNuclearSpin;
}
ostream & operator<< (ostream & theStream, Atom & theAtom)
{
/*#ifndef __WATCOMC__
theStream << setw(ATOM_NAME_LENGTH) << left << theAtom.itsName << "\t";
theStream << setprecision(8);
theStream << setw(12) << showpoint << right << theAtom.itsX << "\t";
theStream << setw(12) << theAtom.itsY << "\t" ;
theStream << setw(12) << theAtom.itsZ << "\t";
theStream << setprecision(9);
theStream << setw(13) << resetiosflags(ios::showpoint) << left << theAtom.itsWeight << "\t";
theStream << setw(3) << setprecision(1) << theAtom.itsNuclearSpin << endl;
#else*/
theStream << setw(ATOM_NAME_LENGTH) << setiosflags(ios::left) << theAtom.itsName << "\t";
theStream << setprecision(8);
theStream << setw(12) << setiosflags(ios::showpoint) << setiosflags(ios::right) << theAtom.itsX << "\t";
theStream << setw(12) << theAtom.itsY << "\t" ;
theStream << setw(12) << theAtom.itsZ << "\t";
theStream << setprecision(9);
theStream << setw(13) << resetiosflags(ios::showpoint) << setiosflags(ios::left) << theAtom.itsWeight << "\t";
theStream << setw(3) << setprecision(1) << theAtom.itsNuclearSpin << endl;
//#endif
theStream << setprecision(8);
return theStream;
}
// Local definitions
bool InitializeTable ()
{
// Returns TRUE if periodic table successfully read from "thermo.dat"
// Returns FALSE on error
if(isInitialized)
return true;
ifstream fin(ElementsFileName);
if (!fin)
{
cerr << "File " << ElementsFileName << " was not found. Creating new..." << endl;
fin.close();
if (!CreateTable())
return false;
fin.open(ElementsFileName);
}
if (!fin)
{
string e = "Cannot create ";
e += ElementsFileName;
fin.close();
throw GenericError(e);
return false;
}
fin >> NElements;
for (int k=0; k<NElements; k++)
{
char Name[ATOM_NAME_LENGTH];
if(!fin) return false;
fin >> Name;
PeriodicTable[Name];
fin >> PeriodicTable[Name].Weight >> PeriodicTable[Name].Spin;
#ifdef NO_SPIN
PeriodicTable[Name].Spin = 0;
#endif
PeriodicTable[Name].Number = k+1;
}
isInitialized = true;
fin.close();
return true;
}
bool CreateTable ()
{
ofstream fout(ElementsFileName);
if(!fout.is_open())
{
string e = "## Unable to write";
e += ElementsFileName;
throw GenericError(e);
}
/* {
#ifndef SILENT
cerr << "\nUnable to write" << ElementsFileName << "\n Exiting";
return false;
#else
return <number_of_error>
#endif
}*/
fout.precision(10);
fout.width(16);
fout << "55\nH\t1.00794\t\t0.5\n";
fout << "He\t4.002602\t1.5\nLi\t6.941\t\t1.5\nBe\t9.012182\t1.5\nB\t10.811\t\t3.2\nC\t12.0107\t\t0\n";
fout << "N\t14.0067\t\t1\nO\t15.9994\t\t0\nF\t18.9984032\t0.5\nNe\t20.1797\t\t0\n";
fout << "Na\t22.98976928\t1.5\nMg\t24.305\t\t0\nAl\t26.9815386\t2.5\nSi\t28.0855\t\t0\n";
fout << "P\t30.973762\t0.5\nS\t32.065\t\t0\nCl\t35.453\t\t1.5\nAr\t39.948\t\t0\n";
fout << "K\t39.0983\t\t1.5\nCa\t40.078\t\t0\nSc\t44.955912\t3.5\nTi\t47.867\t\t0\nV\t50.9415\t\t3.5\n";
fout << "Cr\t51.9961\t\t0\nMn\t54.938045\t2.5\nFe\t55.845\t\t0\nCo\t58.933195\t3.5\nNi\t58.6934\t\t0\n";
fout << "Cu\t63.546\t\t1.5\nZn\t65.409\t\t0\nGa\t69.723\t\t1.5\nGe\t72.64\t\t0\nAs\t74.9216\t\t1.5\n";
fout << "Se\t78.96\t\t0\nBr\t79.904\t\t1.5\nKr\t83.798\t\t0\n";
fout << "Rb\t85.4678\t\t2.5\nSr\t87.62\t\t0\nY\t88.90585\t0.5\nZr\t91.224\t\t0\nNb\t92.90638\t4.5\n";
fout << "Mo\t95.94\t\t0\nTc\t98.000\t\t6\nRu\t101.07\t\t0\nRh\t102.9055\t0.5\nPd\t106.42\t\t0\nAg\t107.8682\t0.5\n";
fout << "Cd\t112.411\t\t0\nIn\t114.818\t\t4.5\nSn\t118.71\t\t0\nSb\t121.76\t\t2.5\nTe\t127.6\t\t0\n";
fout << "I\t126.90447\t2.5\nXe\t131.293\t\t0\nW\t183.84\t\t0";
fout.close();
return true;
}