Installation

This guide covers how to build and install Cocoa on your system.

Prerequisites

Before building Cocoa, ensure you have the following dependencies installed:

Compilers

Cocoa requires a C++20 compatible compiler. The minimum versions are dictated by Kokkos 5.0 (included with Trilinos 17), which sets stricter requirements than C++20 alone.

Table 1 Minimum Compiler Requirements

Compiler

Minimum Version

Notes

GCC

10.4.0

Recommended for CPU and as CUDA host compiler

Clang (CPU)

14.0.0

For CPU-only builds

Clang (CUDA host)

15.0.0

When used as nvcc host compiler

NVIDIA nvcc

12.2

Requires CUDA Toolkit 12.2+

Intel icpx (CPU)

2022.0.0

Intel oneAPI DPC++/C++ Compiler

Intel icpx (SYCL)

2024.2.1

For SYCL backend builds

ROCm (HIPCC)

6.2.0

For AMD GPU builds

NVIDIA HPC SDK (NVC++)

22.3

Alternative to nvcc for NVIDIA GPUs

Note

These requirements are set by Kokkos 5.0. See the Kokkos Requirements documentation for the most up-to-date information.

Build System

  • CMake 3.23 or later

  • GNU Make or Ninja build system

Required Libraries

The following libraries must be pre-installed on your system:

  • Trilinos 17.0 or later (with Kokkos, KokkosKernels, Tpetra, Belos, Ifpack2, Zoltan2 enabled)

  • NetCDF-C (4.9.3+ recommended; for mesh and output I/O)

  • HDF5 (development headers required; installed automatically as a NetCDF-C dependency)

Warning

NetCDF-C versions prior to 4.9.3 have a bug (#2674) that causes spurious HDF5 error messages on stderr when reading variables. Ubuntu 24.04 ships NetCDF-C 4.9.2; if using that distribution, build NetCDF-C 4.9.3+ from source.

  • ParMETIS (for mesh partitioning, required via Zoltan2 for MPI builds)

Note

Trilinos 17.0+ is required because it includes Kokkos 5.0+ which uses APIs that Cocoa depends on.

Automatically Fetched Dependencies

The following dependencies are automatically downloaded and built via CPM during CMake configuration:

  • yaml-cpp (configuration file parsing)

  • spdlog (logging)

  • fmt (string formatting)

  • Catch2 (unit testing)

Optional Dependencies

  • CUDA Toolkit (for NVIDIA GPU support, required for Trilinos CUDA build)

  • ROCm (for AMD GPU support, required for Trilinos HIP build)

  • MPI (for distributed computing, if Trilinos was built with MPI)

Building from Source

Clone the Repository

git clone https://github.com/cocoaorg/cocoa.git
cd cocoa

Configure with CMake

Basic Build:

mkdir build && cd build
cmake .. \
    -DCMAKE_BUILD_TYPE=Release \
    -DNETCDF_DIR=/path/to/netcdf-c \
    -DTrilinos_DIR=/path/to/trilinos

With custom install prefix:

cmake .. \
    -DCMAKE_BUILD_TYPE=Release \
    -DCMAKE_INSTALL_PREFIX=/path/to/install \
    -DNETCDF_DIR=/path/to/netcdf-c \
    -DTrilinos_DIR=/path/to/trilinos

CMake Options

Option

Description

Default

NETCDF_DIR

Hint path for CMake’s FindNetCDF module. Point to the NetCDF-C installation prefix.

(auto-detected; required if not in system paths)

Trilinos_DIR

Path to the Trilinos CMake config directory (e.g., <prefix>/lib/cmake/Trilinos).

(auto-detected; required if not in system paths)

cocoa_BACKEND

Combined execution space and MPI configuration. Available options depend on the Trilinos build. Examples: CUDA+MPI, CUDA, HIP+MPI, OPENMP+MPI, OPENMP, SERIAL+MPI, SERIAL.

DEFAULT – auto-selects the best available backend from Trilinos (prefers GPU over CPU, MPI over non-MPI)

CMAKE_BUILD_TYPE

Build type. Options: Release, Debug, RelWithDebInfo, MinSizeRel.

RelWithDebInfo (if not specified)

CMAKE_INSTALL_PREFIX

Installation directory for make install.

/usr/local

BUILD_TESTING

Build the unit test suite (requires Catch2, fetched automatically).

OFF

cocoa_MAINTAINER_MODE

Enable strict compiler warnings, sanitizers, cppcheck, and hardening. Automatically enabled when building as the top-level project.

OFF (ON when top-level project)

cocoa_CUDA_MEMORY_SPACE

CUDA memory space. CUDA for device memory, CUDAUVM for unified virtual memory. Only applies to CUDA backends.

CUDA

cocoa_USE_THRUST

Use thrust::copy_if for the wet/dry stream compaction on OpenMP and Serial backends (advanced). See Stream Compaction below. Requires a Thrust/CCCL installation. CUDA builds always use CUB and ignore this option.

OFF

cocoa_ENABLE_GRIB

Enable GRIB2 meteorological forcing (GFS, HRRR, …). Requires an installed ECMWF ecCodes (found via eccodes_DIR) built with the JPEG2000 (Jasper or OpenJPEG) and CCSDS/AEC codecs that NCEP products use; cocoa checks for those features at configure time. See Meteorological Forcing.

OFF

eccodes_DIR

Path to the ecCodes CMake config directory (e.g., <prefix>/lib/cmake/eccodes). Required with cocoa_ENABLE_GRIB=ON if ecCodes is not in the default search paths. Install a suitable build with, e.g., spack install eccodes +memfs +aec jp2k=openjpeg.

(auto-detected)

cocoa_PRINT_LOG_TIME

Print elapsed wall-clock time in screen log output.

OFF

Floating-Point Precision

Cocoa computes in double precision (FP64). There is no build-time precision option: to reduce GPU memory traffic, a fixed set of bandwidth-sensitive fields is stored as float and promoted to double on read, while all arithmetic stays in double. See Numerical Methods for the list of mixed-precision fields and the rationale.

Stream Compaction

Each step, the wet/dry solver rebuilds compacted lists of the currently wet elements and nodes – a stream compaction (copy_if over an index range). The implementation is selected by backend:

  • CUDA: cub::DeviceSelect::If on the Kokkos execution-space stream, with the algorithm’s temporary storage allocated once at setup and reused every step (no per-step cudaMalloc/cudaFree). CUB ships with the CUDA Toolkit, so no extra setup is needed.

  • OpenMP/Serial with cocoa_USE_THRUST=ON: thrust::copy_if through the matching thrust host device system.

  • Otherwise: a fused Kokkos parallel_scan.

All implementations use the same selection predicate and produce identical results.

cocoa_USE_THRUST is an advanced option that applies only to OpenMP and Serial backends; CUDA builds always use CUB and ignore it. Enabling it requires a Thrust installation, typically via NVIDIA CCCL, with CMake pointed at it:

cmake .. \
    -Dcocoa_BACKEND=OPENMP+MPI \
    -Dcocoa_USE_THRUST=ON \
    -DCCCL_DIR=/path/to/cccl/lib/cmake/cccl
    # or, for a standalone Thrust:
    # -DThrust_DIR=/path/to/thrust/lib/cmake/thrust

Cocoa configures the thrust host device system to match the selected backend (OpenMP or Serial). If cocoa_USE_THRUST=ON is requested but no Thrust/CCCL installation is found, or the backend is neither OpenMP nor Serial (and not CUDA, where the option is ignored), configuration fails with an explanatory error.

Compile

make -j$(nproc)

Install

make install

Verifying the Installation

Run the test suite to verify your installation:

ctest --output-on-failure