Program Listing for File atom_type.hpp

Return to documentation for file (cif++/atom_type.hpp)

/*-
 * SPDX-License-Identifier: BSD-2-Clause
 *
 * Copyright (c) 2020 NKI/AVL, Netherlands Cancer Institute
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include "cif++/exports.hpp"

#include <cstdint>
#include <limits>
#include <stdexcept>
#include <string>

namespace cif
{

enum atom_type : uint8_t
{
    Nn = 0,

    H = 1,
    He = 2,

    Li = 3,
    Be = 4,
    B = 5,
    C = 6,
    N = 7,
    O = 8,
    F = 9,
    Ne = 10,

    Na = 11,
    Mg = 12,
    Al = 13,
    Si = 14,
    P = 15,
    S = 16,
    Cl = 17,
    Ar = 18,

    K = 19,
    Ca = 20,
    Sc = 21,
    Ti = 22,
    V = 23,
    Cr = 24,
    Mn = 25,
    Fe = 26,
    Co = 27,
    Ni = 28,
    Cu = 29,
    Zn = 30,
    Ga = 31,
    Ge = 32,
    As = 33,
    Se = 34,
    Br = 35,
    Kr = 36,

    Rb = 37,
    Sr = 38,
    Y = 39,
    Zr = 40,
    Nb = 41,
    Mo = 42,
    Tc = 43,
    Ru = 44,
    Rh = 45,
    Pd = 46,
    Ag = 47,
    Cd = 48,
    In = 49,
    Sn = 50,
    Sb = 51,
    Te = 52,
    I = 53,
    Xe = 54,
    Cs = 55,
    Ba = 56,
    La = 57,

    Hf = 72,
    Ta = 73,
    W = 74,
    Re = 75,
    Os = 76,
    Ir = 77,
    Pt = 78,
    Au = 79,
    Hg = 80,
    Tl = 81,
    Pb = 82,
    Bi = 83,
    Po = 84,
    At = 85,
    Rn = 86,
    Fr = 87,
    Ra = 88,
    Ac = 89,

    Rf = 104,
    Db = 105,
    Sg = 106,
    Bh = 107,
    Hs = 108,
    Mt = 109,
    Ds = 110,
    Rg = 111,
    Cn = 112,
    Nh = 113,
    Fl = 114,
    Mc = 115,
    Lv = 116,
    Ts = 117,
    Og = 118,

    Ce = 58,
    Pr = 59,
    Nd = 60,
    Pm = 61,
    Sm = 62,
    Eu = 63,
    Gd = 64,
    Tb = 65,
    Dy = 66,
    Ho = 67,
    Er = 68,
    Tm = 69,
    Yb = 70,
    Lu = 71,

    Th = 90,
    Pa = 91,
    U = 92,
    Np = 93,
    Pu = 94,
    Am = 95,
    Cm = 96,
    Bk = 97,
    Cf = 98,
    Es = 99,
    Fm = 100,
    Md = 101,
    No = 102,
    Lr = 103,

    D = 119,
};

// --------------------------------------------------------------------


enum class radius_type
{
    calculated,
    empirical,

    covalent_empirical,

    single_bond,
    double_bond,
    triple_bond,

    van_der_waals,

    type_count
};

constexpr std::size_t kRadiusTypeCount = static_cast<std::size_t>(radius_type::type_count);


enum class ionic_radius_type
{
    effective,
    crystal
};

constexpr float kNA = std::numeric_limits<float>::quiet_NaN();


struct atom_type_info
{
    atom_type type;

    std::string name;

    std::string symbol;

    float weight;

    bool metal;

    float radii[kRadiusTypeCount];
};


extern CIFPP_EXPORT const atom_type_info kKnownAtoms[];

// --------------------------------------------------------------------
// AtomTypeTraits


class atom_type_traits
{
  public:
    atom_type_traits(atom_type a);

    atom_type_traits(const std::string &symbol);

    atom_type type() const { return m_info->type; }
    std::string name() const { return m_info->name; }
    std::string symbol() const { return m_info->symbol; }
    float weight() const { return m_info->weight; }

    bool is_metal() const { return m_info->metal; }

    static bool is_element(const std::string &symbol);

    static bool is_metal(const std::string &symbol);

    float radius(radius_type type = radius_type::single_bond) const
    {
        if (type >= radius_type::type_count)
            throw std::invalid_argument("invalid radius requested");
        return m_info->radii[static_cast<std::size_t>(type)] / 100.f;
    }

    float crystal_ionic_radius(int charge) const;

    float effective_ionic_radius(int charge) const;

    float ionic_radius(int charge, ionic_radius_type type = ionic_radius_type::effective) const
    {
        return type == ionic_radius_type::effective ? effective_ionic_radius(charge) : crystal_ionic_radius(charge);
    }

    struct SFData
    {
        double a[6], b[6];
    };

    static constexpr int kWKSFVal = -99;

    const SFData &wksf(int charge = 0) const;

    const SFData &elsf() const;

    bool has_sf(int charge) const;

  private:
    const struct atom_type_info *m_info;
};

} // namespace cif