Skip to content

Commit 21d7f62

Browse files
committed
[1.3.61] 2025-12-17
## Core - Fixed CMake linkage visibility for `stdc++fs` library on older GNU compilers (< 9.0) by specifying `PRIVATE` visibility. - Added `compact` parameter to `WarningAggregator::report()` for single-line warning summaries. ## Energy Balance - CUDA is now optional. Plugin uses three-tier execution: GPU (CUDA), OpenMP (parallel CPU), or serial CPU fallback. OpenMP is recommended for most workloads. - Added `enableGPUAcceleration()`, `disableGPUAcceleration()`, and `isGPUAccelerationEnabled()` methods to control GPU usage at runtime (only available when compiled with CUDA). ## Collision Detection - Added runtime warning when OpenMP is not available, recommending its installation for better performance. ## Plant Architecture - Added nitrogen model for simulating nitrogen uptake, allocation, remobilization, and stress effects on plant growth. Uses area-based nitrogen tracking (g N/m²) with three-level pool structure (root → available → per-leaf). Calculates nitrogen stress factor (0-1) for use by other plugins. ## Leaf Optics - Added nitrogen-based automatic leaf optics mode that computes chlorophyll and carotenoid content from leaf nitrogen concentration. Uses adaptive binning to limit computational overhead while maintaining spectral fidelity across nitrogen gradients. Integrates with PlantArchitecture nitrogen model via `leaf_nitrogen_gN_m2` object data.
1 parent d0bb362 commit 21d7f62

28 files changed

Lines changed: 4124 additions & 202 deletions

core/CMake_project.cmake

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ endif()
154154
add_subdirectory( "${BASE_DIRECTORY}/core" "lib" )
155155
target_link_libraries( ${EXECUTABLE_NAME} PUBLIC helios)
156156
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9)
157-
target_link_libraries(${EXECUTABLE_NAME} stdc++fs)
157+
target_link_libraries(${EXECUTABLE_NAME} PRIVATE stdc++fs)
158158
endif()
159159
if(APPLE) #get rid of annoying duplicate library warning on Mac
160160
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-no_warn_duplicate_libraries")
@@ -173,7 +173,7 @@ foreach(PLUGIN ${PLUGINS})
173173
target_link_libraries( ${PLUGIN} PUBLIC helios )
174174
if( NOT APPLE )
175175
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9)
176-
target_link_libraries(${PLUGIN} stdc++fs)
176+
target_link_libraries(${PLUGIN} PRIVATE stdc++fs)
177177
endif()
178178
endif()
179179
endforeach(PLUGIN)

core/include/global.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,9 +1537,11 @@ namespace helios {
15371537
//! Report all accumulated warnings and clear
15381538
/**
15391539
* \param[in] stream Output stream to write warnings to (default: std::cerr)
1540-
* \note Outputs format: "WARNING: N instances of 'category' (showing first 3):"
1540+
* \param[in] compact If true, output single line per category with count only (default: false)
1541+
* \note Standard format: "WARNING: N instances of 'category' (showing first 3):"
1542+
* \note Compact format: "WARNING: N instances of 'category'"
15411543
*/
1542-
void report(std::ostream &stream = std::cerr);
1544+
void report(std::ostream &stream = std::cerr, bool compact = false);
15431545

15441546
//! Get the count of warnings for a specific category
15451547
/**

core/src/global.cpp

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2995,7 +2995,7 @@ void helios::WarningAggregator::addWarning(const std::string &category, const st
29952995
}
29962996
}
29972997

2998-
void helios::WarningAggregator::report(std::ostream &stream) {
2998+
void helios::WarningAggregator::report(std::ostream &stream, bool compact) {
29992999
std::lock_guard<std::mutex> lock(mutex_);
30003000

30013001
if (counts_.empty()) {
@@ -3009,21 +3009,26 @@ void helios::WarningAggregator::report(std::ostream &stream) {
30093009

30103010
stream << "WARNING: " << count << " instance" << (count > 1 ? "s" : "") << " of '" << category << "'";
30113011

3012-
// Get stored messages for this category
3013-
const auto &messages = warnings_[category];
3012+
if (!compact) {
3013+
// Original behavior: show examples
3014+
const auto &messages = warnings_[category];
30143015

3015-
// Show first few examples
3016-
size_t examples_to_show = std::min(size_t(3), messages.size());
3017-
stream << " (showing first " << examples_to_show << "):" << std::endl;
3016+
// Show first few examples
3017+
size_t examples_to_show = std::min(size_t(3), messages.size());
3018+
stream << " (showing first " << examples_to_show << "):" << std::endl;
30183019

3019-
for (size_t i = 0; i < examples_to_show; ++i) {
3020-
stream << " - " << messages[i] << std::endl;
3021-
}
3020+
for (size_t i = 0; i < examples_to_show; ++i) {
3021+
stream << " - " << messages[i] << std::endl;
3022+
}
30223023

3023-
if (count > MAX_EXAMPLES) {
3024-
stream << " (Note: More than " << MAX_EXAMPLES << " warnings of this type were encountered)" << std::endl;
3024+
if (count > MAX_EXAMPLES) {
3025+
stream << " (Note: More than " << MAX_EXAMPLES << " warnings of this type were encountered)" << std::endl;
3026+
}
3027+
stream << std::endl;
3028+
} else {
3029+
// Compact mode: just the count
3030+
stream << std::endl;
30253031
}
3026-
stream << std::endl;
30273032
}
30283033

30293034
// Clear after reporting

doc/CHANGELOG.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
# Changelog
22

3+
# [1.3.61] 2025-12-17
4+
5+
## Core
6+
- Fixed CMake linkage visibility for `stdc++fs` library on older GNU compilers (< 9.0) by specifying `PRIVATE` visibility.
7+
- Added `compact` parameter to `WarningAggregator::report()` for single-line warning summaries.
8+
9+
## Energy Balance
10+
- CUDA is now optional. Plugin uses three-tier execution: GPU (CUDA), OpenMP (parallel CPU), or serial CPU fallback. OpenMP is recommended for most workloads.
11+
- Added `enableGPUAcceleration()`, `disableGPUAcceleration()`, and `isGPUAccelerationEnabled()` methods to control GPU usage at runtime (only available when compiled with CUDA).
12+
13+
## Collision Detection
14+
- Added runtime warning when OpenMP is not available, recommending its installation for better performance.
15+
16+
## Plant Architecture
17+
- Added nitrogen model for simulating nitrogen uptake, allocation, remobilization, and stress effects on plant growth. Uses area-based nitrogen tracking (g N/m²) with three-level pool structure (root → available → per-leaf). Calculates nitrogen stress factor (0-1) for use by other plugins.
18+
19+
## Leaf Optics
20+
- Added nitrogen-based automatic leaf optics mode that computes chlorophyll and carotenoid content from leaf nitrogen concentration. Uses adaptive binning to limit computational overhead while maintaining spectral fidelity across nitrogen gradients. Integrates with PlantArchitecture nitrogen model via `leaf_nitrogen_gN_m2` object data.
21+
322
# [1.3.60] 2025-12-08
423

524
## Core

doc/header.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
$treeview
4848
$search
4949
$mathjax
50-
$darkmode
5150
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
5251
$extrastylesheet
5352
</head>

plugins/collisiondetection/doc/CollisionDetection.dox

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,19 @@
55
<p> <br><br> </p>
66

77
<table>
8-
<tr>
8+
<tr>
99
<th>Dependencies</th>
10-
<td>NVIDIA CUDA 9.0+ (optional)</td>
10+
<td>OpenMP (recommended), NVIDIA CUDA 9.0+ (optional)</td>
1111
</tr>
12-
<tr>
12+
<tr>
1313
<th>CMakeLists.txt</th>
1414
<td>set( PLUGINS "collisiondetection" )</td>
1515
</tr>
16-
<tr>
16+
<tr>
1717
<th>Header File</th>
1818
<td>#include "CollisionDetection.h"</td>
1919
</tr>
20-
<tr>
20+
<tr>
2121
<th>Class</th>
2222
<td>\ref CollisionDetection</td>
2323
</tr>
@@ -28,25 +28,36 @@
2828
<table>
2929
<tr>
3030
<th>Package</th>
31+
<th>Status</th>
3132
<td>\image html apple-logo.png</td>
3233
<td>\image html unix-logo.png</td>
3334
<td>\image html windows-logo.png</td>
3435
</tr>
36+
<tr>
37+
<td>OpenMP</td>
38+
<td><b>Recommended</b></td>
39+
<td>Usually available (via libomp)</td>
40+
<td>Usually available</td>
41+
<td>Usually available</td>
42+
</tr>
3543
<tr>
3644
<td>NVIDIA CUDA 9.0+ (optional)</td>
45+
<td><b>Optional</b></td>
3746
<td>Mac OSX: Not available</td>
3847
<td>Use <a href="https://developer.nvidia.com/cuda-downloads">CUDA installer</a></td>
3948
<td>Use <a href="https://developer.nvidia.com/cuda-downloads">CUDA installer</a></td>
4049
</tr>
4150
</table>
4251

52+
<b>Performance Note:</b> OpenMP is strongly recommended for production use. The plugin will work without OpenMP using serial CPU execution, but performance will be significantly slower for large scenes.
53+
4354
For help choosing the correct CUDA toolkit version and accompanying OptiX version for your system, consult this page: \ref ChoosingCUDA
4455

4556
Useful OS-specific information for installing CUDA can be found here: \ref DependentSoftware
4657

4758
If you are using a PC, it is likely you will need to increase the GPU timeout in the registry, otherwise calculations lasting longer than 2 secs. will timeout and kill your program. A guide on how to increase the timeout can be found here: \ref PCGPUTimeout
4859

49-
<b>Note:</b> CUDA is optional for this plugin. The collision detection system will work on CPU-only systems, but GPU acceleration provides significant performance improvements for large scenes.
60+
<b>Note:</b> CUDA is optional for this plugin. The collision detection system will work on CPU-only systems. OpenMP provides parallel CPU execution and is recommended for best performance. When neither GPU nor OpenMP is available, the plugin falls back to serial CPU execution with a performance warning.
5061

5162
\section CDIntro Introduction
5263

plugins/collisiondetection/src/CollisionDetection.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,16 @@ CollisionDetection::CollisionDetection(helios::Context *a_context) {
9898
tree_isolation_distance = 5.0f; // Default 5 meter isolation distance
9999
obstacle_spatial_grid_initialized = false;
100100

101+
// Issue warning if OpenMP not available
102+
#ifndef _OPENMP
103+
static bool openmp_warning_issued = false;
104+
if (printmessages && !openmp_warning_issued) {
105+
std::cout << "WARNING (CollisionDetection): OpenMP not available. Using serial CPU implementation. "
106+
<< "Performance will be significantly slower. Consider installing OpenMP for parallel execution." << std::endl;
107+
openmp_warning_issued = true;
108+
}
109+
#endif
110+
101111
// Initialize grid parameters
102112
grid_center = make_vec3(0, 0, 0);
103113
grid_size = make_vec3(1, 1, 1);

plugins/energybalance/CMakeLists.txt

Lines changed: 75 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -7,73 +7,90 @@ endif()
77

88
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/")
99

10-
find_package(CUDAToolkit REQUIRED)
11-
set(CMAKE_CUDA_COMPILER ${CUDAToolkit_NVCC_EXECUTABLE})
10+
# Try to find CUDA toolkit (optional)
11+
find_package(CUDAToolkit QUIET)
1212

13-
# Set CUDA architectures before enabling CUDA language
14-
if( OPTIX_VERSION_LEGACY )
15-
set(CMAKE_CUDA_ARCHITECTURES "35")
16-
else()
17-
include("${CMAKE_BINARY_DIR}/lib/detect_GPU_compute.cmake")
18-
endif()
13+
if(CUDAToolkit_FOUND)
14+
message(STATUS "[EnergyBalance] CUDA found - building with GPU acceleration")
15+
set(CMAKE_CUDA_COMPILER ${CUDAToolkit_NVCC_EXECUTABLE})
1916

20-
# Enable CUDA as a language (modern CMake approach)
21-
enable_language(CUDA)
22-
23-
# Windows-specific: Override CMake's automatic CUDA flag injection
24-
if(WIN32 AND MSVC)
25-
# Clear all CMake-generated CUDA flags that contain problematic MSVC options
26-
set(CMAKE_CUDA_FLAGS_DEBUG "")
27-
set(CMAKE_CUDA_FLAGS_RELEASE "")
28-
set(CMAKE_CUDA_FLAGS_RELWITHDEBINFO "")
29-
set(CMAKE_CUDA_FLAGS_MINSIZEREL "")
30-
31-
# Override the CUDA compile rule to prevent MSVC flag injection
32-
set(CMAKE_CUDA_COMPILE_OBJECT "<CMAKE_CUDA_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -c <SOURCE> -o <OBJECT>")
33-
endif()
17+
# Set CUDA architectures before enabling CUDA language
18+
if( OPTIX_VERSION_LEGACY )
19+
set(CMAKE_CUDA_ARCHITECTURES "35")
20+
else()
21+
include("${CMAKE_BINARY_DIR}/lib/detect_GPU_compute.cmake")
22+
endif()
3423

35-
# Set CUDA flags after enabling language to override defaults
36-
if(WIN32)
37-
# On Windows, use minimal flags and override any CMake defaults
38-
set(CMAKE_CUDA_FLAGS "--use_fast_math")
39-
40-
# Force override CMake's build-type specific flags after they're set
41-
set(CMAKE_CUDA_FLAGS_DEBUG "${CMAKE_CUDA_FLAGS}")
42-
set(CMAKE_CUDA_FLAGS_RELEASE "${CMAKE_CUDA_FLAGS}")
43-
set(CMAKE_CUDA_FLAGS_RELWITHDEBINFO "${CMAKE_CUDA_FLAGS}")
44-
set(CMAKE_CUDA_FLAGS_MINSIZEREL "${CMAKE_CUDA_FLAGS}")
45-
else()
46-
# Non-Windows platforms use full flags
47-
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --use_fast_math -Wno-deprecated-gpu-targets")
48-
49-
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -std=c++${CMAKE_CXX_STANDARD}")
50-
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -D_MWAITXINTRIN_H_INCLUDED -D__STRICT_ANSI__")
51-
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -I${CMAKE_CURRENT_SOURCE_DIR}/include")
52-
endif()
24+
# Enable CUDA as a language (modern CMake approach)
25+
enable_language(CUDA)
5326

54-
if( CMAKE_BUILD_TYPE STREQUAL Debug OR NOT DEFINED CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "" )
55-
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -g -O0")
56-
else()
57-
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -O3")
58-
endif()
27+
# Windows-specific: Override CMake's automatic CUDA flag injection
28+
if(WIN32 AND MSVC)
29+
# Clear all CMake-generated CUDA flags that contain problematic MSVC options
30+
set(CMAKE_CUDA_FLAGS_DEBUG "")
31+
set(CMAKE_CUDA_FLAGS_RELEASE "")
32+
set(CMAKE_CUDA_FLAGS_RELWITHDEBINFO "")
33+
set(CMAKE_CUDA_FLAGS_MINSIZEREL "")
5934

60-
add_library(energybalance STATIC "src/EnergyBalanceModel.cpp" "src/EnergyBalanceModel.cu" "tests/selfTest.cpp")
35+
# Override the CUDA compile rule to prevent MSVC flag injection
36+
set(CMAKE_CUDA_COMPILE_OBJECT "<CMAKE_CUDA_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -c <SOURCE> -o <OBJECT>")
37+
endif()
6138

62-
# Set CUDA properties for the target
63-
set_target_properties(energybalance PROPERTIES CUDA_RUNTIME_LIBRARY Static CUDA_RESOLVE_DEVICE_SYMBOLS ON )
39+
# Set CUDA flags after enabling language to override defaults
40+
if(WIN32)
41+
# On Windows, use minimal flags and override any CMake defaults
42+
set(CMAKE_CUDA_FLAGS "--use_fast_math")
6443

65-
# Windows-specific: Clear any inherited global compile options that cause nvcc issues
66-
if(WIN32 AND MSVC)
67-
# Remove the global /utf-8 flag and other MSVC options from CUDA compilation
68-
set_property(TARGET energybalance PROPERTY COMPILE_OPTIONS "")
69-
set_property(TARGET energybalance PROPERTY COMPILE_DEFINITIONS "")
70-
71-
# Windows-specific defines
72-
target_compile_definitions(energybalance PRIVATE NOMINMAX _USE_MATH_DEFINES _MWAITXINTRIN_H_INCLUDED __STRICT_ANSI__ )
73-
endif()
44+
# Force override CMake's build-type specific flags after they're set
45+
set(CMAKE_CUDA_FLAGS_DEBUG "${CMAKE_CUDA_FLAGS}")
46+
set(CMAKE_CUDA_FLAGS_RELEASE "${CMAKE_CUDA_FLAGS}")
47+
set(CMAKE_CUDA_FLAGS_RELWITHDEBINFO "${CMAKE_CUDA_FLAGS}")
48+
set(CMAKE_CUDA_FLAGS_MINSIZEREL "${CMAKE_CUDA_FLAGS}")
49+
else()
50+
# Non-Windows platforms use full flags
51+
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --use_fast_math -Wno-deprecated-gpu-targets")
52+
53+
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -std=c++${CMAKE_CXX_STANDARD}")
54+
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -D_MWAITXINTRIN_H_INCLUDED -D__STRICT_ANSI__")
55+
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -I${CMAKE_CURRENT_SOURCE_DIR}/include")
56+
endif()
57+
58+
if( CMAKE_BUILD_TYPE STREQUAL Debug OR NOT DEFINED CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "" )
59+
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -g -O0")
60+
else()
61+
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -O3")
62+
endif()
7463

75-
target_link_libraries(energybalance PUBLIC CUDA::cudart_static)
64+
# Build with CUDA support (.cu file included)
65+
add_library(energybalance STATIC "src/EnergyBalanceModel.cpp" "src/EnergyBalanceModel.cu" "tests/selfTest.cpp")
66+
67+
# Set CUDA properties for the target
68+
set_target_properties(energybalance PROPERTIES CUDA_RUNTIME_LIBRARY Static CUDA_RESOLVE_DEVICE_SYMBOLS ON )
69+
70+
# Windows-specific: Clear any inherited global compile options that cause nvcc issues
71+
if(WIN32 AND MSVC)
72+
# Remove the global /utf-8 flag and other MSVC options from CUDA compilation
73+
set_property(TARGET energybalance PROPERTY COMPILE_OPTIONS "")
74+
set_property(TARGET energybalance PROPERTY COMPILE_DEFINITIONS "")
75+
76+
# Windows-specific defines
77+
target_compile_definitions(energybalance PRIVATE NOMINMAX _USE_MATH_DEFINES _MWAITXINTRIN_H_INCLUDED __STRICT_ANSI__ )
78+
endif()
79+
80+
target_link_libraries(energybalance PUBLIC CUDA::cudart_static)
81+
82+
# Define preprocessor macro to indicate CUDA support
83+
target_compile_definitions(energybalance PRIVATE HELIOS_CUDA_AVAILABLE)
84+
85+
else()
86+
message(STATUS "[EnergyBalance] CUDA not found - building CPU-only version with OpenMP")
87+
88+
# Build CPU-only version (exclude .cu file)
89+
add_library(energybalance STATIC "src/EnergyBalanceModel.cpp" "tests/selfTest.cpp")
90+
91+
endif()
7692

93+
# Common configurations for both CUDA and CPU-only builds
7794
target_include_directories(energybalance PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
7895

7996
if(BUILD_TESTS)

0 commit comments

Comments
 (0)