Minimal Celeritas usage#

This simple example shows how to incorporate an already-installed Celeritas into a downstream project.

CMake infrastructure#

A three-line helper script FindCeleritas.cmake gives more verbose loading messages when using Celeritas externally.

find_package(Celeritas QUIET CONFIG)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Celeritas CONFIG_MODE)

The CMake code itself is straightforward, though note the use of celeritas_target_link_libraries instead of target_link_libraries to support CUDA RDC, which is required by VecGeom.

project(CeleritasMinimalExample VERSION 0.0.1 LANGUAGES CXX)
cmake_policy(VERSION 3.12...3.22)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/..")
find_package(Celeritas 0.4 REQUIRED)

add_executable(minimal minimal.cc)

# Use special linking macros to support CUDA RDC across multiple libraries when
# using VecGeom.
include(CeleritasLibrary)
celeritas_target_link_libraries(minimal
  Celeritas::celeritas
)

Main executable#

#include <memory>
#include <celeritas/Constants.hh>
#include <celeritas/phys/PDGNumber.hh>
#include <celeritas/phys/ParticleParams.hh>
#include <corecel/io/Logger.hh>
#include <corecel/math/Quantity.hh>
#include <corecel/sys/Device.hh>
#include <corecel/sys/MpiCommunicator.hh>
#include <corecel/sys/ScopedMpiInit.hh>

using celeritas::ParticleParams;
using celeritas::PDGNumber;
using celeritas::value_as;
using celeritas::units::ElementaryCharge;
using celeritas::units::MevMass;

namespace
{
//---------------------------------------------------------------------------//
std::shared_ptr<ParticleParams> make_particles()
{
    constexpr auto zero = celeritas::zero_quantity();
    constexpr auto stable = celeritas::constants::stable_decay_constant;

    ParticleParams::Input defs;
    defs.push_back({"electron",
                    celeritas::pdg::electron(),
                    MevMass{0.5109989461},
                    ElementaryCharge{-1},
                    stable});
    defs.push_back({"gamma", celeritas::pdg::gamma(), zero, zero, stable});
    defs.push_back({"neutron",
                    PDGNumber{2112},
                    MevMass{939.565413},
                    zero,
                    1.0 / (879.4 * celeritas::units::second)});

    return std::make_shared<ParticleParams>(std::move(defs));
}

//---------------------------------------------------------------------------//
}  // namespace

int main(int argc, char* argv[])
{
    using celeritas::MpiCommunicator;
    using celeritas::ScopedMpiInit;

    // Initialize MPI
    ScopedMpiInit scoped_mpi(&argc, &argv);
    MpiCommunicator comm
        = (ScopedMpiInit::status() == ScopedMpiInit::Status::disabled
               ? MpiCommunicator{}
               : MpiCommunicator::comm_world());

    // Initialize GPU
    celeritas::activate_device(comm);

    // Create particle definitions (copies to GPU if available)
    auto particles = make_particles();

    // Find the identifier for a neutron and make sure it exists
    celeritas::ParticleId pid = particles->find(PDGNumber{2112});
    CELER_ASSERT(pid);
    // Get a particle "view" with properties about the neutron
    auto neutron = particles->get(pid);
    CELER_LOG(info) << "Neutron has a mass of "
                    << value_as<MevMass>(neutron.mass()) << "MeV / c^2"
                    << " = " << native_value_from(neutron.mass()) << " g";
    CELER_LOG(info) << "Its decay constant is " << neutron.decay_constant()
                    << " /s";
    CELER_LOG(info) << "This example doesn't do anything useful! Sorry!";
    return 0;
}