Atom

Atoms are the fundamental building blocks of all matter. In Chemist, the Atom class represents an individual atom. This class is composed of the Nucleus class, which facilitates the access and modification of nucleus-specific properties. In addition, the Atom` class introduces atom-centric properties such as n_electrons(), denoting the number of electrons, and charge(), representing the net charge on the atom.

Construction

There are five different ways including the default and copy constructors to create an Atom object. The codes below shows how to create a Hydrogen atom using different constructors for both C++ and Python. The most explicit constructor enables a user to set the name, atomic number, mass, coordinates, nuclear charge, and number of electrons of an atom.

// Default constructor, properties are initialized to:
// name = '', atomic_number = 0, mass = 0.0
// x = 0.0, y = 0.0, z = 0.0, nuclear_charge = 0.0, n_electrons = 0.
Atom a0;
// Constructor with given name, atomic number, mass, and x, y, z coordinates.
// Nuclear charge and number of electrons are both set to the atomic number.
Atom a1("H", 1ul, 1.0079, 0.0, 0.0, 0.0);
// Constructor with given name, atomic number, mass, x, y, z, and  nuclear
// charge. Number of electrons is set to the atomic number.
Atom a2("H", 1ul, 1.0079, 0.0, 0.0, 0.0, 1.0);
// Constructor with given name, atomic number, mass, x, y, z, nuclear
// charge and number of electrons.
Atom a3("H", 1ul, 1.0079, 0.0, 0.0, 0.0, 1.0, 2);
// Copy constructor
Atom a4(a3);

Properties

Atom class provides read and write access to the following properties: - name: name of the atom - Z: atomic number of the atom - mass: mass of the atom in atomic units - x: x-coordinate of the atom - y: y-coordinate of the atom - z: z-coordinate of the atom - nuclear_charge: charge of the nucleus in atomic units One can also access the net charge of the atom using the charge() method, but this is a read only access. Below, you can find how to access the properties and modify them when possible both through the C++ and Python interfaces. You can also see that two Atom objects can be compared using the == operator.

    // Default constructor
    Atom a5;
    // Explicit constructor with the given states
    Atom a6("He", 2ul, 4.0026, 0.0, 0.0, 1.0, 2.0, 3);
    // a5 and a6 are not equal
    REQUIRE(a5 != a6);
    // Accessing the name (std::string)
    REQUIRE(a5.name() == "");
    REQUIRE(a6.name() == "He");
    a5.name() = "He";
    REQUIRE(a5.name() == a6.name());
    // Accessing the atomic number (unsigned integer)
    REQUIRE(a5.Z() == 0ul);
    REQUIRE(a6.Z() == 2ul);
    a5.Z() = 2ul;
    REQUIRE(a5.Z() == a6.Z());
    // Accessing the mass (double)
    REQUIRE(a5.mass() == 0.0);
    REQUIRE(a6.mass() == 4.0026);
    a5.mass() = 4.0026;
    REQUIRE(a5.mass() == a6.mass());
    // Accessing the coordinates
    REQUIRE(a5.x() == 0.0);
    REQUIRE(a5.y() == 0.0);
    REQUIRE(a5.z() == 0.0);
    REQUIRE(a6.z() == 1.0);
    a5.z() = 1.0;
    REQUIRE(a5.z() == a6.z());
    // Accessing the nuclear charge (double)
    REQUIRE(a5.nuclear_charge() == 0.0);
    REQUIRE(a6.nuclear_charge() == 2.0);
    a5.nuclear_charge() = 2.0;
    REQUIRE(a5.nuclear_charge() == a6.nuclear_charge());
    // Accessing the number of electrons (unsigned integer)
    REQUIRE(a5.n_electrons() == 0ul);
    REQUIRE(a6.n_electrons() == 3ul);
    a5.n_electrons() = 3ul;
    REQUIRE(a5.n_electrons() == a6.n_electrons());
    // Accessing the charge (double, read only)
    REQUIRE(a5.charge() == -1.0);
    REQUIRE(a6.charge() == -1.0);
    // After the changes above, a5 and a6 are equal
    REQUIRE(a5 == a6);

Serializing

Users can serialize an Atom object into a binary, XML, or JSON archive and deserialize accordingly with the C++ interface. We use Cereal library for serialization. Note that corresponding Cereal header files need to be included.

    std::stringstream ssb, ssj, ssx;
    {
        cereal::BinaryOutputArchive output_binary_archive(ssb);
        cereal::JSONOutputArchive output_json_archive(ssj);
        cereal::XMLOutputArchive output_xml_archive(ssx);
        output_binary_archive(a3);
        output_json_archive(a3);
        output_xml_archive(a3);
    }
    // Deserializing an Atom object
    Atom a7, a8, a9;
    {
        cereal::BinaryInputArchive input_binary_archive(ssb);
        cereal::JSONInputArchive input_json_archive(ssj);
        cereal::XMLInputArchive input_xml_archive(ssx);
        input_binary_archive(a7);
        input_json_archive(a8);
        input_xml_archive(a9);
    }
    REQUIRE(a3 == a7);
    REQUIRE(a3 == a8);
    REQUIRE(a3 == a9);