2High-level BoundaryLayerConductanceModel interface for PyHelios.
4This module provides a user-friendly interface to the boundary layer conductance modeling
5capabilities with graceful plugin handling and informative error messages.
9from typing
import List, Optional
11from .plugins.registry
import get_plugin_registry
12from .wrappers
import UBoundaryLayerConductanceWrapper
as bl_wrapper
13from .Context
import Context, check_context_alive
14from .exceptions
import HeliosError
16logger = logging.getLogger(__name__)
20 """Exception raised for BoundaryLayerConductanceModel-specific errors."""
26 High-level interface for boundary layer conductance modeling and heat/mass transfer calculations.
28 This class provides a user-friendly wrapper around the native Helios
29 boundary layer conductance plugin with automatic plugin availability checking and
30 graceful error handling.
32 The boundary layer conductance model implements four different boundary-layer models:
33 - Pohlhausen: Laminar flat plate, forced convection (default)
34 - InclinedPlate: Mixed free-forced convection for inclined plates
35 - Sphere: Laminar flow around a sphere
36 - Ground: Flow over bare ground surface
39 - Cross-platform support (Windows, Linux, macOS)
41 - No special dependencies
42 - Boundary layer conductance plugin compiled into PyHelios
45 >>> from pyhelios import Context, BoundaryLayerConductanceModel
47 >>> with Context() as context:
48 ... # Add leaf geometry
49 ... leaf_uuid = context.addPatch(center=[0, 0, 1], size=[0.1, 0.1])
51 ... with BoundaryLayerConductanceModel(context) as bl_model:
52 ... # Set model for all primitives (default is Pohlhausen)
53 ... bl_model.setBoundaryLayerModel("InclinedPlate")
58 ... # Or set different models for different primitives
59 ... bl_model.setBoundaryLayerModel("Sphere", uuids=[leaf_uuid])
60 ... bl_model.run(uuids=[leaf_uuid])
63 def __init__(self, context: Context):
65 Initialize BoundaryLayerConductanceModel with graceful plugin handling.
68 context: Helios Context instance
71 TypeError: If context is not a Context instance
72 BoundaryLayerConductanceModelError: If boundary layer conductance plugin is not available
75 if not (hasattr(context,
'__class__')
and
76 (isinstance(context, Context)
or
77 context.__class__.__name__ ==
'Context')):
78 raise TypeError(f
"BoundaryLayerConductanceModel requires a Context instance, got {type(context).__name__}")
84 registry = get_plugin_registry()
86 if not registry.is_plugin_available(
'boundarylayerconductance'):
88 available_plugins = registry.get_available_plugins()
91 "BoundaryLayerConductanceModel requires the 'boundarylayerconductance' plugin which is not available.\n\n"
92 "The boundary layer conductance plugin provides heat and mass transfer calculations using four validated models:\n"
93 "- Pohlhausen: Laminar flat plate, forced convection\n"
94 "- InclinedPlate: Mixed free-forced convection for inclined surfaces\n"
95 "- Sphere: Laminar flow around spherical objects\n"
96 "- Ground: Convective transfer over bare ground\n\n"
98 "- Cross-platform support (Windows, Linux, macOS)\n"
99 "- No GPU or special dependencies required\n"
100 "- Applicable to plant leaves, fruits, and soil surfaces\n\n"
101 "To enable boundary layer conductance modeling:\n"
102 "1. Build PyHelios with boundary layer conductance plugin:\n"
103 " build_scripts/build_helios --plugins boundarylayerconductance\n"
104 "2. Or build with multiple physics plugins:\n"
105 " build_scripts/build_helios --plugins boundarylayerconductance,energybalance,stomatalconductance\n"
106 f
"\nCurrently available plugins: {available_plugins}"
110 alternatives = registry.suggest_alternatives(
'boundarylayerconductance')
112 error_msg += f
"\n\nAlternative plugins available: {alternatives}"
113 error_msg +=
"\nConsider using energybalance or stomatalconductance for related plant physiology modeling."
119 self.
bl_model = bl_wrapper.createBoundaryLayerConductanceModel(context.getNativePtr())
122 "Failed to create BoundaryLayerConductanceModel instance. "
123 "This may indicate a problem with the native library."
125 logger.info(
"BoundaryLayerConductanceModel created successfully")
127 except Exception
as e:
131 """Raise if the owning Context has been destroyed (see Context.check_context_alive)."""
132 check_context_alive(getattr(self,
"context",
None),
"BoundaryLayerConductanceModel")
135 """Context manager entry."""
138 def __exit__(self, exc_type, exc_value, traceback):
139 """Context manager exit with proper cleanup."""
142 bl_wrapper.destroyBoundaryLayerConductanceModel(self.
bl_model)
143 logger.debug(
"BoundaryLayerConductanceModel destroyed successfully")
144 except Exception
as e:
145 logger.warning(f
"Error destroying BoundaryLayerConductanceModel: {e}")
150 """Destructor to ensure C++ resources freed even without 'with' statement."""
151 if hasattr(self,
'bl_model')
and self.
bl_model is not None:
153 bl_wrapper.destroyBoundaryLayerConductanceModel(self.
bl_model)
155 except Exception
as e:
157 warnings.warn(f
"Error in BoundaryLayerConductanceModel.__del__: {e}")
160 """Get the native pointer for advanced operations."""
165 Enable console output messages from the boundary layer conductance model.
168 BoundaryLayerConductanceModelError: If operation fails
172 bl_wrapper.enableMessages(self.
bl_model)
173 except Exception
as e:
178 Disable console output messages from the boundary layer conductance model.
181 BoundaryLayerConductanceModelError: If operation fails
185 bl_wrapper.disableMessages(self.
bl_model)
186 except Exception
as e:
191 Set the boundary layer conductance model to be used.
193 Four models are available:
194 - "Pohlhausen": Laminar flat plate, forced convection (default)
195 - "InclinedPlate": Mixed free-forced convection for inclined plates
196 - "Sphere": Laminar flow around a sphere
197 - "Ground": Flow over bare ground surface
200 model_name: Name of the boundary layer model to use.
201 Must be one of: "Pohlhausen", "InclinedPlate", "Sphere", "Ground"
202 uuids: Optional list of primitive UUIDs to apply the model to.
203 If None, applies to all primitives in the Context.
206 ValueError: If model_name is not valid
207 BoundaryLayerConductanceModelError: If operation fails
210 >>> # Set Pohlhausen model for all primitives
211 >>> bl_model.setBoundaryLayerModel("Pohlhausen")
213 >>> # Set InclinedPlate model for specific leaves
214 >>> bl_model.setBoundaryLayerModel("InclinedPlate", uuids=[uuid1, uuid2])
216 >>> # Set Sphere model for fruit geometry
217 >>> bl_model.setBoundaryLayerModel("Sphere", uuids=[fruit_uuid])
219 >>> # Set Ground model for soil patches
220 >>> bl_model.setBoundaryLayerModel("Ground", uuids=[ground_uuids])
223 valid_models = [
"Pohlhausen",
"InclinedPlate",
"Sphere",
"Ground"]
224 if model_name
not in valid_models:
226 f
"Invalid boundary layer model '{model_name}'. "
227 f
"Must be one of: {', '.join(valid_models)}"
234 bl_wrapper.setBoundaryLayerModel(self.
bl_model, model_name)
235 elif len(uuids) == 1:
237 bl_wrapper.setBoundaryLayerModelForUUID(self.
bl_model, uuids[0], model_name)
240 bl_wrapper.setBoundaryLayerModelForUUIDs(self.
bl_model, uuids, model_name)
242 except Exception
as e:
245 def run(self, uuids: Optional[List[int]] =
None) ->
None:
247 Run the boundary layer conductance calculations.
249 Calculates boundary-layer conductance values and stores results as
250 primitive data "boundarylayer_conductance" (mol air/m²/s).
253 uuids: Optional list of primitive UUIDs to process.
254 If None, processes all primitives in the Context.
257 BoundaryLayerConductanceModelError: If calculation fails
260 >>> # Calculate for all primitives
263 >>> # Calculate for specific primitives
264 >>> bl_model.run(uuids=[leaf1_uuid, leaf2_uuid])
270 bl_wrapper.runBoundaryLayerModel(self.
bl_model)
273 bl_wrapper.runBoundaryLayerModelForUUIDs(self.
bl_model, uuids)
275 except Exception
as e:
281 Check if BoundaryLayerConductanceModel plugin is available in current build.
284 True if plugin is available, False otherwise
287 >>> if BoundaryLayerConductanceModel.is_available():
288 ... print("Boundary layer conductance modeling is available!")
290 registry = get_plugin_registry()
291 return registry.is_plugin_available(
'boundarylayerconductance')
Exception raised for BoundaryLayerConductanceModel-specific errors.
High-level interface for boundary layer conductance modeling and heat/mass transfer calculations.
__del__(self)
Destructor to ensure C++ resources freed even without 'with' statement.
__exit__(self, exc_type, exc_value, traceback)
Context manager exit with proper cleanup.
getNativePtr(self)
Get the native pointer for advanced operations.
None disableMessages(self)
Disable console output messages from the boundary layer conductance model.
None run(self, Optional[List[int]] uuids=None)
Run the boundary layer conductance calculations.
bool is_available()
Check if BoundaryLayerConductanceModel plugin is available in current build.
None setBoundaryLayerModel(self, str model_name, Optional[List[int]] uuids=None)
Set the boundary layer conductance model to be used.
_check_context_alive(self)
Raise if the owning Context has been destroyed (see Context.check_context_alive).
__init__(self, Context context)
Initialize BoundaryLayerConductanceModel with graceful plugin handling.
None enableMessages(self)
Enable console output messages from the boundary layer conductance model.
__enter__(self)
Context manager entry.
Exception classes for PyHelios library.