================ Cello Components ================ The software design of Enzo-E / ``Cello`` is based on object-oriented programming (OOP), a proven software design and implementation paradigm that helps reduce software complexity and improves code maintainability. .. image:: components.png The ``Cello`` framework is functionally decomposed into a collection of software components. The ``Enzo-E`` application is implemented on top of Cello, which is comprised of the components within the central boxed region. ``Cello`` is in turn implemented using the Charm++ parallel programming system. Components in ``Cello`` are organized into multiple layers, with software dependencies directed primarily downwards; cross-cutting software concerns are also implemented as components. Each component is composed of one or more inter-operating C++ classes. Enzo-E ====== ``Enzo-E`` is the astrophysics and cosmology application built on top of the ``Cello`` scalable AMR framework. ``Enzo-E`` interfaces with ``Cello`` primarily through C++ class inheritance of ``Cello`` classes in the ``Simulation``, ``Problem``, ``Method``, and ``Mesh`` components. Due to the separation of concerns between ``Enzo-E`` and Cello, development of ``Enzo-E`` requires no knowledge or awareness of parallel programming, and development of ``Cello`` requires no knowledge of specific numerical methods. This allows relatively independent software development of ``Enzo-E`` by physical science and numerical methods experts, and of ``Cello`` by computer science and parallel programming experts. High-level components ===================== Top level components of ``Cello`` include ``Simulation``, ``Problem``, and ``Method``. A ``Simulation`` defines and manages a computational astrophysics ``Problem``, which defines physics, method, and data structure ``Parameters``, initial conditions, and boundary conditions. The ``Simulation`` class, which is implemented as a ``Charm`` *process group*, initializes and begins parallel execution of the simulation. ``Method`` classes are used to implement individual numerical methods that compute on ``Field`` (current) data on a block, as well as ``Particle`` and ``Ray`` data (proposed). Data structure components ========================= Data structure components include the existing ``Mesh`` and ``Field`` components, and the proposed ``Particle`` and ``Ray`` components, for implementing the distributed computational data containers. The ``Mesh`` component includes classes for representing and operating on an adaptive mesh hierarchy, implemented as a fully-distributed array-of-octrees. Octree nodes are associated with Blocks, which are containers for the ``Field`` and other data, and implemented as a Charm++ *chare array*. Middle-level components ======================= Middle-level components include ``Control``, ``Parameters`` and ``Io`` ``Control`` handles the time stepping of ``Method`` s to advance the problem forward in time, as well as sequencing adaptive mesh refinement data structure operations, including remeshing, scheduling dynamic load balancing (which will be delegated to Charm++), and refreshing ghost zones on Block boundaries. The ``Parameters`` component serves to read, store, and provide access to parameters defined in an input configuration file. To improve usability over Enzo, configuration files are more structured, and support floating-point and logical expressions to greatly simplify initializing problems with complex initial conditions. The ``Io`` component serves as a layer to coordinate the disk output of data structure components, such as ``Simulation`` ``Hierarchy`` and ``Field`` data. It calls the ``Disk`` component to handle actual file operations. Hardware-interface components ============================= The lower-level hardware-interface components include ``Disk``, ``Memory`` and ``Parallel``. The ``Disk`` component implements basic disk operations, isolating the specific file format from the higher-level ``Io`` component. ``Disk`` currently supports HDF5, and we propose to support the Adaptable IO System (ADIOS) in the future to enhance transfer of data to and from other HPC software components. The ``Memory`` component controls dynamic memory allocation and management. Currently ``Memory`` handles allocating and monitoring heap memory usage; proposed functionality includes allocating, deallocating, and transferring data between main memory, hardware accelerator (GPU) memory, and many-core coprocessors (e.g.~the Intel Xeon Phi). As with the ``Disk`` component, this serves to isolate lower-level details from higher-level components. The ``Parallel`` component currently supplies basic access to core rank and core count, and is being depreciated. Interface components ==================== Interface components include ``Monitor`` (current) and ``Portal`` (proposed). The ``Monitor`` component controls the user-readable summary of progress to stdout, and the proposed ``Portal`` component will control the interaction of ``Enzo-E`` with external applications running concurrently, such as inline analysis or real-time visualization. One particular such analysis and visualization application is yt, which we will use to help drive the design and development of the ``Portal`` component. Cross-cutting components ======================== Some ``Cello`` components can in principle be called from any software layer---these include ``Performance`` and ``Error``. The ``Performance`` component dynamically collects performance data for the running ``Enzo-E`` simulation, and provides a holistic summary of performance data to the user, as well as to software components that can adapt to optimize desired performance metrics. Current metrics measured include memory usage (via the ``Memory`` component), and computation amount and memory access amount (via the Performance Application Programming Interface (PAPI). Future support will include metrics for monitoring parallel communication, dynamic load balancing, and disk usage. The ``Error`` component will be used to detect, evaluate, and decide what to do about software errors; higher-level error detection and recovery will be handled by Charm++, which supports both simple checkpoint to disk, as well as double in-memory checkpoint with automatic restart.