From 08cee18f3207b6cea777dbbd24e17ca1a1f39ded Mon Sep 17 00:00:00 2001 From: "Ellad B. Tadmor" Date: Fri, 21 Jun 2019 18:39:18 -0500 Subject: [PATCH] Added code to define unit conversion factors --- src/KIM/kim_style.cpp | 219 ++++--- src/KIM/kim_style.h | 2 + src/KIM/kim_units.cpp | 1411 +++++++++++++++++++++++++++++++++++++++++ src/KIM/kim_units.h | 59 ++ 4 files changed, 1596 insertions(+), 95 deletions(-) create mode 100644 src/KIM/kim_units.cpp create mode 100644 src/KIM/kim_units.h diff --git a/src/KIM/kim_style.cpp b/src/KIM/kim_style.cpp index fcc3f33aa2..44d5c411ab 100644 --- a/src/KIM/kim_style.cpp +++ b/src/KIM/kim_style.cpp @@ -56,6 +56,7 @@ #include #include +#include #include "kim_style.h" #include "error.h" #include "atom.h" @@ -67,6 +68,7 @@ #include "input.h" #include "variable.h" #include "fix_store_kim.h" +#include "kim_units.h" extern "C" { #include "KIM_SimulatorHeaders.h" @@ -100,7 +102,6 @@ void KimStyle::command(int narg, char **arg) determine_model_type_and_units(model_name, user_units, &model_units); do_init(model_name, user_units, model_units); - if (unit_conversion_mode) do_variables(user_units, model_units); } else if (strcmp(arg[0],"setup") == 0) { if (!domain->box_exist) error->all(FLERR,"Must use 'kim_style setup' command after " @@ -255,7 +256,10 @@ void KimStyle::determine_model_type_and_units(char * model_name, if ((! unit_conversion_mode) && (strcmp(*model_units, user_units)!=0)) { - error->all(FLERR,"Incompatible units for KIM Simulator Model"); + std::stringstream mesg; + mesg << "Incompatible units for KIM Simulator Model, required units = " + << *model_units; + error->all(FLERR,mesg.str().c_str()); } } @@ -280,17 +284,43 @@ void KimStyle::do_init(char *model_name, char *user_units, char* model_units) fix_store->setptr("user_units", (void *) user_units); fix_store->setptr("model_units", (void *) model_units); + int kimerror; + // @@@@@ switch to c-bindings when they are available + KIM::SimulatorModel * simulatorModel; + kimerror = KIM::SimulatorModel::Create(model_name,&simulatorModel); + + const std::string *sim_name, *sim_version; + simulatorModel->GetSimulatorNameAndVersion(&sim_name, &sim_version); + + if (*sim_name != "LAMMPS") + error->all(FLERR,"Incompatible KIM Simulator Model"); + + // Begin output to log file + kim_style_log_delimiter("begin","model"); + if (comm->me == 0) { + std::string mesg("# Using KIM Simulator Model : "); + mesg += model_name; + mesg += "\n"; + mesg += "# For Simulator : "; + mesg += *sim_name + " " + *sim_version + "\n"; + mesg += "# Running on : LAMMPS "; + mesg += universe->version; + mesg += "\n"; + mesg += "#\n"; + + if (screen) fputs(mesg.c_str(),screen); + if (logfile) fputs(mesg.c_str(),logfile); + } + + // Define unit conversion factor variables and print to log + if (unit_conversion_mode) do_variables(user_units, model_units); + // set units std::string cmd("units "); cmd += model_units; input->one(cmd.c_str()); - int kimerror; - // @@@@@ switch to c-bindings when they are available - KIM::SimulatorModel * simulatorModel; - kimerror = KIM::SimulatorModel::Create(model_name,&simulatorModel); - // not a Kim Simulator Model; nothing else to do here. if (kimerror) return; @@ -318,13 +348,36 @@ void KimStyle::do_init(char *model_name, char *user_units, char* model_units) } } - // reset template map. + // End output to log file + kim_style_log_delimiter("end","model"); + // reset template map. simulatorModel->OpenAndInitializeTemplateMap(); } /* ---------------------------------------------------------------------- */ +void KimStyle::kim_style_log_delimiter(std::string begin_end, + std::string model_setup) +{ + if (comm->me == 0) { + std::string mesg; + if ((begin_end == "begin") && (model_setup == "model")) mesg = + "#=== BEGIN kim-style MODEL ==================================\n"; + else if ((begin_end == "begin") && (model_setup == "setup")) mesg = + "#=== BEGIN kim-style SETUP ==================================\n"; + else if ((begin_end == "end") && (model_setup == "model")) mesg = + "#=== END kim-style MODEL ====================================\n\n"; + else if ((begin_end == "end") && (model_setup == "setup")) mesg = + "#=== END kim-style SETUP ====================================\n\n"; + + if (screen) fputs(mesg.c_str(),screen); + if (logfile) fputs(mesg.c_str(),logfile); + } +} + +/* ---------------------------------------------------------------------- */ + void KimStyle::do_setup(int narg, char **arg) { if (narg != atom->ntypes) @@ -345,30 +398,13 @@ void KimStyle::do_setup(int narg, char **arg) simulatorModel = (KIM::SimulatorModel *)fix_store->getptr("simulator_model"); } else error->all(FLERR,"Must use 'kim_style model' before 'kim_style setup'"); + // Begin output to log file + kim_style_log_delimiter("begin","setup"); + if (simulatorModel) { - const std::string *sim_name, *sim_version; std::string atom_type_sym_list; - simulatorModel->GetSimulatorNameAndVersion(&sim_name, &sim_version); - - if (comm->me == 0) { - std::string mesg("Using KIM Simulator Model : "); - mesg += model; - mesg += "\n"; - mesg += "For Simulator : "; - mesg += *sim_name + " " + *sim_version + "\n"; - mesg += "Running on : LAMMPS "; - mesg += universe->version; - mesg += "\n"; - - if (screen) fputs(mesg.c_str(),screen); - if (logfile) fputs(mesg.c_str(),logfile); - } - - if (*sim_name != "LAMMPS") - error->all(FLERR,"Incompatible KIM Simulator Model"); - for (int i = 0; i < narg; i++) atom_type_sym_list += std::string(" ") + arg[i]; @@ -455,6 +491,10 @@ void KimStyle::do_setup(int narg, char **arg) input->one(cmd1.c_str()); input->one(cmd2.c_str()); } + + // End output to log file + kim_style_log_delimiter("end","setup"); + } /* ---------------------------------------------------------------------- */ @@ -464,85 +504,74 @@ void KimStyle::do_variables(char *user_units, char *model_units) char *from = user_units, *to = model_units; Variable *variable = input->variable; - // refuse convertion from or to reduced units + // refuse conversion from or to reduced units if ((strcmp(from,"lj") == 0) || (strcmp(to,"lj") == 0)) error->all(FLERR,"Cannot set up conversion variables for 'lj' units"); // get index to internal style variables. create, if needed. - // default to conversion factor 1.0 for newly created variables - - // @@@@@@ below needs to be updated to use Ellad's luc. - int v_length, v_mass, v_time; + // set conversion factors for newly created variables. + double conversion_factor; + int ier; char *args[3]; + std::string var_str; args[1] = (char *)"internal"; args[2] = (char *)"1.0"; - - args[0] = (char *)"_u_length"; - v_length = variable->find(args[0]); - if (v_length < 0) { - variable->set(3,args); - v_length = variable->find(args[0]); + int v_unit; + int const nunits = 14; + char *units[nunits] = {(char *)"mass", + (char *)"distance", + (char *)"time", + (char *)"energy", + (char *)"velocity", + (char *)"force", + (char *)"torque", + (char *)"temperature", + (char *)"pressure", + (char *)"viscosity", + (char *)"charge", + (char *)"dipole", + (char *)"efield", + (char *)"density"}; + + if (comm->me == 0) { + std::stringstream mesg; + mesg << "# Conversion factors from " << from << " to " << to + << ":" << std::endl; + if (screen) fputs(mesg.str().c_str(),screen); + if (logfile) fputs(mesg.str().c_str(),logfile); } - args[0] = (char *)"_u_mass"; - v_mass = variable->find(args[0]); - if (v_mass < 0) { - variable->set(3,args); - v_mass = variable->find(args[0]); - } - - args[0] = (char *)"_u_time"; - v_time = variable->find(args[0]); - if (v_time < 0) { - variable->set(3,args); - v_time = variable->find(args[0]); - } - - // special case: both unit styles are the same => conversion factor 1.0 - - if (strcmp(from,to) == 0) { - variable->internal_set(v_length,1.0); - variable->internal_set(v_mass,1.0); - variable->internal_set(v_time,1.0); - return; - } - - if (strcmp(from,"real") == 0) { - if (strcmp(to,"metal") == 0) { - variable->internal_set(v_length,1.0); - variable->internal_set(v_mass,1.0); - variable->internal_set(v_time,0.001); - } else { - std::string err("Do not know how to set up conversion variables "); - err += "between '"; - err += from; - err += "' and '"; - err += to; - err += "' units"; + for (int i = 0; i < nunits; i++) + { + var_str = std::string("_u_") + std::string(units[i]); + args[0] = (char *)var_str.c_str(); + v_unit = variable->find(args[0]); + if (v_unit < 0) { + variable->set(3,args); + v_unit = variable->find(args[0]); + } + ier = lammps_unit_conversion(units[i], + from, + to, + conversion_factor); + if (ier != 0) { + std::string err = std::string("Unable to obtain conversion factor: ") + + "unit = " + units[i] + "; " + "from = " + from + "; " + "to = " + to + "."; error->all(FLERR,err.c_str()); } - } else if (strcmp(from,"metal") == 0) { - if (strcmp(to,"real") == 0) { - variable->internal_set(v_length,1.0); - variable->internal_set(v_mass,1.0); - variable->internal_set(v_time,1000.0); - } else { - std::string err("Do not know how to set up conversion variables "); - err += "between '"; - err += from; - err += "' and '"; - err += to; - err += "' units"; - error->all(FLERR,err.c_str()); + variable->internal_set(v_unit,conversion_factor); + if (comm->me == 0) { + std::stringstream mesg; + mesg << "# " << var_str << " = " << conversion_factor << std::endl; + if (screen) fputs(mesg.str().c_str(),screen); + if (logfile) fputs(mesg.str().c_str(),logfile); } - } else { - std::string err("Do not know how to set up conversion variables "); - err += "between '"; - err += from; - err += "' and '"; - err += to; - err += "' units"; - error->all(FLERR,err.c_str()); + } + if (comm->me == 0) { + if (screen) fputs("#\n",screen); + if (logfile) fputs("#\n",logfile); } } diff --git a/src/KIM/kim_style.h b/src/KIM/kim_style.h index b7ff47404f..b18f6627ea 100644 --- a/src/KIM/kim_style.h +++ b/src/KIM/kim_style.h @@ -80,6 +80,8 @@ class KimStyle : protected Pointers { void do_init(char *, char *, char *); void do_setup(int, char **); void do_variables(char*, char*); + void kim_style_log_delimiter(std::string begin_end, + std::string model_setup); }; } diff --git a/src/KIM/kim_units.cpp b/src/KIM/kim_units.cpp new file mode 100644 index 0000000000..fe90d58e9e --- /dev/null +++ b/src/KIM/kim_units.cpp @@ -0,0 +1,1411 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: Ellad B. Tadmor (UMN) +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, see . + + Linking LAMMPS statically or dynamically with other modules is making a + combined work based on LAMMPS. Thus, the terms and conditions of the GNU + General Public License cover the whole combination. + + In addition, as a special exception, the copyright holders of LAMMPS give + you permission to combine LAMMPS with free software programs or libraries + that are released under the GNU LGPL and with code included in the standard + release of the "kim-api" under the CDDL (or modified versions of such code, + with unchanged license). You may copy and distribute such a system following + the terms of the GNU GPL for LAMMPS and the licenses of the other code + concerned, provided that you include the source code of that other code + when and as the GNU GPL requires distribution of source code. + + Note that people who make modified versions of LAMMPS are not obligated to + grant this special exception for their modified versions; it is their choice + whether to do so. The GNU General Public License gives permission to release + a modified version without this exception; this exception also makes it + possible to release a modified version which carries forward this exception. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Designed for use with the kim-api-2.0.2 (and newer) package +------------------------------------------------------------------------- */ + +#include +#include +#include +#include +using namespace std; + +namespace +{ + +// Constants of nature and basic conversion factors +// Source: https://physics.nist.gov/cuu/Constants/Table/allascii.txt +// Working with NIST values even when there are newer values for +// compatibility with LAMMPS + +/*---------------------- + Fundamental constants +------------------------ */ +double const boltz_si = 1.38064852e-23; // [J K^-1] Boltzmann's factor + // (NIST value) +double const Nav = 6.022140857e23; // [unitless] Avogadro's number + // (NIST value) +// double const Nav = 6.02214076e23; // [unitless] Avogadro's number + // (official value May 2019) +double const me = 9.10938356e-31; // [kg] electron rest mass + // (NIST value) +// double me = 9.10938291e-31; // [kg] electron rest mass +double const e_si = 1.6021766208e-19; // [C] elementary charge + // (charge of an electron/proton) + // (NIST value) + +/*---------------------- + Distance units +------------------------ */ +double const bohr_si = 5.2917721067e-11; // [m] Bohr unit (distance between + // nucleus and electron in H) + // (NIST value) +double const angstrom_si = 1e-10; // [m] Angstrom +double const centimeter_si = 1e-2; // [m] centimeter +double const micrometer_si = 1e-6; // [m] micrometer (micron) +double const nanometer_si = 1e-9; // [m] nanometer + +/*---------------------- + Mass units +------------------------ */ +double const gram_per_mole_si = 1e-3/Nav; // [kg] gram per mole +double const amu_si = 1e-3/Nav; // [kg] atomic mass unit (molecular + // weight) For example, the mean + // molecular weight of water + // is 18.015 atomic mass units + // (amu), so one mole of water + // weight 18.015 grams. +double const gram_si = 1e-3; // [kg] gram +double const picogram_si = 1e-15; // [kg] picogram +double const attogram_si = 1e-21; // [kg[ attogram + +/*---------------------- + Time units +------------------------ */ +double const atu_si = 2.418884326509e-17; // [s] atomic time unit + // ( = hbar/E_h where E_h is the + // Hartree energy) (NIST value) +double const atu_electron_si = atu_si*sqrt(amu_si/me); // [s] atomic time unit + // used in electron system (see https://sourceforge.net/p/lammps/mailman/lammps-users/thread/BCA2BDB2-BA03-4280-896F-1E6120EF47B2%40caltech.edu/) +double const microsecond_si = 1e-6; // [s] microsecond +double const nanosecond_si = 1e-9; // [s] nanosecond +double const picosecond_si = 1e-12; // [s] picosecond +double const femtosecond_si = 1e-15; // [s] femtosecond + +/*---------------------- + Density units +------------------------ */ +double const gram_per_centimetercu_si = + gram_si/pow(centimeter_si,3); // [kg/m^3] gram/centimeter^3 +double const amu_per_bohrcu_si = amu_si/pow(bohr_si,3); // [kg/m^3] amu/bohr^3 +double const picogram_per_micrometercu_si = + picogram_si/pow(micrometer_si,3); // [kg/m^3] picogram/micrometer^3 +double const attogram_per_nanometercu_si = + attogram_si/pow(nanometer_si,3); // [kg/m^3] attogram/ + // nanomaterial^3 + +/*---------------------- + Energy/torque units +------------------------ */ +double const kcal_si = 4184.0; // [J] kilocalroie (heat energy + // involved in warming up one + // kilogram of water by one + // degree Kelvin) +double const ev_si = 1.6021766208e-19; // [J] electon volt (amount of + // energy gained or lost by the + // charge of a single electron + // moving across an electric + // potential difference of one + // volt.) (NIST value) +double const hartree_si = 4.359744650e-18; // [J] Hartree (approximately the + // electric potential energy of + // the hydrogen atom in its + // ground state) (NIST value) +double const kcal_per_mole_si = kcal_si/Nav;// [J] kcal/mole +double const erg_si = 1e-7; // [J] erg +double const dyne_centimeter_si = 1e-7; // [J[ dyne*centimeter +double const picogram_micrometersq_per_microsecondsq_si = + picogram_si*pow(micrometer_si,2)/pow(microsecond_si,2); + // [J] pigogram*micrometer^2/ + // micorsecond^2 +double const attogram_nanometersq_per_nanosecondsq_si = + attogram_si*pow(nanometer_si,2)/pow(nanosecond_si,2); + // [J] attogram*nanometer^2/ + // nanosecond^2 + +/*---------------------- + Velocity units +------------------------ */ +double const angstrom_per_femtosecond_si = + angstrom_si/femtosecond_si; // [m/s] Angstrom/femtosecond +double const angstrom_per_picosecond_si = + angstrom_si/picosecond_si; // [m/s] Angstrom/picosecond +double const micrometer_per_microsecond_si = + micrometer_si/microsecond_si; // [m/s] micrometer/microsecond +double const nanometer_per_nanosecond_si = + nanometer_si/nanosecond_si; // [m/s] nanometer/nanosecond +double const centimeter_per_second_si = + centimeter_si; // [m/s] centimeter/second +double const bohr_per_atu_si = + bohr_si/atu_electron_si; // [m/s] bohr/atu + +/*---------------------- + Force units +------------------------ */ +double const kcal_per_mole_angstrom_si = + kcal_per_mole_si/angstrom_si; // [N] kcal/(mole*Angstrom) +double const ev_per_angstrom_si = + ev_si/angstrom_si; // [N] eV/Angstrom +double const dyne_si = + dyne_centimeter_si/centimeter_si; // [N] dyne +double const hartree_per_bohr_si = + hartree_si/bohr_si; // [N] hartree/bohr +double const picogram_micrometer_per_microsecondsq_si = + picogram_si*micrometer_si/pow(microsecond_si,2); + // [N] picogram*micrometer/ + // microsecond^2 +double const attogram_nanometer_per_nanosecondsq_si = + attogram_si*nanometer_si/pow(nanosecond_si,2); + // [N] attogram*nanometer/ + // nanosecond^2 + +/*---------------------- + Pressure units +------------------------ */ +double const atmosphere_si = 101325.0; // [Pa] standard atmosphere (NIST value) +double const bar_si = 1e5; // [Pa] bar +double const dyne_per_centimetersq_si = + dyne_centimeter_si/pow(centimeter_si,3); + // [Pa] dyne/centimeter^2 +double const picogram_per_micrometer_microsecondsq_si = + picogram_si/(micrometer_si*pow(microsecond_si,2)); + // [Pa] picogram/(micrometer* + // microsecond^2) +double const attogram_per_nanometer_nanosecondsq_si = + attogram_si/(nanometer_si*pow(nanosecond_si,2)); + // [Pa] attogram/(nanometer*nanosecond^2) + +/*---------------------- + Viscosity units +------------------------ */ +double const poise_si = 0.1; // [Pa*s] Poise +double const amu_per_bohr_femtosecond_si = + amu_si/(bohr_si*femtosecond_si); // [Pa*s] amu/(bohr*femtosecond) +double const picogram_per_micrometer_microsecond_si = + picogram_si/(micrometer_si*microsecond_si); + // [Pa*s] picogram/(micrometer* + // microsecond) +double const attogram_per_nanometer_nanosecond_si = + attogram_si/(nanometer_si*nanosecond_si); + // [Pa*s] attogram/(nanometer* + // nanosecond) + +/*---------------------- + Charge units +------------------------ */ +double const echarge_si = e_si; // [C] electron charge unit +double const statcoulomb_si = e_si/4.8032044e-10; // [C] Statcoulomb or esu + // (value from LAMMPS units + // documentation) +double const picocoulomb_si = 1e-12; // [C] picocoulomb + +/*---------------------- + Dipole units +------------------------ */ +double const electron_angstrom_si = echarge_si*angstrom_si; + // [C*m] electron*angstrom +double const statcoulomb_centimeter_si = statcoulomb_si*centimeter_si; + // [C*m] statcoulomb*centimeter +double const debye_si = 1e-18*statcoulomb_centimeter_si; + // [C*m] Debye +double const picocoulomb_micrometer_si = picocoulomb_si*micrometer_si; + // [C*m] picocoulomb*micrometer +double const electron_nanometer_si = echarge_si*nanometer_si; + // [C*m] electron*nanometer + +/*---------------------- + Electric field units +------------------------ */ +double const volt_per_angstrom_si = 1.0/angstrom_si;// [V/m] volt/angstrom +double const statvolt_per_centimeter_si = + erg_si/(statcoulomb_si*centimeter_si); // [V/m] statvolt/centimeter +double const volt_per_centimeter_si = + 1.0/centimeter_si; // [V/m] volt/centimeter +double const volt_per_micrometer_si = + 1.0/micrometer_si; // [V/m] volt/micrometer +double const volt_per_nanometer_si = + 1.0/nanometer_si; // [V/m] volt/nanometer + +// Define enumerations +enum sys_type +{ + real = 1, + metal = 2, + si = 3, + cgs = 4, + electron = 5, + micro = 6, + nano = 7 +}; + +enum unit_type +{ + mass = 1, + distance = 2, + time = 3, + energy = 4, + velocity = 5, + force = 6, + torque = 7, + temperature = 8, + pressure = 9, + viscosity = 10, + charge = 11, + dipole = 12, + efield = 13, + density = 14 +}; + +enum units +{ + // mass + gram_per_mole = 101, + kilogram = 102, + gram = 103, + amu = 104, + picogram = 105, + attogram = 106, + // distance + angstrom = 201, + meter = 202, + centimeter = 203, + bohr = 204, + micrometer = 205, + nanometer = 206, + // time + femtosecond = 301, + picosecond = 302, + second = 303, + microsecond = 304, + nanosecond = 305, + // energy + kcal_per_mole = 401, + ev = 402, + joule = 403, + erg = 404, + hartree = 405, + picogram_micrometersq_per_microsecondsq = 406, + attogram_nanometersq_per_nanosecondsq = 407, + // velocity + angstrom_per_femtosecond = 501, + angstrom_per_picosecond = 502, + meter_per_second = 503, + centimeter_per_second = 504, + bohr_per_atu = 505, + micrometer_per_microsecond = 506, + nanometer_per_nanosecond = 507, + // force + kcal_per_mole_angstrom = 601, + ev_per_angstrom = 602, + newton = 603, + dyne = 604, + hartree_per_bohr = 605, + picogram_micrometer_per_microsecondsq = 606, + attogram_nanometer_per_nanosecondsq = 607, + // torque + newton_meter = 701, + dyne_centimeter = 702, + // temperature + kelvin = 801, + // pressure + atmosphere = 901, + bar = 902, + pascal = 903, + dyne_per_centimetersq = 904, + picogram_per_micrometer_microsecondsq = 905, + attogram_per_nanometer_nanosecondsq = 906, + // viscosity + poise = 1001, + pascal_second = 1002, + amu_per_bohr_femtosecond = 1003, // electron system, not in docs, GUESSED + picogram_per_micrometer_microsecond = 1004, + attogram_per_nanometer_nanosecond = 1005, + // charge + echarge = 1101, + coulomb = 1102, + statcoulomb = 1103, + picocoulomb = 1104, + // dipole + electron_angstrom = 1201, + coulomb_meter = 1202, + statcoulomb_centimeter = 1203, + debye = 1204, + picocoulomb_micrometer = 1205, + electron_nanometer = 1206, + // electric field + volt_per_angstrom = 1301, + volt_per_meter = 1302, + statvolt_per_centimeter = 1303, + volt_per_centimeter = 1304, + volt_per_micrometer = 1305, + volt_per_nanometer = 1306, + // density + gram_per_centimetercu = 1401, + kilogram_per_metercu = 1402, + amu_per_bohrcu = 1403, // electron system, not in docs, GUESSED + picogram_per_micrometercu = 1404, + attogram_per_nanometercu = 1405 +}; + +// Define dictionaries +map system_dic; +map unit_dic; +map units_real_dic; +map units_metal_dic; +map units_si_dic; +map units_cgs_dic; +map units_electron_dic; +map units_micro_dic; +map units_nano_dic; + +/* ---------------------------------------------------------------------- */ + +void initialize_dictionaries() +{ + system_dic["real"] = real; + system_dic["metal"] = metal; + system_dic["si"] = si; + system_dic["cgs"] = cgs; + system_dic["electron"] = electron; + system_dic["micro"] = micro; + system_dic["nano"] = nano; + + unit_dic["mass"] = mass; + unit_dic["distance"] = distance; + unit_dic["time"] = time; + unit_dic["energy"] = energy; + unit_dic["velocity"] = velocity; + unit_dic["force"] = force; + unit_dic["torque"] = torque; + unit_dic["temperature"]= temperature; + unit_dic["pressure"] = pressure; + unit_dic["viscosity"] = viscosity; + unit_dic["charge"] = charge; + unit_dic["dipole"] = dipole; + unit_dic["efield"] = efield; + unit_dic["density"] = density; + + units_real_dic[mass] = gram_per_mole; + units_real_dic[distance] = angstrom; + units_real_dic[time] = femtosecond; + units_real_dic[energy] = kcal_per_mole; + units_real_dic[velocity] = angstrom_per_femtosecond; + units_real_dic[force] = kcal_per_mole_angstrom; + units_real_dic[torque] = kcal_per_mole; + units_real_dic[temperature]= kelvin; + units_real_dic[pressure] = atmosphere; + units_real_dic[viscosity] = poise; + units_real_dic[charge] = echarge; + units_real_dic[dipole] = electron_angstrom; + units_real_dic[efield] = volt_per_angstrom; + units_real_dic[density] = gram_per_centimetercu; + + units_metal_dic[mass] = gram_per_mole; + units_metal_dic[distance] = angstrom; + units_metal_dic[time] = picosecond; + units_metal_dic[energy] = ev; + units_metal_dic[velocity] = angstrom_per_picosecond; + units_metal_dic[force] = ev_per_angstrom; + units_metal_dic[torque] = ev; + units_metal_dic[temperature]= kelvin; + units_metal_dic[pressure] = bar; + units_metal_dic[viscosity] = poise; + units_metal_dic[charge] = echarge; + units_metal_dic[dipole] = electron_angstrom; + units_metal_dic[efield] = volt_per_angstrom; + units_metal_dic[density] = gram_per_centimetercu; + + units_si_dic[mass] = kilogram; + units_si_dic[distance] = meter; + units_si_dic[time] = second; + units_si_dic[energy] = joule; + units_si_dic[velocity] = meter_per_second; + units_si_dic[force] = newton; + units_si_dic[torque] = newton_meter; + units_si_dic[temperature]= kelvin; + units_si_dic[pressure] = pascal; + units_si_dic[viscosity] = pascal_second; + units_si_dic[charge] = coulomb; + units_si_dic[dipole] = coulomb_meter; + units_si_dic[efield] = volt_per_meter; + units_si_dic[density] = kilogram_per_metercu; + + units_cgs_dic[mass] = gram; + units_cgs_dic[distance] = centimeter; + units_cgs_dic[time] = second; + units_cgs_dic[energy] = erg; + units_cgs_dic[velocity] = centimeter_per_second; + units_cgs_dic[force] = dyne; + units_cgs_dic[torque] = dyne_centimeter; + units_cgs_dic[temperature]= kelvin; + units_cgs_dic[pressure] = dyne_per_centimetersq; + units_cgs_dic[viscosity] = poise; + units_cgs_dic[charge] = statcoulomb; + units_cgs_dic[dipole] = statcoulomb_centimeter; + units_cgs_dic[efield] = statvolt_per_centimeter; + units_cgs_dic[density] = gram_per_centimetercu; + + units_electron_dic[mass] = amu; + units_electron_dic[distance] = bohr; + units_electron_dic[time] = femtosecond; + units_electron_dic[energy] = hartree; + units_electron_dic[velocity] = bohr_per_atu; + units_electron_dic[force] = hartree_per_bohr; + units_electron_dic[torque] = hartree; // unknown, GUESSED + units_electron_dic[temperature]= kelvin; + units_electron_dic[pressure] = pascal; + units_electron_dic[viscosity] = pascal_second; // unknown, GUESSED + units_electron_dic[charge] = echarge; + units_electron_dic[dipole] = debye; + units_electron_dic[efield] = volt_per_centimeter; + units_electron_dic[density] = amu_per_bohrcu; // unknown, GUESSED + + units_micro_dic[mass] = picogram; + units_micro_dic[distance] = micrometer; + units_micro_dic[time] = microsecond; + units_micro_dic[energy] = picogram_micrometersq_per_microsecondsq; + units_micro_dic[velocity] = micrometer_per_microsecond; + units_micro_dic[force] = picogram_micrometer_per_microsecondsq; + units_micro_dic[torque] = picogram_micrometersq_per_microsecondsq; + units_micro_dic[temperature]= kelvin; + units_micro_dic[pressure] = picogram_per_micrometer_microsecondsq; + units_micro_dic[viscosity] = picogram_per_micrometer_microsecond; + units_micro_dic[charge] = picocoulomb; + units_micro_dic[dipole] = picocoulomb_micrometer; + units_micro_dic[efield] = volt_per_micrometer; + units_micro_dic[density] = picogram_per_micrometercu; + + units_nano_dic[mass] = attogram; + units_nano_dic[distance] = nanometer; + units_nano_dic[time] = nanosecond; + units_nano_dic[energy] = attogram_nanometersq_per_nanosecondsq; + units_nano_dic[velocity] = nanometer_per_nanosecond; + units_nano_dic[force] = attogram_nanometer_per_nanosecondsq; + units_nano_dic[torque] = attogram_nanometersq_per_nanosecondsq; + units_nano_dic[temperature]= kelvin; + units_nano_dic[pressure] = attogram_per_nanometer_nanosecondsq; + units_nano_dic[viscosity] = attogram_per_nanometer_nanosecond; + units_nano_dic[charge] = echarge; + units_nano_dic[dipole] = electron_nanometer; + units_nano_dic[efield] = volt_per_nanometer; + units_nano_dic[density] = attogram_per_nanometercu; + +} + +/* ---------------------------------------------------------------------- */ + +// Get the enumeration for the unit of type `unit_type_enum` +// for LAMMPS system `system_enum`. +units get_lammps_system_unit(sys_type system_enum, unit_type unit_type_enum) +{ + switch(system_enum) { + case real : + return units_real_dic[unit_type_enum]; + case metal : + return units_metal_dic[unit_type_enum]; + case si : + return units_si_dic[unit_type_enum]; + case cgs : + return units_cgs_dic[unit_type_enum]; + case electron : + return units_electron_dic[unit_type_enum]; + case micro : + return units_micro_dic[unit_type_enum]; + case nano : + default : // This is here to a prevent a compiler warning + return units_nano_dic[unit_type_enum]; + } +} + +/* ---------------------------------------------------------------------- */ + +// Mass conversion +double get_mass_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[kilogram][kilogram] = 1.0; + conv[kilogram][gram_per_mole] = 1.0/gram_per_mole_si; + conv[kilogram][gram] = 1.0/gram_si; + conv[kilogram][amu] = 1.0/amu_si; + conv[kilogram][picogram] = 1.0/picogram_si; + conv[kilogram][attogram] = 1.0/attogram_si; + + to_si = 1.0/conv[kilogram][gram_per_mole]; + conv[gram_per_mole][kilogram] = to_si*conv[kilogram][kilogram]; + conv[gram_per_mole][gram_per_mole] = 1.0; + conv[gram_per_mole][gram] = to_si*conv[kilogram][gram]; + conv[gram_per_mole][amu] = to_si*conv[kilogram][amu]; + conv[gram_per_mole][picogram] = to_si*conv[kilogram][picogram]; + conv[gram_per_mole][attogram] = to_si*conv[kilogram][attogram]; + + to_si = 1.0/conv[kilogram][gram]; + conv[gram][kilogram] = to_si*conv[kilogram][kilogram]; + conv[gram][gram_per_mole] = to_si*conv[kilogram][gram_per_mole]; + conv[gram][gram] = 1.0; + conv[gram][amu] = to_si*conv[kilogram][amu]; + conv[gram][picogram] = to_si*conv[kilogram][picogram]; + conv[gram][attogram] = to_si*conv[kilogram][attogram]; + + to_si = 1.0/conv[kilogram][amu]; + conv[amu][kilogram] = to_si*conv[kilogram][kilogram]; + conv[amu][gram_per_mole] = to_si*conv[kilogram][gram_per_mole]; + conv[amu][gram] = to_si*conv[kilogram][gram]; + conv[amu][amu] = 1.0; + conv[amu][picogram] = to_si*conv[kilogram][picogram]; + conv[amu][attogram] = to_si*conv[kilogram][attogram]; + + to_si = 1.0/conv[kilogram][picogram]; + conv[picogram][kilogram] = to_si*conv[kilogram][kilogram]; + conv[picogram][gram_per_mole] = to_si*conv[kilogram][gram_per_mole]; + conv[picogram][gram] = to_si*conv[kilogram][gram]; + conv[picogram][amu] = to_si*conv[kilogram][amu]; + conv[picogram][picogram] = 1.0; + conv[picogram][attogram] = to_si*conv[kilogram][attogram]; + + to_si = 1.0/conv[kilogram][attogram]; + conv[attogram][kilogram] = to_si*conv[kilogram][kilogram]; + conv[attogram][gram_per_mole] = to_si*conv[kilogram][gram_per_mole]; + conv[attogram][gram] = to_si*conv[kilogram][gram]; + conv[attogram][amu] = to_si*conv[kilogram][amu]; + conv[attogram][picogram] = to_si*conv[kilogram][picogram]; + conv[attogram][attogram] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Distance conversion +double get_distance_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[meter][meter] = 1.0; + conv[meter][angstrom] = 1.0/angstrom_si; + conv[meter][centimeter] = 1.0/centimeter_si; + conv[meter][bohr] = 1.0/bohr_si; + conv[meter][micrometer] = 1.0/micrometer_si; + conv[meter][nanometer] = 1.0/nanometer_si; + + to_si = 1.0/conv[meter][angstrom]; + conv[angstrom][meter] = to_si*conv[meter][meter]; + conv[angstrom][angstrom] = 1.0; + conv[angstrom][centimeter] = to_si*conv[meter][centimeter]; + conv[angstrom][bohr] = to_si*conv[meter][bohr]; + conv[angstrom][micrometer] = to_si*conv[meter][micrometer]; + conv[angstrom][nanometer] = to_si*conv[meter][nanometer]; + + to_si = 1.0/conv[meter][centimeter]; + conv[centimeter][meter] = to_si*conv[meter][meter]; + conv[centimeter][angstrom] = to_si*conv[meter][angstrom]; + conv[centimeter][centimeter] = 1.0; + conv[centimeter][bohr] = to_si*conv[meter][bohr]; + conv[centimeter][micrometer] = to_si*conv[meter][micrometer]; + conv[centimeter][nanometer] = to_si*conv[meter][nanometer]; + + to_si = 1.0/conv[meter][bohr]; + conv[bohr][meter] = to_si*conv[meter][meter]; + conv[bohr][angstrom] = to_si*conv[meter][angstrom]; + conv[bohr][centimeter] = to_si*conv[meter][centimeter]; + conv[bohr][bohr] = 1.0; + conv[bohr][micrometer] = to_si*conv[meter][micrometer]; + conv[bohr][nanometer] = to_si*conv[meter][nanometer]; + + to_si = 1.0/conv[meter][micrometer]; + conv[micrometer][meter] = to_si*conv[meter][meter]; + conv[micrometer][angstrom] = to_si*conv[meter][angstrom]; + conv[micrometer][centimeter] = to_si*conv[meter][centimeter]; + conv[micrometer][bohr] = to_si*conv[meter][bohr]; + conv[micrometer][micrometer] = 1.0; + conv[micrometer][nanometer] = to_si*conv[meter][nanometer]; + + to_si = 1.0/conv[meter][nanometer]; + conv[nanometer][meter] = to_si*conv[meter][meter]; + conv[nanometer][angstrom] = to_si*conv[meter][angstrom]; + conv[nanometer][centimeter] = to_si*conv[meter][centimeter]; + conv[nanometer][bohr] = to_si*conv[meter][bohr]; + conv[nanometer][micrometer] = to_si*conv[meter][micrometer]; + conv[nanometer][nanometer] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Time conversion +double get_time_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[second][second] = 1.0; + conv[second][femtosecond] = 1.0/femtosecond_si; + conv[second][picosecond] = 1.0/picosecond_si; + conv[second][microsecond] = 1.0/microsecond_si; + conv[second][nanosecond] = 1.0/nanosecond_si; + + to_si = 1.0/conv[second][femtosecond]; + conv[femtosecond][second] = to_si*conv[second][second]; + conv[femtosecond][femtosecond] = 1.0; + conv[femtosecond][picosecond] = to_si*conv[second][picosecond]; + conv[femtosecond][microsecond] = to_si*conv[second][microsecond]; + conv[femtosecond][nanosecond] = to_si*conv[second][nanosecond]; + + to_si = 1.0/conv[second][picosecond]; + conv[picosecond][second] = to_si*conv[second][second]; + conv[picosecond][femtosecond] = to_si*conv[second][femtosecond]; + conv[picosecond][picosecond] = 1.0; + conv[picosecond][microsecond] = to_si*conv[second][microsecond]; + conv[picosecond][nanosecond] = to_si*conv[second][nanosecond]; + + to_si = 1.0/conv[second][microsecond]; + conv[microsecond][second] = to_si*conv[second][second]; + conv[microsecond][femtosecond] = to_si*conv[second][femtosecond]; + conv[microsecond][picosecond] = to_si*conv[second][picosecond]; + conv[microsecond][microsecond] = 1.0; + conv[microsecond][nanosecond] = to_si*conv[second][nanosecond]; + + to_si = 1.0/conv[second][nanosecond]; + conv[nanosecond][second] = to_si*conv[second][second]; + conv[nanosecond][femtosecond] = to_si*conv[second][femtosecond]; + conv[nanosecond][picosecond] = to_si*conv[second][picosecond]; + conv[nanosecond][microsecond] = to_si*conv[second][microsecond]; + conv[nanosecond][nanosecond] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Energy conversion +double get_energy_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + + map > conv; + double to_si; + + conv[joule][joule] = 1.0; + conv[joule][kcal_per_mole] = 1.0/kcal_per_mole_si; + conv[joule][ev] = 1.0/ev_si; + conv[joule][erg] = 1.0/erg_si; + conv[joule][hartree] = 1.0/hartree_si; + conv[joule][picogram_micrometersq_per_microsecondsq] = 1.0/picogram_micrometersq_per_microsecondsq_si; + conv[joule][attogram_nanometersq_per_nanosecondsq] = 1.0/attogram_nanometersq_per_nanosecondsq_si; + + to_si = 1.0/conv[joule][kcal_per_mole]; + conv[kcal_per_mole][joule] = to_si*conv[joule][joule]; + conv[kcal_per_mole][kcal_per_mole] = 1.0; + conv[kcal_per_mole][ev] = to_si*conv[joule][ev]; + conv[kcal_per_mole][erg] = to_si*conv[joule][erg]; + conv[kcal_per_mole][hartree] = to_si*conv[joule][hartree]; + conv[kcal_per_mole][picogram_micrometersq_per_microsecondsq] = to_si*conv[joule][picogram_micrometersq_per_microsecondsq]; + conv[kcal_per_mole][attogram_nanometersq_per_nanosecondsq] = to_si*conv[joule][attogram_nanometersq_per_nanosecondsq]; + + to_si = 1.0/conv[joule][ev]; + conv[ev][joule] = to_si*conv[joule][joule]; + conv[ev][kcal_per_mole] = to_si*conv[joule][kcal_per_mole]; + conv[ev][ev] = 1.0; + conv[ev][erg] = to_si*conv[joule][erg]; + conv[ev][hartree] = to_si*conv[joule][hartree]; + conv[ev][picogram_micrometersq_per_microsecondsq] = to_si*conv[joule][picogram_micrometersq_per_microsecondsq]; + conv[ev][attogram_nanometersq_per_nanosecondsq] = to_si*conv[joule][attogram_nanometersq_per_nanosecondsq]; + + to_si = 1.0/conv[joule][erg]; + conv[erg][joule] = to_si*conv[joule][joule]; + conv[erg][kcal_per_mole] = to_si*conv[joule][kcal_per_mole]; + conv[erg][ev] = to_si*conv[joule][ev]; + conv[erg][erg] = 1.0; + conv[erg][hartree] = to_si*conv[joule][hartree]; + conv[erg][picogram_micrometersq_per_microsecondsq] = to_si*conv[joule][picogram_micrometersq_per_microsecondsq]; + conv[erg][attogram_nanometersq_per_nanosecondsq] = to_si*conv[joule][attogram_nanometersq_per_nanosecondsq]; + + to_si = 1.0/conv[joule][hartree]; + conv[hartree][joule] = to_si*conv[joule][joule]; + conv[hartree][kcal_per_mole] = to_si*conv[joule][kcal_per_mole]; + conv[hartree][ev] = to_si*conv[joule][ev]; + conv[hartree][erg] = to_si*conv[joule][erg]; + conv[hartree][hartree] = 1.0; + conv[hartree][picogram_micrometersq_per_microsecondsq] = to_si*conv[joule][picogram_micrometersq_per_microsecondsq]; + conv[hartree][attogram_nanometersq_per_nanosecondsq] = to_si*conv[joule][attogram_nanometersq_per_nanosecondsq]; + + to_si = 1.0/conv[joule][picogram_micrometersq_per_microsecondsq]; + conv[picogram_micrometersq_per_microsecondsq][joule] = to_si*conv[joule][joule]; + conv[picogram_micrometersq_per_microsecondsq][kcal_per_mole] = to_si*conv[joule][kcal_per_mole]; + conv[picogram_micrometersq_per_microsecondsq][ev] = to_si*conv[joule][ev]; + conv[picogram_micrometersq_per_microsecondsq][erg] = to_si*conv[joule][erg]; + conv[picogram_micrometersq_per_microsecondsq][hartree] = to_si*conv[joule][hartree]; + conv[picogram_micrometersq_per_microsecondsq][picogram_micrometersq_per_microsecondsq] = 1.0; + conv[picogram_micrometersq_per_microsecondsq][attogram_nanometersq_per_nanosecondsq] = to_si*conv[joule][attogram_nanometersq_per_nanosecondsq]; + + to_si = 1.0/conv[joule][attogram_nanometersq_per_nanosecondsq]; + conv[attogram_nanometersq_per_nanosecondsq][joule] = to_si*conv[joule][joule]; + conv[attogram_nanometersq_per_nanosecondsq][kcal_per_mole] = to_si*conv[joule][kcal_per_mole]; + conv[attogram_nanometersq_per_nanosecondsq][ev] = to_si*conv[joule][ev]; + conv[attogram_nanometersq_per_nanosecondsq][erg] = to_si*conv[joule][erg]; + conv[attogram_nanometersq_per_nanosecondsq][hartree] = to_si*conv[joule][hartree]; + conv[attogram_nanometersq_per_nanosecondsq][picogram_micrometersq_per_microsecondsq] = to_si*conv[joule][picogram_micrometersq_per_microsecondsq]; + conv[attogram_nanometersq_per_nanosecondsq][attogram_nanometersq_per_nanosecondsq] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Velocity conversion +double get_velocity_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[meter_per_second][meter_per_second] = 1.0; + conv[meter_per_second][angstrom_per_femtosecond] = 1.0/angstrom_per_femtosecond_si; + conv[meter_per_second][angstrom_per_picosecond] = 1.0/angstrom_per_picosecond_si; + conv[meter_per_second][centimeter_per_second] = 1.0/centimeter_per_second_si; + conv[meter_per_second][bohr_per_atu] = 1.0/bohr_per_atu_si; + conv[meter_per_second][micrometer_per_microsecond] = 1.0/micrometer_per_microsecond_si; + conv[meter_per_second][nanometer_per_nanosecond] = 1.0/nanometer_per_nanosecond_si; + + to_si = 1.0/conv[meter_per_second][angstrom_per_femtosecond]; + conv[angstrom_per_femtosecond][meter_per_second] = to_si*conv[meter_per_second][meter_per_second]; + conv[angstrom_per_femtosecond][angstrom_per_femtosecond] = 1.0; + conv[angstrom_per_femtosecond][angstrom_per_picosecond] = to_si*conv[meter_per_second][angstrom_per_picosecond]; + conv[angstrom_per_femtosecond][centimeter_per_second] = to_si*conv[meter_per_second][centimeter_per_second]; + conv[angstrom_per_femtosecond][bohr_per_atu] = to_si*conv[meter_per_second][bohr_per_atu]; + conv[angstrom_per_femtosecond][micrometer_per_microsecond] = to_si*conv[meter_per_second][micrometer_per_microsecond]; + conv[angstrom_per_femtosecond][nanometer_per_nanosecond] = to_si*conv[meter_per_second][nanometer_per_nanosecond]; + + to_si = 1.0/conv[meter_per_second][angstrom_per_picosecond]; + conv[angstrom_per_picosecond][meter_per_second] = to_si*conv[meter_per_second][meter_per_second]; + conv[angstrom_per_picosecond][angstrom_per_femtosecond] = to_si*conv[meter_per_second][angstrom_per_femtosecond]; + conv[angstrom_per_picosecond][angstrom_per_picosecond] = 1.0; + conv[angstrom_per_picosecond][centimeter_per_second] = to_si*conv[meter_per_second][centimeter_per_second]; + conv[angstrom_per_picosecond][bohr_per_atu] = to_si*conv[meter_per_second][bohr_per_atu]; + conv[angstrom_per_picosecond][micrometer_per_microsecond] = to_si*conv[meter_per_second][micrometer_per_microsecond]; + conv[angstrom_per_picosecond][nanometer_per_nanosecond] = to_si*conv[meter_per_second][nanometer_per_nanosecond]; + + to_si = 1.0/conv[meter_per_second][centimeter_per_second]; + conv[centimeter_per_second][meter_per_second] = to_si*conv[meter_per_second][meter_per_second]; + conv[centimeter_per_second][angstrom_per_femtosecond] = to_si*conv[meter_per_second][angstrom_per_femtosecond]; + conv[centimeter_per_second][angstrom_per_picosecond] = to_si*conv[meter_per_second][angstrom_per_picosecond]; + conv[centimeter_per_second][centimeter_per_second] = 1.0; + conv[centimeter_per_second][bohr_per_atu] = to_si*conv[meter_per_second][bohr_per_atu]; + conv[centimeter_per_second][micrometer_per_microsecond] = to_si*conv[meter_per_second][micrometer_per_microsecond]; + conv[centimeter_per_second][nanometer_per_nanosecond] = to_si*conv[meter_per_second][nanometer_per_nanosecond]; + + to_si = 1.0/conv[meter_per_second][bohr_per_atu]; + conv[bohr_per_atu][meter_per_second] = to_si*conv[meter_per_second][meter_per_second]; + conv[bohr_per_atu][angstrom_per_femtosecond] = to_si*conv[meter_per_second][angstrom_per_femtosecond]; + conv[bohr_per_atu][angstrom_per_picosecond] = to_si*conv[meter_per_second][angstrom_per_picosecond]; + conv[bohr_per_atu][centimeter_per_second] = to_si*conv[meter_per_second][centimeter_per_second]; + conv[bohr_per_atu][bohr_per_atu] = 1.0; + conv[bohr_per_atu][micrometer_per_microsecond] = to_si*conv[meter_per_second][micrometer_per_microsecond]; + conv[bohr_per_atu][nanometer_per_nanosecond] = to_si*conv[meter_per_second][nanometer_per_nanosecond]; + + to_si = 1.0/conv[meter_per_second][micrometer_per_microsecond]; + conv[micrometer_per_microsecond][meter_per_second] = to_si*conv[meter_per_second][meter_per_second]; + conv[micrometer_per_microsecond][angstrom_per_femtosecond] = to_si*conv[meter_per_second][angstrom_per_femtosecond]; + conv[micrometer_per_microsecond][angstrom_per_picosecond] = to_si*conv[meter_per_second][angstrom_per_picosecond]; + conv[micrometer_per_microsecond][centimeter_per_second] = to_si*conv[meter_per_second][centimeter_per_second]; + conv[micrometer_per_microsecond][bohr_per_atu] = to_si*conv[meter_per_second][bohr_per_atu]; + conv[micrometer_per_microsecond][micrometer_per_microsecond] = 1.0; + conv[micrometer_per_microsecond][nanometer_per_nanosecond] = to_si*conv[meter_per_second][nanometer_per_nanosecond]; + + to_si = 1.0/conv[meter_per_second][nanometer_per_nanosecond]; + conv[nanometer_per_nanosecond][meter_per_second] = to_si*conv[meter_per_second][meter_per_second]; + conv[nanometer_per_nanosecond][angstrom_per_femtosecond] = to_si*conv[meter_per_second][angstrom_per_femtosecond]; + conv[nanometer_per_nanosecond][angstrom_per_picosecond] = to_si*conv[meter_per_second][angstrom_per_picosecond]; + conv[nanometer_per_nanosecond][centimeter_per_second] = to_si*conv[meter_per_second][centimeter_per_second]; + conv[nanometer_per_nanosecond][bohr_per_atu] = to_si*conv[meter_per_second][bohr_per_atu]; + conv[nanometer_per_nanosecond][micrometer_per_microsecond] = to_si*conv[meter_per_second][micrometer_per_microsecond]; + conv[nanometer_per_nanosecond][nanometer_per_nanosecond] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Force conversion +double get_force_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[newton][newton] = 1.0; + conv[newton][kcal_per_mole_angstrom] = 1.0/kcal_per_mole_angstrom_si; + conv[newton][ev_per_angstrom] = 1.0/ev_per_angstrom_si; + conv[newton][dyne] = 1.0/dyne_si; + conv[newton][hartree_per_bohr] = 1.0/hartree_per_bohr_si; + conv[newton][picogram_micrometer_per_microsecondsq] = 1.0/picogram_micrometer_per_microsecondsq_si; + conv[newton][attogram_nanometer_per_nanosecondsq] = 1.0/attogram_nanometer_per_nanosecondsq_si; + + to_si = 1.0/conv[newton][kcal_per_mole_angstrom]; + conv[kcal_per_mole_angstrom][newton] = to_si*conv[newton][newton]; + conv[kcal_per_mole_angstrom][kcal_per_mole_angstrom] = 1.0; + conv[kcal_per_mole_angstrom][ev_per_angstrom] = to_si*conv[newton][ev_per_angstrom]; + conv[kcal_per_mole_angstrom][dyne] = to_si*conv[newton][dyne]; + conv[kcal_per_mole_angstrom][hartree_per_bohr] = to_si*conv[newton][hartree_per_bohr]; + conv[kcal_per_mole_angstrom][picogram_micrometer_per_microsecondsq] = to_si*conv[newton][picogram_micrometer_per_microsecondsq]; + conv[kcal_per_mole_angstrom][attogram_nanometer_per_nanosecondsq] = to_si*conv[newton][attogram_nanometer_per_nanosecondsq]; + + to_si = 1.0/conv[newton][ev_per_angstrom]; + conv[ev_per_angstrom][newton] = to_si*conv[newton][newton]; + conv[ev_per_angstrom][kcal_per_mole_angstrom] = to_si*conv[newton][kcal_per_mole_angstrom]; + conv[ev_per_angstrom][ev_per_angstrom] = 1.0; + conv[ev_per_angstrom][dyne] = to_si*conv[newton][dyne]; + conv[ev_per_angstrom][hartree_per_bohr] = to_si*conv[newton][hartree_per_bohr]; + conv[ev_per_angstrom][picogram_micrometer_per_microsecondsq] = to_si*conv[newton][picogram_micrometer_per_microsecondsq]; + conv[ev_per_angstrom][attogram_nanometer_per_nanosecondsq] = to_si*conv[newton][attogram_nanometer_per_nanosecondsq]; + + to_si = 1.0/conv[newton][dyne]; + conv[dyne][newton] = to_si*conv[newton][newton]; + conv[dyne][kcal_per_mole_angstrom] = to_si*conv[newton][kcal_per_mole_angstrom]; + conv[dyne][ev_per_angstrom] = to_si*conv[newton][ev_per_angstrom]; + conv[dyne][dyne] = 1.0; + conv[dyne][hartree_per_bohr] = to_si*conv[newton][hartree_per_bohr]; + conv[dyne][picogram_micrometer_per_microsecondsq] = to_si*conv[newton][picogram_micrometer_per_microsecondsq]; + conv[dyne][attogram_nanometer_per_nanosecondsq] = to_si*conv[newton][attogram_nanometer_per_nanosecondsq]; + + to_si = 1.0/conv[newton][hartree_per_bohr]; + conv[hartree_per_bohr][newton] = to_si*conv[newton][newton]; + conv[hartree_per_bohr][kcal_per_mole_angstrom] = to_si*conv[newton][kcal_per_mole_angstrom]; + conv[hartree_per_bohr][ev_per_angstrom] = to_si*conv[newton][ev_per_angstrom]; + conv[hartree_per_bohr][dyne] = to_si*conv[newton][dyne]; + conv[hartree_per_bohr][hartree_per_bohr] = 1.0; + conv[hartree_per_bohr][picogram_micrometer_per_microsecondsq] = to_si*conv[newton][picogram_micrometer_per_microsecondsq]; + conv[hartree_per_bohr][attogram_nanometer_per_nanosecondsq] = to_si*conv[newton][attogram_nanometer_per_nanosecondsq]; + + to_si = 1.0/conv[newton][picogram_micrometer_per_microsecondsq]; + conv[picogram_micrometer_per_microsecondsq][newton] = to_si*conv[newton][newton]; + conv[picogram_micrometer_per_microsecondsq][kcal_per_mole_angstrom] = to_si*conv[newton][kcal_per_mole_angstrom]; + conv[picogram_micrometer_per_microsecondsq][ev_per_angstrom] = to_si*conv[newton][ev_per_angstrom]; + conv[picogram_micrometer_per_microsecondsq][dyne] = to_si*conv[newton][dyne]; + conv[picogram_micrometer_per_microsecondsq][hartree_per_bohr] = to_si*conv[newton][hartree_per_bohr]; + conv[picogram_micrometer_per_microsecondsq][picogram_micrometer_per_microsecondsq] = 1.0; + conv[picogram_micrometer_per_microsecondsq][attogram_nanometer_per_nanosecondsq] = to_si*conv[newton][attogram_nanometer_per_nanosecondsq]; + + to_si = 1.0/conv[newton][attogram_nanometer_per_nanosecondsq]; + conv[attogram_nanometer_per_nanosecondsq][newton] = to_si*conv[newton][newton]; + conv[attogram_nanometer_per_nanosecondsq][kcal_per_mole_angstrom] = to_si*conv[newton][kcal_per_mole_angstrom]; + conv[attogram_nanometer_per_nanosecondsq][ev_per_angstrom] = to_si*conv[newton][ev_per_angstrom]; + conv[attogram_nanometer_per_nanosecondsq][dyne] = to_si*conv[newton][dyne]; + conv[attogram_nanometer_per_nanosecondsq][hartree_per_bohr] = to_si*conv[newton][hartree_per_bohr]; + conv[attogram_nanometer_per_nanosecondsq][picogram_micrometer_per_microsecondsq] = to_si*conv[newton][picogram_micrometer_per_microsecondsq]; + conv[attogram_nanometer_per_nanosecondsq][attogram_nanometer_per_nanosecondsq] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Torque conversion +double get_torque_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[newton_meter][newton_meter] = 1.0; + conv[newton_meter][kcal_per_mole] = 1.0/kcal_per_mole_si; + conv[newton_meter][ev] = 1.0/ev_si; + conv[newton_meter][dyne_centimeter] = 1.0/dyne_centimeter_si; + conv[newton_meter][hartree] = 1.0/hartree_si; + conv[newton_meter][picogram_micrometersq_per_microsecondsq] = 1.0/picogram_micrometersq_per_microsecondsq_si; + conv[newton_meter][attogram_nanometersq_per_nanosecondsq] = 1.0/attogram_nanometersq_per_nanosecondsq_si; + + to_si = 1.0/conv[newton_meter][kcal_per_mole]; + conv[kcal_per_mole][newton_meter] = to_si*conv[newton_meter][newton_meter]; + conv[kcal_per_mole][kcal_per_mole] = 1.0; + conv[kcal_per_mole][ev] = to_si*conv[newton_meter][ev]; + conv[kcal_per_mole][dyne_centimeter] = to_si*conv[newton_meter][dyne_centimeter]; + conv[kcal_per_mole][hartree] = to_si*conv[newton_meter][hartree]; + conv[kcal_per_mole][picogram_micrometersq_per_microsecondsq] = to_si*conv[newton_meter][picogram_micrometersq_per_microsecondsq]; + conv[kcal_per_mole][attogram_nanometersq_per_nanosecondsq] = to_si*conv[newton_meter][attogram_nanometersq_per_nanosecondsq]; + + to_si = 1.0/conv[newton_meter][ev]; + conv[ev][newton_meter] = to_si*conv[newton_meter][newton_meter]; + conv[ev][kcal_per_mole] = to_si*conv[newton_meter][kcal_per_mole]; + conv[ev][ev] = 1.0; + conv[ev][dyne_centimeter] = to_si*conv[newton_meter][dyne_centimeter]; + conv[ev][hartree] = to_si*conv[newton_meter][hartree]; + conv[ev][picogram_micrometersq_per_microsecondsq] = to_si*conv[newton_meter][picogram_micrometersq_per_microsecondsq]; + conv[ev][attogram_nanometersq_per_nanosecondsq] = to_si*conv[newton_meter][attogram_nanometersq_per_nanosecondsq]; + + to_si = 1.0/conv[newton_meter][dyne_centimeter]; + conv[dyne_centimeter][newton_meter] = to_si*conv[newton_meter][newton_meter]; + conv[dyne_centimeter][kcal_per_mole] = to_si*conv[newton_meter][kcal_per_mole]; + conv[dyne_centimeter][ev] = to_si*conv[newton_meter][ev]; + conv[dyne_centimeter][dyne_centimeter] = 1.0; + conv[dyne_centimeter][hartree] = to_si*conv[newton_meter][hartree]; + conv[dyne_centimeter][picogram_micrometersq_per_microsecondsq] = to_si*conv[newton_meter][picogram_micrometersq_per_microsecondsq]; + conv[dyne_centimeter][attogram_nanometersq_per_nanosecondsq] = to_si*conv[newton_meter][attogram_nanometersq_per_nanosecondsq]; + + to_si = 1.0/conv[newton_meter][hartree]; + conv[hartree][newton_meter] = to_si*conv[newton_meter][newton_meter]; + conv[hartree][kcal_per_mole] = to_si*conv[newton_meter][kcal_per_mole]; + conv[hartree][ev] = to_si*conv[newton_meter][ev]; + conv[hartree][dyne_centimeter] = to_si*conv[newton_meter][dyne_centimeter]; + conv[hartree][hartree] = 1.0; + conv[hartree][picogram_micrometersq_per_microsecondsq] = to_si*conv[newton_meter][picogram_micrometersq_per_microsecondsq]; + conv[hartree][attogram_nanometersq_per_nanosecondsq] = to_si*conv[newton_meter][attogram_nanometersq_per_nanosecondsq]; + + to_si = 1.0/conv[newton_meter][picogram_micrometersq_per_microsecondsq]; + conv[picogram_micrometersq_per_microsecondsq][newton_meter] = to_si*conv[newton_meter][newton_meter]; + conv[picogram_micrometersq_per_microsecondsq][kcal_per_mole] = to_si*conv[newton_meter][kcal_per_mole]; + conv[picogram_micrometersq_per_microsecondsq][ev] = to_si*conv[newton_meter][ev]; + conv[picogram_micrometersq_per_microsecondsq][dyne_centimeter] = to_si*conv[newton_meter][dyne_centimeter]; + conv[picogram_micrometersq_per_microsecondsq][hartree] = to_si*conv[newton_meter][hartree]; + conv[picogram_micrometersq_per_microsecondsq][picogram_micrometersq_per_microsecondsq] = 1.0; + conv[picogram_micrometersq_per_microsecondsq][attogram_nanometersq_per_nanosecondsq] = to_si*conv[newton_meter][attogram_nanometersq_per_nanosecondsq]; + + to_si = 1.0/conv[newton_meter][attogram_nanometersq_per_nanosecondsq]; + conv[attogram_nanometersq_per_nanosecondsq][newton_meter] = to_si*conv[newton_meter][newton_meter]; + conv[attogram_nanometersq_per_nanosecondsq][kcal_per_mole] = to_si*conv[newton_meter][kcal_per_mole]; + conv[attogram_nanometersq_per_nanosecondsq][ev] = to_si*conv[newton_meter][ev]; + conv[attogram_nanometersq_per_nanosecondsq][dyne_centimeter] = to_si*conv[newton_meter][dyne_centimeter]; + conv[attogram_nanometersq_per_nanosecondsq][hartree] = to_si*conv[newton_meter][hartree]; + conv[attogram_nanometersq_per_nanosecondsq][picogram_micrometersq_per_microsecondsq] = to_si*conv[newton_meter][picogram_micrometersq_per_microsecondsq]; + conv[attogram_nanometersq_per_nanosecondsq][attogram_nanometersq_per_nanosecondsq] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Temperature conversion +double get_temperature_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[kelvin][kelvin] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Pressure conversion +double get_pressure_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[pascal][pascal] = 1.0; + conv[pascal][atmosphere] = 1.0/atmosphere_si; + conv[pascal][bar] = 1.0/bar_si; + conv[pascal][dyne_per_centimetersq] = 1.0/dyne_per_centimetersq_si; + conv[pascal][picogram_per_micrometer_microsecondsq] = 1.0/picogram_per_micrometer_microsecondsq_si; + conv[pascal][attogram_per_nanometer_nanosecondsq] = 1.0/attogram_per_nanometer_nanosecondsq_si; + + to_si = 1.0/conv[pascal][atmosphere]; + conv[atmosphere][pascal] = to_si*conv[pascal][pascal]; + conv[atmosphere][atmosphere] = 1.0; + conv[atmosphere][bar] = to_si*conv[pascal][bar]; + conv[atmosphere][dyne_per_centimetersq] = to_si*conv[pascal][dyne_per_centimetersq]; + conv[atmosphere][picogram_per_micrometer_microsecondsq] = to_si*conv[pascal][picogram_per_micrometer_microsecondsq]; + conv[atmosphere][attogram_per_nanometer_nanosecondsq] = to_si*conv[pascal][attogram_per_nanometer_nanosecondsq]; + + to_si = 1.0/conv[pascal][bar]; + conv[bar][pascal] = to_si*conv[pascal][pascal]; + conv[bar][atmosphere] = to_si*conv[pascal][atmosphere]; + conv[bar][bar] = 1.0; + conv[bar][dyne_per_centimetersq] = to_si*conv[pascal][dyne_per_centimetersq]; + conv[bar][picogram_per_micrometer_microsecondsq] = to_si*conv[pascal][picogram_per_micrometer_microsecondsq]; + conv[bar][attogram_per_nanometer_nanosecondsq] = to_si*conv[pascal][attogram_per_nanometer_nanosecondsq]; + + to_si = 1.0/conv[pascal][dyne_per_centimetersq]; + conv[dyne_per_centimetersq][pascal] = to_si*conv[pascal][pascal]; + conv[dyne_per_centimetersq][atmosphere] = to_si*conv[pascal][atmosphere]; + conv[dyne_per_centimetersq][bar] = to_si*conv[pascal][bar]; + conv[dyne_per_centimetersq][dyne_per_centimetersq] = 1.0; + conv[dyne_per_centimetersq][picogram_per_micrometer_microsecondsq] = to_si*conv[pascal][picogram_per_micrometer_microsecondsq]; + conv[dyne_per_centimetersq][attogram_per_nanometer_nanosecondsq] = to_si*conv[pascal][attogram_per_nanometer_nanosecondsq]; + + to_si = 1.0/conv[pascal][picogram_per_micrometer_microsecondsq]; + conv[picogram_per_micrometer_microsecondsq][pascal] = to_si*conv[pascal][pascal]; + conv[picogram_per_micrometer_microsecondsq][atmosphere] = to_si*conv[pascal][atmosphere]; + conv[picogram_per_micrometer_microsecondsq][bar] = to_si*conv[pascal][bar]; + conv[picogram_per_micrometer_microsecondsq][dyne_per_centimetersq] = to_si*conv[pascal][dyne_per_centimetersq]; + conv[picogram_per_micrometer_microsecondsq][picogram_per_micrometer_microsecondsq] = 1.0; + conv[picogram_per_micrometer_microsecondsq][attogram_per_nanometer_nanosecondsq] = to_si*conv[pascal][attogram_per_nanometer_nanosecondsq]; + + to_si = 1.0/conv[pascal][attogram_per_nanometer_nanosecondsq]; + conv[attogram_per_nanometer_nanosecondsq][pascal] = to_si*conv[pascal][pascal]; + conv[attogram_per_nanometer_nanosecondsq][atmosphere] = to_si*conv[pascal][atmosphere]; + conv[attogram_per_nanometer_nanosecondsq][bar] = to_si*conv[pascal][bar]; + conv[attogram_per_nanometer_nanosecondsq][dyne_per_centimetersq] = to_si*conv[pascal][dyne_per_centimetersq]; + conv[attogram_per_nanometer_nanosecondsq][picogram_per_micrometer_microsecondsq] = to_si*conv[pascal][picogram_per_micrometer_microsecondsq]; + conv[attogram_per_nanometer_nanosecondsq][attogram_per_nanometer_nanosecondsq] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Viscosity conversion +double get_viscosity_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[pascal_second][pascal_second] = 1.0; + conv[pascal_second][poise] = 1.0/poise_si; + conv[pascal_second][amu_per_bohr_femtosecond] = 1.0/amu_per_bohr_femtosecond_si; + conv[pascal_second][picogram_per_micrometer_microsecond] = 1.0/picogram_per_micrometer_microsecond_si; + conv[pascal_second][attogram_per_nanometer_nanosecond] = 1.0/attogram_per_nanometer_nanosecond_si; + + to_si = 1.0/conv[pascal_second][poise]; + conv[poise][pascal_second] = to_si*conv[pascal_second][pascal_second]; + conv[poise][poise] = 1.0; + conv[poise][amu_per_bohr_femtosecond] = to_si*conv[pascal_second][amu_per_bohr_femtosecond]; + conv[poise][picogram_per_micrometer_microsecond] = to_si*conv[pascal_second][picogram_per_micrometer_microsecond]; + conv[poise][attogram_per_nanometer_nanosecond] = to_si*conv[pascal_second][attogram_per_nanometer_nanosecond]; + + to_si = 1.0/conv[pascal_second][amu_per_bohr_femtosecond]; + conv[amu_per_bohr_femtosecond][pascal_second] = to_si*conv[pascal_second][pascal_second]; + conv[amu_per_bohr_femtosecond][poise] = to_si*conv[pascal_second][poise]; + conv[amu_per_bohr_femtosecond][amu_per_bohr_femtosecond] = 1.0; + conv[amu_per_bohr_femtosecond][picogram_per_micrometer_microsecond] = to_si*conv[pascal_second][picogram_per_micrometer_microsecond]; + conv[amu_per_bohr_femtosecond][attogram_per_nanometer_nanosecond] = to_si*conv[pascal_second][attogram_per_nanometer_nanosecond]; + + to_si = 1.0/conv[pascal_second][picogram_per_micrometer_microsecond]; + conv[picogram_per_micrometer_microsecond][pascal_second] = to_si*conv[pascal_second][pascal_second]; + conv[picogram_per_micrometer_microsecond][poise] = to_si*conv[pascal_second][poise]; + conv[picogram_per_micrometer_microsecond][amu_per_bohr_femtosecond] = to_si*conv[pascal_second][amu_per_bohr_femtosecond]; + conv[picogram_per_micrometer_microsecond][picogram_per_micrometer_microsecond] = 1.0; + conv[picogram_per_micrometer_microsecond][attogram_per_nanometer_nanosecond] = to_si*conv[pascal_second][attogram_per_nanometer_nanosecond]; + + to_si = 1.0/conv[pascal_second][attogram_per_nanometer_nanosecond]; + conv[attogram_per_nanometer_nanosecond][pascal_second] = to_si*conv[pascal_second][pascal_second]; + conv[attogram_per_nanometer_nanosecond][poise] = to_si*conv[pascal_second][poise]; + conv[attogram_per_nanometer_nanosecond][amu_per_bohr_femtosecond] = to_si*conv[pascal_second][amu_per_bohr_femtosecond]; + conv[attogram_per_nanometer_nanosecond][picogram_per_micrometer_microsecond] = to_si*conv[pascal_second][picogram_per_micrometer_microsecond]; + conv[attogram_per_nanometer_nanosecond][attogram_per_nanometer_nanosecond] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Charge conversion +double get_charge_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[coulomb][coulomb] = 1.0; + conv[coulomb][echarge] = 1.0/echarge_si; + conv[coulomb][statcoulomb] = 1.0/statcoulomb_si; + conv[coulomb][picocoulomb] = 1.0/picocoulomb_si; + + to_si = 1.0/conv[coulomb][echarge]; + conv[echarge][coulomb] = to_si*conv[coulomb][coulomb]; + conv[echarge][echarge] = 1.0; + conv[echarge][statcoulomb] = to_si*conv[coulomb][statcoulomb]; + conv[echarge][picocoulomb] = to_si*conv[coulomb][picocoulomb]; + + to_si = 1.0/conv[coulomb][statcoulomb]; + conv[statcoulomb][coulomb] = to_si*conv[coulomb][coulomb]; + conv[statcoulomb][echarge] = to_si*conv[coulomb][echarge]; + conv[statcoulomb][statcoulomb] = 1.0; + conv[statcoulomb][picocoulomb] = to_si*conv[coulomb][picocoulomb]; + + to_si = 1.0/conv[coulomb][picocoulomb]; + conv[picocoulomb][coulomb] = to_si*conv[coulomb][coulomb]; + conv[picocoulomb][echarge] = to_si*conv[coulomb][echarge]; + conv[picocoulomb][statcoulomb] = to_si*conv[coulomb][statcoulomb]; + conv[picocoulomb][picocoulomb] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Dipole conversion +double get_dipole_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[coulomb_meter][coulomb_meter] = 1.0; + conv[coulomb_meter][electron_angstrom] = 1.0/electron_angstrom_si; + conv[coulomb_meter][statcoulomb_centimeter] = 1.0/statcoulomb_centimeter_si; + conv[coulomb_meter][debye] = 1.0/debye_si; + conv[coulomb_meter][picocoulomb_micrometer] = 1.0/picocoulomb_micrometer_si; + conv[coulomb_meter][electron_nanometer] = 1.0/electron_nanometer_si; + + to_si = 1.0/conv[coulomb_meter][electron_angstrom]; + conv[electron_angstrom][coulomb_meter] = to_si*conv[coulomb_meter][coulomb_meter]; + conv[electron_angstrom][electron_angstrom] = 1.0; + conv[electron_angstrom][statcoulomb_centimeter] = to_si*conv[coulomb_meter][statcoulomb_centimeter]; + conv[electron_angstrom][debye] = to_si*conv[coulomb_meter][debye]; + conv[electron_angstrom][picocoulomb_micrometer] = to_si*conv[coulomb_meter][picocoulomb_micrometer]; + conv[electron_angstrom][electron_nanometer] = to_si*conv[coulomb_meter][electron_nanometer]; + + to_si = 1.0/conv[coulomb_meter][statcoulomb_centimeter]; + conv[statcoulomb_centimeter][coulomb_meter] = to_si*conv[coulomb_meter][coulomb_meter]; + conv[statcoulomb_centimeter][electron_angstrom] = to_si*conv[coulomb_meter][electron_angstrom]; + conv[statcoulomb_centimeter][statcoulomb_centimeter] = 1.0; + conv[statcoulomb_centimeter][debye] = to_si*conv[coulomb_meter][debye]; + conv[statcoulomb_centimeter][picocoulomb_micrometer] = to_si*conv[coulomb_meter][picocoulomb_micrometer]; + conv[statcoulomb_centimeter][electron_nanometer] = to_si*conv[coulomb_meter][electron_nanometer]; + + to_si = 1.0/conv[coulomb_meter][debye]; + conv[debye][coulomb_meter] = to_si*conv[coulomb_meter][coulomb_meter]; + conv[debye][electron_angstrom] = to_si*conv[coulomb_meter][electron_angstrom]; + conv[debye][statcoulomb_centimeter] = to_si*conv[coulomb_meter][statcoulomb_centimeter]; + conv[debye][debye] = 1.0; + conv[debye][picocoulomb_micrometer] = to_si*conv[coulomb_meter][picocoulomb_micrometer]; + conv[debye][electron_nanometer] = to_si*conv[coulomb_meter][electron_nanometer]; + + to_si = 1.0/conv[coulomb_meter][picocoulomb_micrometer]; + conv[picocoulomb_micrometer][coulomb_meter] = to_si*conv[coulomb_meter][coulomb_meter]; + conv[picocoulomb_micrometer][electron_angstrom] = to_si*conv[coulomb_meter][electron_angstrom]; + conv[picocoulomb_micrometer][statcoulomb_centimeter] = to_si*conv[coulomb_meter][statcoulomb_centimeter]; + conv[picocoulomb_micrometer][debye] = to_si*conv[coulomb_meter][debye]; + conv[picocoulomb_micrometer][picocoulomb_micrometer] = 1.0; + conv[picocoulomb_micrometer][electron_nanometer] = to_si*conv[coulomb_meter][electron_nanometer]; + + to_si = 1.0/conv[coulomb_meter][electron_nanometer]; + conv[electron_nanometer][coulomb_meter] = to_si*conv[coulomb_meter][coulomb_meter]; + conv[electron_nanometer][electron_angstrom] = to_si*conv[coulomb_meter][electron_angstrom]; + conv[electron_nanometer][statcoulomb_centimeter] = to_si*conv[coulomb_meter][statcoulomb_centimeter]; + conv[electron_nanometer][debye] = to_si*conv[coulomb_meter][debye]; + conv[electron_nanometer][picocoulomb_micrometer] = to_si*conv[coulomb_meter][picocoulomb_micrometer]; + conv[electron_nanometer][electron_nanometer] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Electric field conversion +double get_efield_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[volt_per_meter][volt_per_meter] = 1.0; + conv[volt_per_meter][volt_per_angstrom] = 1.0/volt_per_angstrom_si; + conv[volt_per_meter][statvolt_per_centimeter] = 1.0/statvolt_per_centimeter_si; + conv[volt_per_meter][volt_per_centimeter] = 1.0/volt_per_centimeter_si; + conv[volt_per_meter][volt_per_micrometer] = 1.0/volt_per_micrometer_si; + conv[volt_per_meter][volt_per_nanometer] = 1.0/volt_per_nanometer_si; + + to_si = 1.0/conv[volt_per_meter][volt_per_angstrom]; + conv[volt_per_angstrom][volt_per_meter] = to_si*conv[volt_per_meter][volt_per_meter]; + conv[volt_per_angstrom][volt_per_angstrom] = 1.0; + conv[volt_per_angstrom][statvolt_per_centimeter] = to_si*conv[volt_per_meter][statvolt_per_centimeter]; + conv[volt_per_angstrom][volt_per_centimeter] = to_si*conv[volt_per_meter][volt_per_centimeter]; + conv[volt_per_angstrom][volt_per_micrometer] = to_si*conv[volt_per_meter][volt_per_micrometer]; + conv[volt_per_angstrom][volt_per_nanometer] = to_si*conv[volt_per_meter][volt_per_nanometer]; + + to_si = 1.0/conv[volt_per_meter][statvolt_per_centimeter]; + conv[statvolt_per_centimeter][volt_per_meter] = to_si*conv[volt_per_meter][volt_per_meter]; + conv[statvolt_per_centimeter][volt_per_angstrom] = to_si*conv[volt_per_meter][volt_per_angstrom]; + conv[statvolt_per_centimeter][statvolt_per_centimeter] = 1.0; + conv[statvolt_per_centimeter][volt_per_centimeter] = to_si*conv[volt_per_meter][volt_per_centimeter]; + conv[statvolt_per_centimeter][volt_per_micrometer] = to_si*conv[volt_per_meter][volt_per_micrometer]; + conv[statvolt_per_centimeter][volt_per_nanometer] = to_si*conv[volt_per_meter][volt_per_nanometer]; + + to_si = 1.0/conv[volt_per_meter][volt_per_centimeter]; + conv[volt_per_centimeter][volt_per_meter] = to_si*conv[volt_per_meter][volt_per_meter]; + conv[volt_per_centimeter][volt_per_angstrom] = to_si*conv[volt_per_meter][volt_per_angstrom]; + conv[volt_per_centimeter][statvolt_per_centimeter] = to_si*conv[volt_per_meter][statvolt_per_centimeter]; + conv[volt_per_centimeter][volt_per_centimeter] = 1.0; + conv[volt_per_centimeter][volt_per_micrometer] = to_si*conv[volt_per_meter][volt_per_micrometer]; + conv[volt_per_centimeter][volt_per_nanometer] = to_si*conv[volt_per_meter][volt_per_nanometer]; + + to_si = 1.0/conv[volt_per_meter][volt_per_micrometer]; + conv[volt_per_micrometer][volt_per_meter] = to_si*conv[volt_per_meter][volt_per_meter]; + conv[volt_per_micrometer][volt_per_angstrom] = to_si*conv[volt_per_meter][volt_per_angstrom]; + conv[volt_per_micrometer][statvolt_per_centimeter] = to_si*conv[volt_per_meter][statvolt_per_centimeter]; + conv[volt_per_micrometer][volt_per_centimeter] = to_si*conv[volt_per_meter][volt_per_centimeter]; + conv[volt_per_micrometer][volt_per_micrometer] = 1.0; + conv[volt_per_micrometer][volt_per_nanometer] = to_si*conv[volt_per_meter][volt_per_nanometer]; + + to_si = 1.0/conv[volt_per_meter][volt_per_nanometer]; + conv[volt_per_nanometer][volt_per_meter] = to_si*conv[volt_per_meter][volt_per_meter]; + conv[volt_per_nanometer][volt_per_angstrom] = to_si*conv[volt_per_meter][volt_per_angstrom]; + conv[volt_per_nanometer][statvolt_per_centimeter] = to_si*conv[volt_per_meter][statvolt_per_centimeter]; + conv[volt_per_nanometer][volt_per_centimeter] = to_si*conv[volt_per_meter][volt_per_centimeter]; + conv[volt_per_nanometer][volt_per_micrometer] = to_si*conv[volt_per_meter][volt_per_micrometer]; + conv[volt_per_nanometer][volt_per_nanometer] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// Demsity conversion +double get_density_conversion_factor(units from_unit_enum, units to_unit_enum) +{ + map > conv; + double to_si; + + conv[kilogram_per_metercu][kilogram_per_metercu] = 1.0; + conv[kilogram_per_metercu][gram_per_centimetercu] = 1.0/gram_per_centimetercu_si; + conv[kilogram_per_metercu][amu_per_bohrcu] = 1.0/amu_per_bohrcu_si; + conv[kilogram_per_metercu][picogram_per_micrometercu] = 1.0/picogram_per_micrometercu_si; + conv[kilogram_per_metercu][attogram_per_nanometercu] = 1.0/attogram_per_nanometercu_si; + + to_si = 1.0/conv[kilogram_per_metercu][gram_per_centimetercu]; + conv[gram_per_centimetercu][kilogram_per_metercu] = to_si*conv[kilogram_per_metercu][kilogram_per_metercu]; + conv[gram_per_centimetercu][gram_per_centimetercu] = 1.0; + conv[gram_per_centimetercu][amu_per_bohrcu] = to_si*conv[kilogram_per_metercu][amu_per_bohrcu]; + conv[gram_per_centimetercu][picogram_per_micrometercu] = to_si*conv[kilogram_per_metercu][picogram_per_micrometercu]; + conv[gram_per_centimetercu][attogram_per_nanometercu] = to_si*conv[kilogram_per_metercu][attogram_per_nanometercu]; + + to_si = 1.0/conv[kilogram_per_metercu][amu_per_bohrcu]; + conv[amu_per_bohrcu][kilogram_per_metercu] = to_si*conv[kilogram_per_metercu][kilogram_per_metercu]; + conv[amu_per_bohrcu][gram_per_centimetercu] = to_si*conv[kilogram_per_metercu][gram_per_centimetercu]; + conv[amu_per_bohrcu][amu_per_bohrcu] = 1.0; + conv[amu_per_bohrcu][picogram_per_micrometercu] = to_si*conv[kilogram_per_metercu][picogram_per_micrometercu]; + conv[amu_per_bohrcu][attogram_per_nanometercu] = to_si*conv[kilogram_per_metercu][attogram_per_nanometercu]; + + to_si = 1.0/conv[kilogram_per_metercu][picogram_per_micrometercu]; + conv[picogram_per_micrometercu][kilogram_per_metercu] = to_si*conv[kilogram_per_metercu][kilogram_per_metercu]; + conv[picogram_per_micrometercu][gram_per_centimetercu] = to_si*conv[kilogram_per_metercu][gram_per_centimetercu]; + conv[picogram_per_micrometercu][amu_per_bohrcu] = to_si*conv[kilogram_per_metercu][amu_per_bohrcu]; + conv[picogram_per_micrometercu][picogram_per_micrometercu] = 1.0; + conv[picogram_per_micrometercu][attogram_per_nanometercu] = to_si*conv[kilogram_per_metercu][attogram_per_nanometercu]; + + to_si = 1.0/conv[kilogram_per_metercu][attogram_per_nanometercu]; + conv[attogram_per_nanometercu][kilogram_per_metercu] = to_si*conv[kilogram_per_metercu][kilogram_per_metercu]; + conv[attogram_per_nanometercu][gram_per_centimetercu] = to_si*conv[kilogram_per_metercu][gram_per_centimetercu]; + conv[attogram_per_nanometercu][amu_per_bohrcu] = to_si*conv[kilogram_per_metercu][amu_per_bohrcu]; + conv[attogram_per_nanometercu][picogram_per_micrometercu] = to_si*conv[kilogram_per_metercu][picogram_per_micrometercu]; + conv[attogram_per_nanometercu][attogram_per_nanometercu] = 1.0; + + return conv[from_unit_enum][to_unit_enum]; +} + +/* ---------------------------------------------------------------------- */ + +// This routine returns the unit conversion factor between the +// `from_system_enum` to the `to_system_enum` for the `unit_type_enum`. +double get_unit_conversion_factor(unit_type &unit_type_enum, + sys_type from_system_enum, + sys_type to_system_enum) +{ + units from_unit = get_lammps_system_unit(from_system_enum, unit_type_enum); + units to_unit = get_lammps_system_unit(to_system_enum, unit_type_enum); + switch(unit_type_enum) { + case mass : + return get_mass_conversion_factor(from_unit, to_unit); + case distance : + return get_distance_conversion_factor(from_unit, to_unit); + case time : + return get_time_conversion_factor(from_unit, to_unit); + case energy : + return get_energy_conversion_factor(from_unit, to_unit); + case velocity : + return get_velocity_conversion_factor(from_unit, to_unit); + case force : + return get_force_conversion_factor(from_unit, to_unit); + case torque : + return get_torque_conversion_factor(from_unit, to_unit); + case temperature : + return get_temperature_conversion_factor(from_unit, to_unit); + case pressure : + return get_pressure_conversion_factor(from_unit, to_unit); + case viscosity : + return get_viscosity_conversion_factor(from_unit, to_unit); + case charge : + return get_charge_conversion_factor(from_unit, to_unit); + case dipole : + return get_dipole_conversion_factor(from_unit, to_unit); + case efield : + return get_efield_conversion_factor(from_unit, to_unit); + case density : + default : // This is here to a prevent a compiler warning + return get_density_conversion_factor(from_unit, to_unit); + } +} + +} // end of anonymous name space + +/* ---------------------------------------------------------------------- */ + +// Wrapper to the routine that gets the unit conversion. Translates strings +// to enumerations and then call get_unit_conversion_factor() +int lammps_unit_conversion(string const &unit_type_str, + string const &from_system_str, + string const &to_system_str, + double &conversion_factor) +{ + // initialize + conversion_factor = 0.0; + initialize_dictionaries(); + + // convert input to enumeration + unit_type unit_type_enum; + { + map::const_iterator itr = unit_dic.find(unit_type_str); + if (itr != unit_dic.end()) unit_type_enum = itr->second; + else return 1; // error + } + sys_type from_system_enum; + { + map::const_iterator + itr = system_dic.find(from_system_str); + if (itr != system_dic.end()) from_system_enum = itr->second; + else return 1; // error + } + sys_type to_system_enum; + { + map::const_iterator + itr = system_dic.find(to_system_str); + if (itr != system_dic.end()) to_system_enum = itr->second; + else return 1; + } + + // process unit conversions + conversion_factor = get_unit_conversion_factor(unit_type_enum, + from_system_enum, + to_system_enum); + return 0; +} + + diff --git a/src/KIM/kim_units.h b/src/KIM/kim_units.h new file mode 100644 index 0000000000..97e81a6222 --- /dev/null +++ b/src/KIM/kim_units.h @@ -0,0 +1,59 @@ +/* -*- c++ -*- ---------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + http://lammps.sandia.gov, Sandia National Laboratories + Steve Plimpton, sjplimp@sandia.gov + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Contributing authors: Ellad B. Tadmor (UMN) +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along with + this program; if not, see . + + Linking LAMMPS statically or dynamically with other modules is making a + combined work based on LAMMPS. Thus, the terms and conditions of the GNU + General Public License cover the whole combination. + + In addition, as a special exception, the copyright holders of LAMMPS give + you permission to combine LAMMPS with free software programs or libraries + that are released under the GNU LGPL and with code included in the standard + release of the "kim-api" under the CDDL (or modified versions of such code, + with unchanged license). You may copy and distribute such a system following + the terms of the GNU GPL for LAMMPS and the licenses of the other code + concerned, provided that you include the source code of that other code + when and as the GNU GPL requires distribution of source code. + + Note that people who make modified versions of LAMMPS are not obligated to + grant this special exception for their modified versions; it is their choice + whether to do so. The GNU General Public License gives permission to release + a modified version without this exception; this exception also makes it + possible to release a modified version which carries forward this exception. +------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------- + Designed for use with the kim-api-2.0.2 (and newer) package +------------------------------------------------------------------------- */ + +int lammps_unit_conversion(std::string const &unit_type_str, + std::string const &from_system_str, + std::string const &to_system_str, + double &conversion_factor);