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
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 """Context manager entry."""
134 def __exit__(self, exc_type, exc_value, traceback):
135 """Context manager exit with proper cleanup."""
138 bl_wrapper.destroyBoundaryLayerConductanceModel(self.
bl_model)
139 logger.debug(
"BoundaryLayerConductanceModel destroyed successfully")
140 except Exception
as e:
141 logger.warning(f
"Error destroying BoundaryLayerConductanceModel: {e}")
146 """Destructor to ensure C++ resources freed even without 'with' statement."""
147 if hasattr(self,
'bl_model')
and self.
bl_model is not None:
149 bl_wrapper.destroyBoundaryLayerConductanceModel(self.
bl_model)
151 except Exception
as e:
153 warnings.warn(f
"Error in BoundaryLayerConductanceModel.__del__: {e}")
156 """Get the native pointer for advanced operations."""
161 Enable console output messages from the boundary layer conductance model.
164 BoundaryLayerConductanceModelError: If operation fails
167 bl_wrapper.enableMessages(self.
bl_model)
168 except Exception
as e:
173 Disable console output messages from the boundary layer conductance model.
176 BoundaryLayerConductanceModelError: If operation fails
179 bl_wrapper.disableMessages(self.
bl_model)
180 except Exception
as e:
185 Set the boundary layer conductance model to be used.
187 Four models are available:
188 - "Pohlhausen": Laminar flat plate, forced convection (default)
189 - "InclinedPlate": Mixed free-forced convection for inclined plates
190 - "Sphere": Laminar flow around a sphere
191 - "Ground": Flow over bare ground surface
194 model_name: Name of the boundary layer model to use.
195 Must be one of: "Pohlhausen", "InclinedPlate", "Sphere", "Ground"
196 uuids: Optional list of primitive UUIDs to apply the model to.
197 If None, applies to all primitives in the Context.
200 ValueError: If model_name is not valid
201 BoundaryLayerConductanceModelError: If operation fails
204 >>> # Set Pohlhausen model for all primitives
205 >>> bl_model.setBoundaryLayerModel("Pohlhausen")
207 >>> # Set InclinedPlate model for specific leaves
208 >>> bl_model.setBoundaryLayerModel("InclinedPlate", uuids=[uuid1, uuid2])
210 >>> # Set Sphere model for fruit geometry
211 >>> bl_model.setBoundaryLayerModel("Sphere", uuids=[fruit_uuid])
213 >>> # Set Ground model for soil patches
214 >>> bl_model.setBoundaryLayerModel("Ground", uuids=[ground_uuids])
217 valid_models = [
"Pohlhausen",
"InclinedPlate",
"Sphere",
"Ground"]
218 if model_name
not in valid_models:
220 f
"Invalid boundary layer model '{model_name}'. "
221 f
"Must be one of: {', '.join(valid_models)}"
227 bl_wrapper.setBoundaryLayerModel(self.
bl_model, model_name)
228 elif len(uuids) == 1:
230 bl_wrapper.setBoundaryLayerModelForUUID(self.
bl_model, uuids[0], model_name)
233 bl_wrapper.setBoundaryLayerModelForUUIDs(self.
bl_model, uuids, model_name)
235 except Exception
as e:
238 def run(self, uuids: Optional[List[int]] =
None) ->
None:
240 Run the boundary layer conductance calculations.
242 Calculates boundary-layer conductance values and stores results as
243 primitive data "boundarylayer_conductance" (mol air/m²/s).
246 uuids: Optional list of primitive UUIDs to process.
247 If None, processes all primitives in the Context.
250 BoundaryLayerConductanceModelError: If calculation fails
253 >>> # Calculate for all primitives
256 >>> # Calculate for specific primitives
257 >>> bl_model.run(uuids=[leaf1_uuid, leaf2_uuid])
262 bl_wrapper.runBoundaryLayerModel(self.
bl_model)
265 bl_wrapper.runBoundaryLayerModelForUUIDs(self.
bl_model, uuids)
267 except Exception
as e:
273 Check if BoundaryLayerConductanceModel plugin is available in current build.
276 True if plugin is available, False otherwise
279 >>> if BoundaryLayerConductanceModel.is_available():
280 ... print("Boundary layer conductance modeling is available!")
282 registry = get_plugin_registry()
283 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.
__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.