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);
# 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.
a0 = chemist.Atom()
# 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.
a1 = chemist.Atom("H", 1, 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.
a2 = chemist.Atom("H", 1, 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.
a3 = chemist.Atom("H", 1, 1.0079, 0.0, 0.0, 0.0, 1.0, 2)
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);
# Default constructor
a5 = chemist.Atom()
# Explicit constructor with the given states
a6 = chemist.Atom("He", 2, 4.0026, 0.0, 0.0, 1.0, 2.0, 3)
# a5 and a6 are different atoms
assert a5 != a6
# Accessing the name
assert a5.name == ""
assert a6.name == "He"
a5.name = "He"
assert a5.name == a6.name
# Accessing the atomic number
assert a5.Z == 0
assert a6.Z == 2
a5.Z = 2
assert a5.Z == a6.Z
# Accessing the mass
assert a5.mass == 0.0
assert a6.mass == 4.0026
a5.mass = 4.0026
assert a5.mass == a6.mass
# Accessing the coordinates
assert a5.x == 0.0
assert a5.y == 0.0
assert a5.z == 0.0
assert a6.z == 1.0
a5.z = 1.0
assert a5.z == a6.z
# Accessing the nuclear charge
assert a5.nuclear_charge == 0.0
assert a6.nuclear_charge == 2.0
a5.nuclear_charge = 2.0
assert a5.nuclear_charge == a6.nuclear_charge
# Accessing the number of electrons
assert a5.n_electrons == 0
assert a6.n_electrons == 3
a5.n_electrons = 3
assert a5.n_electrons == a6.n_electrons
# Accessing the charge, note the parenthesis (read only)
assert a5.charge() == -1.0
assert a6.charge() == -1.0
# After all the changes above, a5 and a6 are now equal
assert 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);