Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
9ac7c20
VIZ: ParticleBase, public EnableIDs, const getAttribute
klappi-s Jul 21, 2026
e031f30
VIZ: Add is_vector_v for ippl vectors
klappi-s Jul 21, 2026
e4f93fa
VIZ: Stream/Registry and Stream/InSitu
klappi-s Jul 21, 2026
bb047b0
VIZ: Fix optional ParticleID attribute
klappi-s Jul 21, 2026
a8a2484
Merge branch 'master' into catalyst-viz-v2.0.0
klappi-s Sep 4, 2026
1aa2545
VIZ: add Catalyst as an external dependency
klappi-s Sep 8, 2026
57f4f43
VIZ: Improve cmake structure and external file interactions
klappi-s Sep 8, 2026
6776302
VIZ: instrument PenningTrap with InSitu
klappi-s Sep 8, 2026
c559dca
VIZ: Change FEL visualization to catalyst based approach
klappi-s Sep 9, 2026
f4cc6aa
VIZ: Use conduit for json and yaml parsing in fel and proxywriter
klappi-s Sep 9, 2026
b3e2597
Merge branch 'IPPL-framework:master' into catalyst-viz-v2.0.0
klappi-s Sep 9, 2026
bc6ab2b
VIZ: particle png extraction, based on first appearing custom attribute
klappi-s Sep 9, 2026
e0936c2
VIZ: add particle attribute names to all demos, change attribute regi…
klappi-s Sep 9, 2026
94ff396
Merge branch 'catalyst-viz-v2.0.0' of github.com:klappi-s/ippl-frk in…
klappi-s Sep 9, 2026
2ae9e24
VIZ: Verbosity suppressed for level3 and below, for all Insitu Compon…
klappi-s Sep 10, 2026
3b79523
VIZ: small fixes, finish dimensional independence, some restructure
klappi-s Sep 10, 2026
2a7f2f6
Merge branch 'master' into catalyst-viz-v2.0.0
klappi-s Sep 10, 2026
7e0cd65
VIZ: map long long particle attributes to Conduit bitwidth types
biddisco Sep 14, 2026
498daec
Merge pull request #2 from IPPL-framework/catalyst-viz-v2.0.0
klappi-s Sep 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# ------------------------------------------------------------------------------
# CMake version requirement
# ------------------------------------------------------------------------------
cmake_minimum_required(VERSION 3.24)
cmake_minimum_required(VERSION 3.26)

# ------------------------------------------------------------------------------
# Policies - use the latest of everything
Expand Down Expand Up @@ -59,6 +59,10 @@ option(IPPL_MARK_FAILING_TESTS
OFF)
option(IPPL_ENABLE_SCRIPTS "Generate job script templates for some benchmarks/tests" OFF)


option(IPPL_ENABLE_CATALYST "Enable ParaView Catalyst" OFF)
set(Catalyst_DIR "" CACHE PATH "Catalyst cmake package directory or install prefix (catalyst_DIR and CATALYST_DIR also accepted)")
set(Catalyst_VERSION "" CACHE STRING "Catalyst version or git.<tag/branch/sha> (default 2.1.0)")
# "Build IPPL as a shared library (ON) or static library (OFF)" OFF) if(IPPL_DYL)
# set(BUILD_SHARED_LIBS ON CACHE BOOL "" FORCE) message(WARNING "IPPL_DYL is deprecated; use
# -DBUILD_SHARED_LIBS=ON instead.") endif()
Expand Down
130 changes: 110 additions & 20 deletions cmake/Dependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
# Dependencies.cmake
# ~~~
#
# Resolves third-party libraries: Kokkos and Heffte.
# Resolves third-party libraries: Kokkos, Heffte, and Catalyst.
#
# Responsibilities:
# - Fetch or find Kokkos, using version and backends from Platforms.cmake
# - Fetch Heffte if IPPL_ENABLE_FFT is ON, using CUDA or AVX2 based on platform
# - Fetch or find Catalyst when in-situ support or the FEL demo is enabled
#
# Not responsible for:
# - Selecting platform backends → Platforms.cmake
Expand Down Expand Up @@ -489,6 +490,114 @@ if(IPPL_ENABLE_FINUFFT)
add_compile_definitions(ENABLE_FINUFFT)
endif()

# ------------------------------------------------------------------------------
# Catalyst (libcatalyst SDK and bundled Conduit parser)
# ------------------------------------------------------------------------------
if(IPPL_ENABLE_CATALYST OR IPPL_ENABLE_FEL)
enable_language(C)

if(NOT Catalyst_VERSION)
set(Catalyst_VERSION 2.1.0)
endif()

extract_git_label(Catalyst_VERSION CATALYST_VERSION_GIT)

# Support Catalyst_DIR, catalyst_DIR, CATALYST_DIR (package dir or install prefix)
foreach(_cat_dir_var IN ITEMS Catalyst_DIR catalyst_DIR CATALYST_DIR)
if(DEFINED ${_cat_dir_var} AND ${_cat_dir_var})
if(EXISTS "${${_cat_dir_var}}/catalyst-config.cmake")
set(catalyst_DIR "${${_cat_dir_var}}")
else()
list(APPEND CMAKE_PREFIX_PATH "${${_cat_dir_var}}")
endif()
endif()
endforeach()
unset(_cat_dir_var)

# Do not mistake the package generated by an earlier FetchContent configure
# for a user-provided Catalyst installation on a subsequent configure.
set(_ippl_reuse_fetched_catalyst OFF)
set(_ippl_catalyst_dir_is_in_build_tree OFF)
if(catalyst_DIR)
cmake_path(IS_PREFIX CMAKE_BINARY_DIR "${catalyst_DIR}" NORMALIZE
_ippl_catalyst_dir_is_in_build_tree)
endif()
if(NOT Catalyst_DIR AND NOT CATALYST_DIR
AND (_ippl_catalyst_dir_is_in_build_tree
OR (IPPL_CATALYST_FETCHED AND NOT catalyst_DIR)))
set(_ippl_reuse_fetched_catalyst ON)
unset(catalyst_DIR CACHE)
unset(catalyst_FOUND)
endif()

if(NOT CATALYST_VERSION_GIT AND NOT _ippl_reuse_fetched_catalyst)
find_package(catalyst ${Catalyst_VERSION} CONFIG QUIET)
set(CATALYST_VERSION_GIT "v${Catalyst_VERSION}")
endif()

if(NOT CATALYST_VERSION_GIT)
set(CATALYST_VERSION_GIT "v${Catalyst_VERSION}")
endif()

if(catalyst_FOUND AND NOT _ippl_reuse_fetched_catalyst)
set(IPPL_CATALYST_FETCHED OFF CACHE INTERNAL "Catalyst was fetched by IPPL" FORCE)
set(IPPL_CATALYST_VERSION "${catalyst_VERSION}")
colour_message(STATUS ${Green} "✅ Catalyst ${catalyst_VERSION} found externally")
else()
set(IPPL_CATALYST_FETCHED ON CACHE INTERNAL "Catalyst was fetched by IPPL" FORCE)
colour_message(STATUS ${Green} "✅ Catalyst ${CATALYST_VERSION_GIT} building from source")

set(CATALYST_BUILD_SHARED_LIBS ON CACHE BOOL "" FORCE)
set(CATALYST_BUILD_STUB_IMPLEMENTATION ON CACHE BOOL "" FORCE)
set(CATALYST_BUILD_TESTING OFF CACHE BOOL "" FORCE)
set(CATALYST_BUILD_TOOLS OFF CACHE BOOL "" FORCE)
set(CATALYST_WRAP_PYTHON OFF CACHE BOOL "" FORCE)
set(CATALYST_WRAP_FORTRAN OFF CACHE BOOL "" FORCE)
set(CATALYST_WITH_EXTERNAL_CONDUIT OFF CACHE BOOL "" FORCE)
set(CATALYST_USE_MPI ON CACHE BOOL "" FORCE)

FetchContent_Declare(
catalyst
GIT_REPOSITORY "https://gitlab.kitware.com/paraview/catalyst.git"
GIT_TAG "${CATALYST_VERSION_GIT}"
DOWNLOAD_EXTRACT_TIMESTAMP ON)
FetchContent_MakeAvailable(catalyst)

if(NOT TARGET catalyst::catalyst)
message(FATAL_ERROR "Catalyst FetchContent did not provide catalyst::catalyst")
endif()

file(
STRINGS "${catalyst_SOURCE_DIR}/CMakeLists.txt" _catalyst_project_line
REGEX "^[ \t]*project\\(CATALYST VERSION [0-9]+\\.[0-9]+")
string(REGEX MATCH "VERSION[ \t]+([0-9]+\\.[0-9]+(\\.[0-9]+)?)"
_catalyst_version_match "${_catalyst_project_line}")
if(NOT CMAKE_MATCH_1)
message(FATAL_ERROR "Could not determine the fetched Catalyst project version")
endif()
set(IPPL_CATALYST_VERSION "${CMAKE_MATCH_1}")

unset(_catalyst_project_line)
unset(_catalyst_version_match)
endif()

string(REGEX MATCH "^([0-9]+)\\.([0-9]+)" _catalyst_major_minor
"${IPPL_CATALYST_VERSION}")
if(NOT _catalyst_major_minor)
message(FATAL_ERROR "Could not determine Catalyst's major/minor version")
endif()
set(IPPL_CATALYST_PACKAGE_DIRNAME "catalyst-${CMAKE_MATCH_1}.${CMAKE_MATCH_2}")
if(IPPL_CATALYST_FETCHED)
set(IPPL_CATALYST_BUILD_PACKAGE_DIR
"${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}/cmake/${IPPL_CATALYST_PACKAGE_DIRNAME}")
endif()

set(IPPL_CATALYST_USE_MPI "${CATALYST_USE_MPI}")
unset(_catalyst_major_minor)
unset(_ippl_catalyst_dir_is_in_build_tree)
unset(_ippl_reuse_fetched_catalyst)
endif()

# ------------------------------------------------------------------------------
# GoogleTest
# ------------------------------------------------------------------------------
Expand All @@ -510,22 +619,3 @@ if(IPPL_ENABLE_UNIT_TESTS)
message(STATUS "✅ GoogleTest built from source (${GTest_VERSION})")
endif()
endif()

# ------------------------------------------------------------------------------
# FEL module header-only dependencies (nlohmann/json for config parsing, stb_image_write for the
# Poynting-flux visualization).
# ------------------------------------------------------------------------------
if(IPPL_ENABLE_FEL)
# Fetch the CMake package instead of downloading the release header directly. CMake's
# file(DOWNLOAD) does not fail by default and can leave a zero-byte json.hpp behind when a
# release-asset host is unavailable, which only surfaces later as a confusing compile error.
set(JSON_BuildTests OFF CACHE BOOL "Disable nlohmann/json tests" FORCE)
FetchContent_Declare(
nlohmann_json
GIT_REPOSITORY https://github.com/nlohmann/json.git
GIT_TAG v3.11.3
GIT_SHALLOW ON)
FetchContent_MakeAvailable(nlohmann_json)

message(STATUS "✅ nlohmann/json loaded for the FEL module.")
endif()
39 changes: 39 additions & 0 deletions cmake/IPPLConfig.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,45 @@ if(@IPPL_ENABLE_FFT@ AND "@Heffte_FOUND@" AND NOT TARGET Heffte::Heffte)
find_dependency(Heffte CONFIG HINTS "${_ipplPrefix}" "@Heffte_DIR@")
endif()

if(@IPPL_ENABLE_CATALYST@)
if("@IPPL_CATALYST_USE_MPI@" AND NOT CMAKE_C_COMPILER_LOADED)
set(${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)
set(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE
"IPPL was built with MPI-enabled Catalyst, which requires the C language. Enable it in the consuming project with project(... LANGUAGES C CXX).")
return()
endif()

if(NOT TARGET catalyst::catalyst)
message(STATUS "Finding IPPL dependency: Catalyst")

if(_ipplBuildTree)
if("@IPPL_CATALYST_FETCHED@")
find_dependency(catalyst @IPPL_CATALYST_VERSION@ CONFIG
HINTS "@IPPL_CATALYST_BUILD_PACKAGE_DIR@")
else()
find_dependency(catalyst @IPPL_CATALYST_VERSION@ CONFIG HINTS "@catalyst_DIR@")
endif()
elseif("@IPPL_CATALYST_FETCHED@")
find_dependency(
catalyst @IPPL_CATALYST_VERSION@ CONFIG
HINTS
"${_ipplPrefix}/@CMAKE_INSTALL_LIBDIR@/cmake/@IPPL_CATALYST_PACKAGE_DIRNAME@")
else()
find_dependency(catalyst @IPPL_CATALYST_VERSION@ CONFIG
HINTS "${_ipplPrefix}" "@catalyst_DIR@")
endif()

message(STATUS "Catalyst version ${catalyst_VERSION}")
endif()
endif()

include("${CMAKE_CURRENT_LIST_DIR}/IPPLTargets.cmake")

if("@IPPL_ENABLE_CATALYST@" AND NOT _ipplBuildTree)
set_property(
TARGET IPPL::ippl APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS
"IPPL_CATALYST_SCRIPTS_DIR=\"${_ipplPrefix}/@CMAKE_INSTALL_DATADIR@/ippl/catalyst_scripts\"")
endif()

unset(_ipplPrefix)
unset(_ipplBuildTree)
1 change: 1 addition & 0 deletions cmake/InstallIppl.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ set(_ippl_install_excludes
PATTERN "*.cc" EXCLUDE
PATTERN "*.cpp" EXCLUDE
PATTERN "*.cu" EXCLUDE
PATTERN "catalyst_scripts" EXCLUDE
# match your filenames if needed
)

Expand Down
43 changes: 43 additions & 0 deletions cmake/SetupCatalyst.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# -----------------------------------------------------------------------------
# SetupCatalyst.cmake
#
# Links Catalyst into the ippl target. Resolution (find vs FetchContent) happens
# in Dependencies.cmake.
# -----------------------------------------------------------------------------

if(NOT TARGET ippl)
message(FATAL_ERROR "SetupCatalyst.cmake must be included after the ippl target is created.")
endif()

if(NOT TARGET catalyst::catalyst)
message(
FATAL_ERROR
"Catalyst enabled but catalyst::catalyst target is missing. "
"Set -DCatalyst_DIR=/path/to/catalyst/cmake or allow FetchContent.")
endif()

message(STATUS "Catalyst enabled")

target_compile_definitions(
ippl
PUBLIC IPPL_ENABLE_CATALYST
$<BUILD_INTERFACE:IPPL_CATALYST_SCRIPTS_DIR="${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_DATADIR}/ippl/catalyst_scripts">)

target_link_libraries(ippl PUBLIC catalyst::catalyst)

message(STATUS "Catalyst Summary:")
message(STATUS " External install: ${catalyst_FOUND}")
if(catalyst_VERSION)
message(STATUS " Version: ${catalyst_VERSION}")
elseif(Catalyst_VERSION)
message(STATUS " Version: ${Catalyst_VERSION}")
endif()
if(catalyst_DIR)
message(STATUS " CMake config dir: ${catalyst_DIR}")
elseif(Catalyst_PACKAGE_DIR)
message(STATUS " CMake config dir: ${Catalyst_PACKAGE_DIR}")
endif()

get_target_property(_cat_type catalyst::catalyst TYPE)
message(STATUS " Target: catalyst::catalyst (${_cat_type})")
unset(_cat_type)
5 changes: 4 additions & 1 deletion demos/alpine/ExamplesWithoutPicManager/ChargedParticles.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,10 +262,13 @@ class ChargedParticles : public ippl::ParticleBase<PLayout> {
}

void registerAttributes() {
P.set_name("velocity");
E.set_name("electric_field");
q.set_name("charge");
// register the particle attributes
this->addAttribute(q);
this->addAttribute(P);
this->addAttribute(E);
this->addAttribute(q);
}

~ChargedParticles() {}
Expand Down
2 changes: 1 addition & 1 deletion demos/alpine/ParticleContainer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ class ParticleContainer : public ippl::ParticleBase<
q.set_name("charge");
E.set_name("electric_field");
// register the particle attributes
this->addAttribute(q);
this->addAttribute(P);
this->addAttribute(E);
this->addAttribute(q);
}
void setupBCs() { setBCAllPeriodic(); }

Expand Down
4 changes: 4 additions & 0 deletions demos/alpine/PenningTrap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ int main(int argc, char* argv[]) {

manager.run(manager.getNt());

#ifdef IPPL_ENABLE_CATALYST
manager.cat_viz.Finalize();
#endif

msg << "End." << endl;

IpplTimings::stopTimer(mainTimer);
Expand Down
48 changes: 48 additions & 0 deletions demos/alpine/PenningTrapManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
#include "Random/NormalDistribution.h"
#include "Random/Randn.h"

#ifdef IPPL_ENABLE_CATALYST
#include "Stream/InSitu/CatalystAdaptor.h"
#endif

using view_type = typename ippl::detail::ViewType<ippl::Vector<double, Dim>, 1>::view_type;

template <typename T, unsigned Dim>
Expand Down Expand Up @@ -45,6 +49,13 @@ class PenningTrapManager : public AlpineManager<T, Dim> {
double alpha_m;
double DrInv_m;



#ifdef IPPL_ENABLE_CATALYST
public:
ippl::CatalystAdaptor cat_viz{std::string{TestName}};
#endif

public:
void pre_run() override {
Inform m("Pre Run");
Expand Down Expand Up @@ -124,6 +135,24 @@ class PenningTrapManager : public AlpineManager<T, Dim> {

this->grid2par();

#ifdef IPPL_ENABLE_CATALYST
m << "Catalyst is enabled" << endl;

std::shared_ptr<ippl::VisRegistryRuntime> runtime_steer_registry = ippl::MakeVisRegistryRuntimePtr();
std::shared_ptr<ippl::VisRegistryRuntime> runtime_vis_registry = ippl::MakeVisRegistryRuntimePtr(
"density", this->fcontainer_m->getRho(),
"ions", this->pcontainer_m
);
// runtime_vis_registry->add("potential", this->fcontainer_m->getRho() );
runtime_vis_registry->add("electrostatic", this->fcontainer_m->getE() );

static IpplTimings::TimerRef CAinit = IpplTimings::getTimer("CAinit");
IpplTimings::startTimer(CAinit);
cat_viz.Initialize(runtime_vis_registry, runtime_steer_registry);
IpplTimings::stopTimer(CAinit);

#endif

this->dump();

m << "Done";
Expand Down Expand Up @@ -239,6 +268,11 @@ class PenningTrapManager : public AlpineManager<T, Dim> {
static IpplTimings::TimerRef domainDecomposition = IpplTimings::getTimer("loadBalance");
static IpplTimings::TimerRef SolveTimer = IpplTimings::getTimer("solve");

#ifdef IPPL_ENABLE_CATALYST
static IpplTimings::TimerRef TMR_CAremember = IpplTimings::getTimer("CAremember");
static IpplTimings::TimerRef TMR_CAexecute = IpplTimings::getTimer("CAexecute");
#endif

double alpha = this->alpha_m;
double Bext = this->Bext_m;
double DrInv = this->DrInv_m;
Expand Down Expand Up @@ -298,6 +332,13 @@ class PenningTrapManager : public AlpineManager<T, Dim> {
// scatter the charge onto the underlying grid
this->par2grid();

// Save deep copy of the density field (for later).
#ifdef IPPL_ENABLE_CATALYST
IpplTimings::startTimer(TMR_CAremember);
cat_viz.rememberNow("density");
IpplTimings::stopTimer(TMR_CAremember);
#endif

// Field solve
IpplTimings::startTimer(SolveTimer);
this->fsolver_m->runSolver();
Expand All @@ -306,6 +347,13 @@ class PenningTrapManager : public AlpineManager<T, Dim> {
// gather E field
this->grid2par();

//trigger In Situ pipeline
#ifdef IPPL_ENABLE_CATALYST
IpplTimings::startTimer(TMR_CAexecute);
cat_viz.Execute(it, this->time_m);
IpplTimings::stopTimer(TMR_CAexecute);
#endif

IpplTimings::startTimer(PTimer);
auto R2view = pc->R.getView();
auto P2view = pc->P.getView();
Expand Down
Loading
Loading