luminarycloud 0.22.1__py3-none-any.whl → 0.22.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- luminarycloud/_client/client.py +5 -3
- luminarycloud/_client/retry_interceptor.py +13 -2
- luminarycloud/_helpers/__init__.py +9 -0
- luminarycloud/_helpers/_inference_jobs.py +227 -0
- luminarycloud/_helpers/_parse_iso_datetime.py +54 -0
- luminarycloud/_helpers/proto_decorator.py +38 -7
- luminarycloud/_proto/api/v0/luminarycloud/geometry/geometry_pb2.py +45 -25
- luminarycloud/_proto/api/v0/luminarycloud/geometry/geometry_pb2.pyi +30 -0
- luminarycloud/_proto/api/v0/luminarycloud/geometry/geometry_pb2_grpc.py +34 -0
- luminarycloud/_proto/api/v0/luminarycloud/geometry/geometry_pb2_grpc.pyi +12 -0
- luminarycloud/_proto/api/v0/luminarycloud/named_variable_set/named_variable_set_pb2.py +25 -3
- luminarycloud/_proto/api/v0/luminarycloud/named_variable_set/named_variable_set_pb2.pyi +30 -0
- luminarycloud/_proto/api/v0/luminarycloud/named_variable_set/named_variable_set_pb2_grpc.py +34 -0
- luminarycloud/_proto/api/v0/luminarycloud/named_variable_set/named_variable_set_pb2_grpc.pyi +12 -0
- luminarycloud/_proto/api/v0/luminarycloud/physics_ai/physics_ai_pb2.py +140 -45
- luminarycloud/_proto/api/v0/luminarycloud/physics_ai/physics_ai_pb2.pyi +322 -8
- luminarycloud/_proto/api/v0/luminarycloud/physics_ai/physics_ai_pb2_grpc.py +68 -0
- luminarycloud/_proto/api/v0/luminarycloud/physics_ai/physics_ai_pb2_grpc.pyi +24 -0
- luminarycloud/_proto/api/v0/luminarycloud/physicsaiinference/physicsaiinference_pb2.py +93 -33
- luminarycloud/_proto/api/v0/luminarycloud/physicsaiinference/physicsaiinference_pb2.pyi +105 -0
- luminarycloud/_proto/api/v0/luminarycloud/physicsaiinference/physicsaiinference_pb2_grpc.py +70 -0
- luminarycloud/_proto/api/v0/luminarycloud/physicsaiinference/physicsaiinference_pb2_grpc.pyi +29 -0
- luminarycloud/_proto/api/v0/luminarycloud/simulation/simulation_pb2.py +29 -7
- luminarycloud/_proto/api/v0/luminarycloud/simulation/simulation_pb2.pyi +39 -0
- luminarycloud/_proto/api/v0/luminarycloud/simulation/simulation_pb2_grpc.py +36 -0
- luminarycloud/_proto/api/v0/luminarycloud/simulation/simulation_pb2_grpc.pyi +18 -0
- luminarycloud/_proto/api/v0/luminarycloud/thirdpartyintegration/onshape/onshape_pb2.py +70 -70
- luminarycloud/_proto/api/v0/luminarycloud/thirdpartyintegration/onshape/onshape_pb2.pyi +5 -5
- luminarycloud/_proto/api/v0/luminarycloud/vis/vis_pb2.py +163 -153
- luminarycloud/_proto/api/v0/luminarycloud/vis/vis_pb2.pyi +37 -3
- luminarycloud/_proto/client/simulation_pb2.py +356 -337
- luminarycloud/_proto/client/simulation_pb2.pyi +89 -3
- luminarycloud/_proto/lcstatus/details/geometry/geometry_pb2.py +256 -0
- luminarycloud/_proto/lcstatus/details/geometry/geometry_pb2.pyi +472 -0
- luminarycloud/_proto/physicsaiinferenceservice/physicsaiinferenceservice_pb2.py +9 -4
- luminarycloud/_proto/physicsaitrainingservice/physicsaitrainingservice_pb2.py +6 -3
- luminarycloud/_proto/physicsaitrainingservice/physicsaitrainingservice_pb2_grpc.py +68 -0
- luminarycloud/_proto/physicsaitrainingservice/physicsaitrainingservice_pb2_grpc.pyi +24 -0
- luminarycloud/_proto/quantity/quantity_pb2.pyi +1 -1
- luminarycloud/_wrapper.py +53 -7
- luminarycloud/feature_modification.py +25 -32
- luminarycloud/geometry.py +6 -6
- luminarycloud/outputs/__init__.py +2 -0
- luminarycloud/outputs/output_definitions.py +3 -3
- luminarycloud/outputs/stopping_conditions.py +94 -0
- luminarycloud/params/enum/_enum_wrappers.py +16 -0
- luminarycloud/params/geometry/shapes.py +33 -33
- luminarycloud/params/simulation/adaptive_mesh_refinement/__init__.py +1 -0
- luminarycloud/params/simulation/adaptive_mesh_refinement/active_region_.py +83 -0
- luminarycloud/params/simulation/adaptive_mesh_refinement/boundary_layer_profile_.py +1 -1
- luminarycloud/params/simulation/adaptive_mesh_refinement_.py +8 -1
- luminarycloud/physics_ai/__init__.py +15 -0
- luminarycloud/physics_ai/architectures.py +1 -1
- luminarycloud/physics_ai/datasets.py +246 -0
- luminarycloud/physics_ai/inference.py +166 -199
- luminarycloud/physics_ai/models.py +22 -0
- luminarycloud/pipelines/__init__.py +11 -0
- luminarycloud/pipelines/api.py +106 -9
- luminarycloud/pipelines/core.py +358 -45
- luminarycloud/pipelines/flowables.py +138 -0
- luminarycloud/pipelines/stages.py +7 -31
- luminarycloud/project.py +56 -2
- luminarycloud/simulation.py +25 -0
- luminarycloud/types/__init__.py +2 -0
- luminarycloud/types/ids.py +2 -0
- luminarycloud/vis/__init__.py +1 -0
- luminarycloud/vis/filters.py +97 -0
- luminarycloud/vis/visualization.py +3 -0
- luminarycloud/volume_selection.py +6 -6
- luminarycloud/workflow_utils.py +149 -0
- {luminarycloud-0.22.1.dist-info → luminarycloud-0.22.3.dist-info}/METADATA +1 -1
- {luminarycloud-0.22.1.dist-info → luminarycloud-0.22.3.dist-info}/RECORD +73 -70
- luminarycloud/_proto/api/v0/luminarycloud/inference/inference_pb2.py +0 -61
- luminarycloud/_proto/api/v0/luminarycloud/inference/inference_pb2.pyi +0 -85
- luminarycloud/_proto/api/v0/luminarycloud/inference/inference_pb2_grpc.py +0 -67
- luminarycloud/_proto/api/v0/luminarycloud/inference/inference_pb2_grpc.pyi +0 -26
- luminarycloud/_proto/inferenceservice/inferenceservice_pb2.py +0 -69
- {luminarycloud-0.22.1.dist-info → luminarycloud-0.22.3.dist-info}/WHEEL +0 -0
luminarycloud/_wrapper.py
CHANGED
|
@@ -103,20 +103,62 @@ class ProtoWrapper(Generic[P]):
|
|
|
103
103
|
def getter(field_name: str) -> Any:
|
|
104
104
|
return lambda self: getattr(self._proto, field_name)
|
|
105
105
|
|
|
106
|
-
def wrapped_getter(field_name: str, wrapper: type
|
|
107
|
-
|
|
106
|
+
def wrapped_getter(field_name: str, wrapper: type) -> Any:
|
|
107
|
+
def _get(self):
|
|
108
|
+
proto_value = getattr(self._proto, field_name)
|
|
109
|
+
|
|
110
|
+
# If it's a ProtoWrapperBase, use the standard pattern
|
|
111
|
+
if issubclass(wrapper, ProtoWrapperBase):
|
|
112
|
+
return wrapper(proto_value)
|
|
113
|
+
|
|
114
|
+
# If it's Vector3, use the conversion pattern
|
|
115
|
+
if wrapper is Vector3:
|
|
116
|
+
return Vector3(
|
|
117
|
+
x=float(proto_value.x), y=float(proto_value.y), z=float(proto_value.z)
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
# For other types, try the constructor directly
|
|
121
|
+
try:
|
|
122
|
+
return wrapper(proto_value)
|
|
123
|
+
except (TypeError, ValueError):
|
|
124
|
+
# Fallback: return the proto value as-is
|
|
125
|
+
return proto_value
|
|
126
|
+
|
|
127
|
+
return _get
|
|
108
128
|
|
|
109
129
|
# This binds the field name to the setter.
|
|
110
130
|
def setter(field_name: str) -> Callable[[C, Any], None]:
|
|
111
131
|
return lambda self, value: setattr(self._proto, field_name, value)
|
|
112
132
|
|
|
113
|
-
def wrapped_setter(
|
|
114
|
-
field_name: str, wrapper: type[ProtoWrapperBase]
|
|
115
|
-
) -> Callable[[C, Any], None]:
|
|
133
|
+
def wrapped_setter(field_name: str, wrapper: type) -> Callable[[C, Any], None]:
|
|
116
134
|
def _set(self: C, value: Any) -> None:
|
|
117
135
|
if not isinstance(value, wrapper):
|
|
118
136
|
raise TypeError(f"{field_name} should be a {wrapper.__name__}")
|
|
119
|
-
|
|
137
|
+
|
|
138
|
+
# If it's a ProtoWrapperBase, extract the _proto
|
|
139
|
+
if issubclass(wrapper, ProtoWrapperBase):
|
|
140
|
+
# For protobuf message fields, use CopyFrom instead of direct assignment
|
|
141
|
+
proto_field = getattr(self._proto, field_name)
|
|
142
|
+
proto_field.CopyFrom(value._proto)
|
|
143
|
+
|
|
144
|
+
# If it's Vector3, convert to protobuf Vector3
|
|
145
|
+
elif wrapper is Vector3:
|
|
146
|
+
proto_field = getattr(self._proto, field_name)
|
|
147
|
+
proto_field.x = float(value.x)
|
|
148
|
+
proto_field.y = float(value.y)
|
|
149
|
+
proto_field.z = float(value.z)
|
|
150
|
+
|
|
151
|
+
# For other types, try direct assignment or conversion
|
|
152
|
+
else:
|
|
153
|
+
try:
|
|
154
|
+
# Try using _to_proto method if it exists
|
|
155
|
+
if hasattr(value, "_to_proto"):
|
|
156
|
+
setattr(self._proto, field_name, value._to_proto())
|
|
157
|
+
else:
|
|
158
|
+
setattr(self._proto, field_name, value)
|
|
159
|
+
except (TypeError, ValueError, AttributeError):
|
|
160
|
+
# Fallback: direct assignment
|
|
161
|
+
setattr(self._proto, field_name, value)
|
|
120
162
|
|
|
121
163
|
return _set
|
|
122
164
|
|
|
@@ -148,7 +190,11 @@ class ProtoWrapper(Generic[P]):
|
|
|
148
190
|
pass
|
|
149
191
|
else:
|
|
150
192
|
try:
|
|
151
|
-
if
|
|
193
|
+
if (
|
|
194
|
+
issubclass(_type, Enum)
|
|
195
|
+
or issubclass(_type, ProtoWrapperBase)
|
|
196
|
+
or _type is Vector3
|
|
197
|
+
):
|
|
152
198
|
fget = wrapped_getter(field.name, _type)
|
|
153
199
|
fset = wrapped_setter(field.name, _type)
|
|
154
200
|
except TypeError:
|
|
@@ -148,6 +148,29 @@ def _update_repeated_field(
|
|
|
148
148
|
target_field.extend(new_values)
|
|
149
149
|
|
|
150
150
|
|
|
151
|
+
def _update_create_op_from_shape(create_op: gpb.Create, shape: Shape) -> None:
|
|
152
|
+
"""Helper function to replace the shape in a gpb.Create operation with a shape object.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
create: The gpb.Create to modify
|
|
156
|
+
shape: The shape to add
|
|
157
|
+
"""
|
|
158
|
+
if isinstance(shape, Sphere):
|
|
159
|
+
create_op.sphere.CopyFrom(shape._to_proto())
|
|
160
|
+
elif isinstance(shape, Cube):
|
|
161
|
+
create_op.box.CopyFrom(shape._to_proto())
|
|
162
|
+
elif isinstance(shape, Cylinder):
|
|
163
|
+
create_op.cylinder.CopyFrom(shape._to_proto())
|
|
164
|
+
elif isinstance(shape, Torus):
|
|
165
|
+
create_op.torus.CopyFrom(shape._to_proto())
|
|
166
|
+
elif isinstance(shape, Cone):
|
|
167
|
+
create_op.cone.CopyFrom(shape._to_proto())
|
|
168
|
+
elif isinstance(shape, HalfSphere):
|
|
169
|
+
create_op.half_sphere.CopyFrom(shape._to_proto())
|
|
170
|
+
else:
|
|
171
|
+
raise TypeError(f"Unsupported shape type: {type(shape)}")
|
|
172
|
+
|
|
173
|
+
|
|
151
174
|
def modify_import(
|
|
152
175
|
feature: gpb.Feature,
|
|
153
176
|
geometry_url: Optional[str] = None,
|
|
@@ -205,22 +228,7 @@ def modify_create(
|
|
|
205
228
|
create_op = feature_copy.create
|
|
206
229
|
|
|
207
230
|
if shape is not None:
|
|
208
|
-
create_op
|
|
209
|
-
|
|
210
|
-
if isinstance(shape, Sphere):
|
|
211
|
-
create_op.sphere.CopyFrom(shape._to_proto()) # type: ignore
|
|
212
|
-
elif isinstance(shape, Cube):
|
|
213
|
-
create_op.box.CopyFrom(shape._to_proto()) # type: ignore
|
|
214
|
-
elif isinstance(shape, Cylinder):
|
|
215
|
-
create_op.cylinder.CopyFrom(shape._to_proto()) # type: ignore
|
|
216
|
-
elif isinstance(shape, Torus):
|
|
217
|
-
create_op.torus.CopyFrom(shape._to_proto()) # type: ignore
|
|
218
|
-
elif isinstance(shape, Cone):
|
|
219
|
-
create_op.cone.CopyFrom(shape._to_proto()) # type: ignore
|
|
220
|
-
elif isinstance(shape, HalfSphere):
|
|
221
|
-
create_op.half_sphere.CopyFrom(shape._to_proto()) # type: ignore
|
|
222
|
-
else:
|
|
223
|
-
raise TypeError(f"Unsupported shape type: {type(shape)}")
|
|
231
|
+
_update_create_op_from_shape(create_op, shape)
|
|
224
232
|
|
|
225
233
|
return gpb.Modification(
|
|
226
234
|
mod_type=gpb.Modification.ModificationType.MODIFICATION_TYPE_UPDATE_FEATURE,
|
|
@@ -719,22 +727,7 @@ def modify_farfield(
|
|
|
719
727
|
farfield_op = feature_copy.farfield
|
|
720
728
|
|
|
721
729
|
if shape is not None:
|
|
722
|
-
|
|
723
|
-
if isinstance(shape, Sphere):
|
|
724
|
-
create_op.sphere.CopyFrom(shape._to_proto()) # type: ignore
|
|
725
|
-
elif isinstance(shape, Cube):
|
|
726
|
-
create_op.box.CopyFrom(shape._to_proto()) # type: ignore
|
|
727
|
-
elif isinstance(shape, Cylinder):
|
|
728
|
-
create_op.cylinder.CopyFrom(shape._to_proto()) # type: ignore
|
|
729
|
-
elif isinstance(shape, Torus):
|
|
730
|
-
create_op.torus.CopyFrom(shape._to_proto()) # type: ignore
|
|
731
|
-
elif isinstance(shape, Cone):
|
|
732
|
-
create_op.cone.CopyFrom(shape._to_proto()) # type: ignore
|
|
733
|
-
elif isinstance(shape, HalfSphere):
|
|
734
|
-
create_op.half_sphere.CopyFrom(shape._to_proto()) # type: ignore
|
|
735
|
-
else:
|
|
736
|
-
raise TypeError(f"Unsupported shape type: {type(shape)}")
|
|
737
|
-
farfield_op.create.CopyFrom(create_op)
|
|
730
|
+
_update_create_op_from_shape(farfield_op.create, shape)
|
|
738
731
|
|
|
739
732
|
if volumes is not None:
|
|
740
733
|
vol_ids = _volumes_to_int_list(volumes)
|
luminarycloud/geometry.py
CHANGED
|
@@ -178,17 +178,17 @@ class Geometry(ProtoWrapperBase):
|
|
|
178
178
|
"""
|
|
179
179
|
create_proto = gpb.Create()
|
|
180
180
|
if isinstance(shape, shapes.Sphere):
|
|
181
|
-
create_proto.sphere.CopyFrom(shape._to_proto())
|
|
181
|
+
create_proto.sphere.CopyFrom(shape._to_proto())
|
|
182
182
|
elif isinstance(shape, shapes.Cube):
|
|
183
|
-
create_proto.box.CopyFrom(shape._to_proto())
|
|
183
|
+
create_proto.box.CopyFrom(shape._to_proto())
|
|
184
184
|
elif isinstance(shape, shapes.Cylinder):
|
|
185
|
-
create_proto.cylinder.CopyFrom(shape._to_proto())
|
|
185
|
+
create_proto.cylinder.CopyFrom(shape._to_proto())
|
|
186
186
|
elif isinstance(shape, shapes.Torus):
|
|
187
|
-
create_proto.torus.CopyFrom(shape._to_proto())
|
|
187
|
+
create_proto.torus.CopyFrom(shape._to_proto())
|
|
188
188
|
elif isinstance(shape, shapes.Cone):
|
|
189
|
-
create_proto.cone.CopyFrom(shape._to_proto())
|
|
189
|
+
create_proto.cone.CopyFrom(shape._to_proto())
|
|
190
190
|
elif isinstance(shape, shapes.HalfSphere):
|
|
191
|
-
create_proto.half_sphere.CopyFrom(shape._to_proto())
|
|
191
|
+
create_proto.half_sphere.CopyFrom(shape._to_proto())
|
|
192
192
|
else:
|
|
193
193
|
raise TypeError(f"Unsupported shape for farfield: {type(shape)}")
|
|
194
194
|
self._modify(
|
|
@@ -19,6 +19,8 @@ from .output_definitions import (
|
|
|
19
19
|
|
|
20
20
|
from .stopping_conditions import (
|
|
21
21
|
StoppingCondition as StoppingCondition,
|
|
22
|
+
StoppingConditionResult as StoppingConditionResult,
|
|
23
|
+
StoppingConditionStatusResult as StoppingConditionStatusResult,
|
|
22
24
|
GeneralStoppingConditions as GeneralStoppingConditions,
|
|
23
25
|
create_or_update_stopping_condition as create_or_update_stopping_condition,
|
|
24
26
|
get_stopping_condition as get_stopping_condition,
|
|
@@ -125,7 +125,7 @@ class SurfaceAverageOutputDefinition(CodeRepr):
|
|
|
125
125
|
space_averaging_type: SpaceAveragingType = SpaceAveragingType.AREA
|
|
126
126
|
"Type of spatial averaging to use."
|
|
127
127
|
vector_component: Vector3Component = Vector3Component.UNSPECIFIED
|
|
128
|
-
"For vector quantities, the component to measure."
|
|
128
|
+
"For vector quantities, the component to measure must be specified (X, Y, or Z)."
|
|
129
129
|
|
|
130
130
|
def _to_proto(self) -> feoutputpb.OutputNode:
|
|
131
131
|
proto = feoutputpb.OutputNode(
|
|
@@ -309,7 +309,7 @@ class PointProbeOutputDefinition(CodeRepr):
|
|
|
309
309
|
include: OutputDefinitionInclusions = field(default_factory=OutputDefinitionInclusions)
|
|
310
310
|
"Configuration for what values to include."
|
|
311
311
|
vector_component: Vector3Component = Vector3Component.UNSPECIFIED
|
|
312
|
-
"For vector quantities, the component to measure."
|
|
312
|
+
"For vector quantities, the component to measure must be specified (X, Y, or Z)."
|
|
313
313
|
|
|
314
314
|
def _to_proto(self) -> feoutputpb.OutputNode:
|
|
315
315
|
proto = feoutputpb.OutputNode(
|
|
@@ -356,7 +356,7 @@ class VolumeReductionOutputDefinition(CodeRepr):
|
|
|
356
356
|
volume_reduction_type: VolumeReductionType = VolumeReductionType.AVERAGE
|
|
357
357
|
"Type of reduction to perform for each volume."
|
|
358
358
|
vector_component: Vector3Component = Vector3Component.UNSPECIFIED
|
|
359
|
-
"For vector quantities, the component to measure."
|
|
359
|
+
"For vector quantities, the component to measure must be specified (X, Y, or Z)."
|
|
360
360
|
|
|
361
361
|
def _to_proto(self) -> feoutputpb.OutputNode:
|
|
362
362
|
proto = feoutputpb.OutputNode(
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from .._client import get_default_client
|
|
4
4
|
from .._proto.api.v0.luminarycloud.stopping_condition import stopping_condition_pb2 as stopcondpb
|
|
5
|
+
from .._proto.api.v0.luminarycloud.simulation import simulation_pb2 as simulationpb
|
|
5
6
|
from .._proto.output import output_pb2 as outputpb
|
|
6
7
|
from dataclasses import dataclass
|
|
7
8
|
|
|
@@ -213,3 +214,96 @@ def update_general_stopping_conditions(
|
|
|
213
214
|
)
|
|
214
215
|
res = get_default_client().UpdateBasicStoppingConditions(req)
|
|
215
216
|
return GeneralStoppingConditions._from_proto(res.basic_stopping_conditions)
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
@dataclass
|
|
220
|
+
class StoppingConditionResult:
|
|
221
|
+
"""
|
|
222
|
+
Result of evaluating a single stopping condition.
|
|
223
|
+
|
|
224
|
+
Attributes
|
|
225
|
+
----------
|
|
226
|
+
output_name : str
|
|
227
|
+
Name of the output being monitored.
|
|
228
|
+
threshold : float
|
|
229
|
+
The threshold value for this condition.
|
|
230
|
+
value : float
|
|
231
|
+
The actual value of the monitored output.
|
|
232
|
+
satisfied : bool
|
|
233
|
+
Whether this condition was satisfied.
|
|
234
|
+
is_force_condition : bool
|
|
235
|
+
Whether this is a force-stop condition (e.g., max iterations, max time).
|
|
236
|
+
Force conditions cause immediate termination regardless of other conditions.
|
|
237
|
+
"""
|
|
238
|
+
|
|
239
|
+
output_name: str
|
|
240
|
+
threshold: float
|
|
241
|
+
value: float
|
|
242
|
+
satisfied: bool
|
|
243
|
+
is_force_condition: bool
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
@dataclass
|
|
247
|
+
class StoppingConditionStatusResult:
|
|
248
|
+
"""
|
|
249
|
+
Status of all stopping conditions for a simulation.
|
|
250
|
+
|
|
251
|
+
This represents the evaluation of stopping conditions against the final
|
|
252
|
+
simulation results.
|
|
253
|
+
|
|
254
|
+
Attributes
|
|
255
|
+
----------
|
|
256
|
+
overall_success : bool
|
|
257
|
+
Whether the overall stopping criteria were met (excluding force-stop conditions).
|
|
258
|
+
force_stopped : bool
|
|
259
|
+
Whether a force-stop condition was triggered.
|
|
260
|
+
condition_results : list[StoppingConditionResult]
|
|
261
|
+
Results for each individual stopping condition.
|
|
262
|
+
"""
|
|
263
|
+
|
|
264
|
+
overall_success: bool
|
|
265
|
+
force_stopped: bool
|
|
266
|
+
condition_results: list[StoppingConditionResult]
|
|
267
|
+
|
|
268
|
+
@classmethod
|
|
269
|
+
def _from_proto(
|
|
270
|
+
cls, proto: simulationpb.GetStoppingConditionStatusResponse
|
|
271
|
+
) -> "StoppingConditionStatusResult":
|
|
272
|
+
condition_results = []
|
|
273
|
+
for i, condition in enumerate(proto.conditions):
|
|
274
|
+
# Get the value from the status with bounds checking
|
|
275
|
+
value = (
|
|
276
|
+
proto.status.value[i].values[0].value
|
|
277
|
+
if i < len(proto.status.value) and proto.status.value[i].values
|
|
278
|
+
else float("nan")
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
# Get the threshold, checking for field presence (not truthiness)
|
|
282
|
+
threshold = condition.threshold.value if condition.HasField("threshold") else 0.0
|
|
283
|
+
|
|
284
|
+
# Check if this is a force condition
|
|
285
|
+
is_force = condition.op == outputpb.STOP_COND_OP_FORCE
|
|
286
|
+
|
|
287
|
+
# Get output name with field presence check
|
|
288
|
+
output_name = condition.output.name if condition.HasField("output") else ""
|
|
289
|
+
|
|
290
|
+
# Get satisfied status with bounds checking
|
|
291
|
+
satisfied = (
|
|
292
|
+
proto.status.cond_success[i] if i < len(proto.status.cond_success) else False
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
condition_results.append(
|
|
296
|
+
StoppingConditionResult(
|
|
297
|
+
output_name=output_name,
|
|
298
|
+
threshold=threshold,
|
|
299
|
+
value=value,
|
|
300
|
+
satisfied=satisfied,
|
|
301
|
+
is_force_condition=is_force,
|
|
302
|
+
)
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
return cls(
|
|
306
|
+
overall_success=proto.status.success,
|
|
307
|
+
force_stopped=proto.status.force_stop,
|
|
308
|
+
condition_results=condition_results,
|
|
309
|
+
)
|
|
@@ -747,6 +747,14 @@ class PtTableFluid(_IntEnum):
|
|
|
747
747
|
R410A.
|
|
748
748
|
REAL_GAS_R507A
|
|
749
749
|
R507A.
|
|
750
|
+
REAL_GAS_R513A
|
|
751
|
+
R513A.
|
|
752
|
+
REAL_GAS_R513B
|
|
753
|
+
R513B.
|
|
754
|
+
REAL_GAS_R515A
|
|
755
|
+
R515A.
|
|
756
|
+
REAL_GAS_R515B
|
|
757
|
+
R515B.
|
|
750
758
|
REAL_GAS_RC318
|
|
751
759
|
RC318.
|
|
752
760
|
REAL_GAS_SES36
|
|
@@ -883,6 +891,10 @@ class PtTableFluid(_IntEnum):
|
|
|
883
891
|
>>> PtTableFluid.REAL_GAS_R41
|
|
884
892
|
>>> PtTableFluid.REAL_GAS_R410A
|
|
885
893
|
>>> PtTableFluid.REAL_GAS_R507A
|
|
894
|
+
>>> PtTableFluid.REAL_GAS_R513A
|
|
895
|
+
>>> PtTableFluid.REAL_GAS_R513B
|
|
896
|
+
>>> PtTableFluid.REAL_GAS_R515A
|
|
897
|
+
>>> PtTableFluid.REAL_GAS_R515B
|
|
886
898
|
>>> PtTableFluid.REAL_GAS_RC318
|
|
887
899
|
>>> PtTableFluid.REAL_GAS_SES36
|
|
888
900
|
>>> PtTableFluid.REAL_GAS_SULFUR_DIOXIDE
|
|
@@ -1009,6 +1021,10 @@ class PtTableFluid(_IntEnum):
|
|
|
1009
1021
|
REAL_GAS_R41 = _clientpb.REAL_GAS_R41
|
|
1010
1022
|
REAL_GAS_R410A = _clientpb.REAL_GAS_R410A
|
|
1011
1023
|
REAL_GAS_R507A = _clientpb.REAL_GAS_R507A
|
|
1024
|
+
REAL_GAS_R513A = _clientpb.REAL_GAS_R513A
|
|
1025
|
+
REAL_GAS_R513B = _clientpb.REAL_GAS_R513B
|
|
1026
|
+
REAL_GAS_R515A = _clientpb.REAL_GAS_R515A
|
|
1027
|
+
REAL_GAS_R515B = _clientpb.REAL_GAS_R515B
|
|
1012
1028
|
REAL_GAS_RC318 = _clientpb.REAL_GAS_RC318
|
|
1013
1029
|
REAL_GAS_SES36 = _clientpb.REAL_GAS_SES36
|
|
1014
1030
|
REAL_GAS_SULFUR_DIOXIDE = _clientpb.REAL_GAS_SULFUR_DIOXIDE
|
|
@@ -1,84 +1,84 @@
|
|
|
1
1
|
# Copyright 2024 Luminary Cloud, Inc. All Rights Reserved.
|
|
2
|
-
from dataclasses import dataclass
|
|
2
|
+
from dataclasses import dataclass, field
|
|
3
3
|
|
|
4
|
-
from luminarycloud.
|
|
5
|
-
from luminarycloud._helpers.proto_decorator import proto_decorator
|
|
4
|
+
from luminarycloud._helpers.proto_decorator import ProtoConvertible, proto_decorator
|
|
6
5
|
from luminarycloud._proto.cad import shape_pb2 as shapepb
|
|
6
|
+
from luminarycloud.types import Vector3
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
class Shape:
|
|
9
|
+
class Shape(ProtoConvertible):
|
|
10
10
|
pass
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
@dataclass(kw_only=True)
|
|
14
14
|
@proto_decorator(shapepb.Sphere)
|
|
15
15
|
class Sphere(Shape):
|
|
16
|
-
center: Vector3
|
|
17
|
-
radius: float
|
|
16
|
+
center: Vector3 = field(default_factory=Vector3)
|
|
17
|
+
radius: float = 0.0
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
@dataclass(kw_only=True)
|
|
21
21
|
@proto_decorator(shapepb.SphereShell)
|
|
22
22
|
class SphereShell(Shape):
|
|
23
|
-
center: Vector3
|
|
24
|
-
radius: float
|
|
25
|
-
radius_inner: float
|
|
23
|
+
center: Vector3 = field(default_factory=Vector3)
|
|
24
|
+
radius: float = 0.0
|
|
25
|
+
radius_inner: float = 0.0
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
@dataclass(kw_only=True)
|
|
29
29
|
@proto_decorator(shapepb.HalfSphere)
|
|
30
30
|
class HalfSphere(Shape):
|
|
31
|
-
center: Vector3
|
|
32
|
-
radius: float
|
|
33
|
-
normal: Vector3
|
|
31
|
+
center: Vector3 = field(default_factory=Vector3)
|
|
32
|
+
radius: float = 0.0
|
|
33
|
+
normal: Vector3 = field(default_factory=Vector3)
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
@dataclass(kw_only=True)
|
|
37
37
|
@proto_decorator(shapepb.Cube)
|
|
38
38
|
class Cube(Shape):
|
|
39
|
-
min: Vector3
|
|
40
|
-
max: Vector3
|
|
39
|
+
min: Vector3 = field(default_factory=Vector3)
|
|
40
|
+
max: Vector3 = field(default_factory=Vector3)
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
@dataclass(kw_only=True)
|
|
44
44
|
@proto_decorator(shapepb.OrientedCube)
|
|
45
45
|
class OrientedCube(Shape):
|
|
46
|
-
min: Vector3
|
|
47
|
-
max: Vector3
|
|
48
|
-
origin: Vector3
|
|
49
|
-
x_axis: Vector3
|
|
50
|
-
y_axis: Vector3
|
|
46
|
+
min: Vector3 = field(default_factory=Vector3)
|
|
47
|
+
max: Vector3 = field(default_factory=Vector3)
|
|
48
|
+
origin: Vector3 = field(default_factory=Vector3)
|
|
49
|
+
x_axis: Vector3 = field(default_factory=Vector3)
|
|
50
|
+
y_axis: Vector3 = field(default_factory=Vector3)
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
@dataclass(kw_only=True)
|
|
54
54
|
@proto_decorator(shapepb.Cylinder)
|
|
55
55
|
class Cylinder(Shape):
|
|
56
|
-
start: Vector3
|
|
57
|
-
end: Vector3
|
|
58
|
-
radius: float
|
|
56
|
+
start: Vector3 = field(default_factory=Vector3)
|
|
57
|
+
end: Vector3 = field(default_factory=Vector3)
|
|
58
|
+
radius: float = 0.0
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
@dataclass(kw_only=True)
|
|
62
62
|
@proto_decorator(shapepb.AnnularCylinder)
|
|
63
63
|
class AnnularCylinder(Shape):
|
|
64
|
-
start: Vector3
|
|
65
|
-
end: Vector3
|
|
66
|
-
radius: float
|
|
67
|
-
radius_inner: float
|
|
64
|
+
start: Vector3 = field(default_factory=Vector3)
|
|
65
|
+
end: Vector3 = field(default_factory=Vector3)
|
|
66
|
+
radius: float = 0.0
|
|
67
|
+
radius_inner: float = 0.0
|
|
68
68
|
|
|
69
69
|
|
|
70
70
|
@dataclass(kw_only=True)
|
|
71
71
|
@proto_decorator(shapepb.Torus)
|
|
72
72
|
class Torus(Shape):
|
|
73
|
-
center: Vector3
|
|
74
|
-
normal: Vector3
|
|
75
|
-
major_radius: float
|
|
76
|
-
minor_radius: float
|
|
73
|
+
center: Vector3 = field(default_factory=Vector3)
|
|
74
|
+
normal: Vector3 = field(default_factory=Vector3)
|
|
75
|
+
major_radius: float = 0.0
|
|
76
|
+
minor_radius: float = 0.0
|
|
77
77
|
|
|
78
78
|
|
|
79
79
|
@dataclass(kw_only=True)
|
|
80
80
|
@proto_decorator(shapepb.Cone)
|
|
81
81
|
class Cone(Shape):
|
|
82
|
-
apex: Vector3
|
|
83
|
-
base_center: Vector3
|
|
84
|
-
base_radius: float
|
|
82
|
+
apex: Vector3 = field(default_factory=Vector3)
|
|
83
|
+
base_center: Vector3 = field(default_factory=Vector3)
|
|
84
|
+
base_radius: float = 0.0
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Generated by generate_sdk_wrappers.py. DO NOT EDIT
|
|
2
|
+
|
|
3
|
+
from abc import ABC, ABCMeta
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from typing import Any
|
|
6
|
+
from uuid import uuid4
|
|
7
|
+
|
|
8
|
+
from google.protobuf.message import Message as _Message
|
|
9
|
+
from luminarycloud.tables import RectilinearTable, _param_name_to_table_type
|
|
10
|
+
from luminarycloud.types import Vector3, LcFloat
|
|
11
|
+
from luminarycloud.types.adfloat import _to_ad_proto, _from_ad_proto
|
|
12
|
+
from luminarycloud._helpers._entity_identifier import _create_entity_identifier
|
|
13
|
+
from luminarycloud._proto.client import simulation_pb2 as clientpb
|
|
14
|
+
from luminarycloud._proto.client.entity_pb2 import EntityIdentifier
|
|
15
|
+
from luminarycloud._helpers import CodeRepr
|
|
16
|
+
import luminarycloud.params.enum._enum_wrappers as enum
|
|
17
|
+
|
|
18
|
+
from luminarycloud.params.simulation._lib import ParamGroupWrapper, create_unique_id
|
|
19
|
+
|
|
20
|
+
from luminarycloud.params.geometry import shapes
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass(kw_only=True)
|
|
24
|
+
class ActiveRegion(CodeRepr, ParamGroupWrapper[clientpb.ActiveRegion]):
|
|
25
|
+
"""Region(s) within which the mesh is adapted at full resolution. Outside of these regions the mesh is coarsened with increasing distance from the region."""
|
|
26
|
+
|
|
27
|
+
error_weight: LcFloat = 1.0
|
|
28
|
+
"Error weighting from the active region at Max Distance. Local error weighting is 1.0 inside the region and decreases to Error Weight at the Max Distance."
|
|
29
|
+
max_distance: LcFloat = 0.0
|
|
30
|
+
"Distance from the active regions at which to apply the full error factor."
|
|
31
|
+
cube: shapes.Cube | None = None
|
|
32
|
+
"Coordinate-aligned box."
|
|
33
|
+
oriented_cube: shapes.OrientedCube | None = None
|
|
34
|
+
"Box oriented along arbitrary axes."
|
|
35
|
+
cylinder: shapes.Cylinder | None = None
|
|
36
|
+
"Cylinder shape."
|
|
37
|
+
annular_cylinder: shapes.AnnularCylinder | None = None
|
|
38
|
+
"Cylinder with a hole along the axis."
|
|
39
|
+
sphere: shapes.Sphere | None = None
|
|
40
|
+
"Sphere shape."
|
|
41
|
+
sphere_shell: shapes.SphereShell | None = None
|
|
42
|
+
"Spherical shell shape."
|
|
43
|
+
|
|
44
|
+
def _to_proto(self) -> clientpb.ActiveRegion:
|
|
45
|
+
_proto = clientpb.ActiveRegion()
|
|
46
|
+
_proto.error_weight.CopyFrom(_to_ad_proto(self.error_weight))
|
|
47
|
+
_proto.max_distance.CopyFrom(_to_ad_proto(self.max_distance))
|
|
48
|
+
if self.cube is not None:
|
|
49
|
+
_proto.cube.CopyFrom(self.cube._to_proto())
|
|
50
|
+
if self.oriented_cube is not None:
|
|
51
|
+
_proto.oriented_cube.CopyFrom(self.oriented_cube._to_proto())
|
|
52
|
+
if self.cylinder is not None:
|
|
53
|
+
_proto.cylinder.CopyFrom(self.cylinder._to_proto())
|
|
54
|
+
if self.annular_cylinder is not None:
|
|
55
|
+
_proto.annular_cylinder.CopyFrom(self.annular_cylinder._to_proto())
|
|
56
|
+
if self.sphere is not None:
|
|
57
|
+
_proto.sphere.CopyFrom(self.sphere._to_proto())
|
|
58
|
+
if self.sphere_shell is not None:
|
|
59
|
+
_proto.sphere_shell.CopyFrom(self.sphere_shell._to_proto())
|
|
60
|
+
return _proto
|
|
61
|
+
|
|
62
|
+
def _from_proto(self, proto: clientpb.ActiveRegion) -> None:
|
|
63
|
+
self.error_weight = _from_ad_proto(proto.error_weight)
|
|
64
|
+
self.max_distance = _from_ad_proto(proto.max_distance)
|
|
65
|
+
if proto.cube.ByteSize() > 0:
|
|
66
|
+
self.cube = shapes.Cube()
|
|
67
|
+
self.cube._from_proto(proto.cube)
|
|
68
|
+
if proto.oriented_cube.ByteSize() > 0:
|
|
69
|
+
self.oriented_cube = shapes.OrientedCube()
|
|
70
|
+
self.oriented_cube._from_proto(proto.oriented_cube)
|
|
71
|
+
if proto.cylinder.ByteSize() > 0:
|
|
72
|
+
self.cylinder = shapes.Cylinder()
|
|
73
|
+
self.cylinder._from_proto(proto.cylinder)
|
|
74
|
+
if proto.annular_cylinder.ByteSize() > 0:
|
|
75
|
+
self.annular_cylinder = shapes.AnnularCylinder()
|
|
76
|
+
self.annular_cylinder._from_proto(proto.annular_cylinder)
|
|
77
|
+
if proto.sphere.ByteSize() > 0:
|
|
78
|
+
self.sphere = shapes.Sphere()
|
|
79
|
+
self.sphere._from_proto(proto.sphere)
|
|
80
|
+
if proto.sphere_shell.ByteSize() > 0:
|
|
81
|
+
self.sphere_shell = shapes.SphereShell()
|
|
82
|
+
self.sphere_shell._from_proto(proto.sphere_shell)
|
|
83
|
+
return None
|
|
@@ -20,7 +20,7 @@ from luminarycloud.params.simulation._lib import ParamGroupWrapper, create_uniqu
|
|
|
20
20
|
|
|
21
21
|
@dataclass(kw_only=True)
|
|
22
22
|
class BoundaryLayerProfile(CodeRepr, ParamGroupWrapper[clientpb.BoundaryLayerProfile]):
|
|
23
|
-
""""""
|
|
23
|
+
"""Boundary layer meshing parameters to apply to adapted meshes."""
|
|
24
24
|
|
|
25
25
|
n_layers: int = 40
|
|
26
26
|
"Maximum number of prism layers within a boundary layer mesh."
|
|
@@ -17,6 +17,8 @@ import luminarycloud.params.enum._enum_wrappers as enum
|
|
|
17
17
|
|
|
18
18
|
from luminarycloud.params.simulation._lib import ParamGroupWrapper, create_unique_id
|
|
19
19
|
|
|
20
|
+
from luminarycloud.params.simulation.adaptive_mesh_refinement.active_region_ import ActiveRegion
|
|
21
|
+
from luminarycloud.params.simulation.adaptive_mesh_refinement.active_region_ import *
|
|
20
22
|
from luminarycloud.params.simulation.adaptive_mesh_refinement.boundary_layer_profile_ import (
|
|
21
23
|
BoundaryLayerProfile,
|
|
22
24
|
)
|
|
@@ -46,7 +48,9 @@ class AdaptiveMeshRefinement(CodeRepr, ParamGroupWrapper[clientpb.AdaptiveMeshRe
|
|
|
46
48
|
user_scaling: LcFloat = 1.0
|
|
47
49
|
"Scale factor between the geometry and the mesh."
|
|
48
50
|
boundary_layer_profile: list[BoundaryLayerProfile] = field(default_factory=list)
|
|
49
|
-
""
|
|
51
|
+
"Boundary layer meshing parameters to apply to adapted meshes."
|
|
52
|
+
active_region: list[ActiveRegion] = field(default_factory=list)
|
|
53
|
+
"Region(s) within which the mesh is adapted at full resolution. Outside of these regions the mesh is coarsened with increasing distance from the region."
|
|
50
54
|
|
|
51
55
|
def _to_proto(self) -> clientpb.AdaptiveMeshRefinement:
|
|
52
56
|
_proto = clientpb.AdaptiveMeshRefinement()
|
|
@@ -61,6 +65,8 @@ class AdaptiveMeshRefinement(CodeRepr, ParamGroupWrapper[clientpb.AdaptiveMeshRe
|
|
|
61
65
|
_proto.user_scaling.CopyFrom(_to_ad_proto(self.user_scaling))
|
|
62
66
|
if self.boundary_layer_profile is not None:
|
|
63
67
|
_proto.boundary_layer_profile.extend(v._to_proto() for v in self.boundary_layer_profile)
|
|
68
|
+
if self.active_region is not None:
|
|
69
|
+
_proto.active_region.extend(v._to_proto() for v in self.active_region)
|
|
64
70
|
return _proto
|
|
65
71
|
|
|
66
72
|
def _from_proto(self, proto: clientpb.AdaptiveMeshRefinement) -> None:
|
|
@@ -76,4 +82,5 @@ class AdaptiveMeshRefinement(CodeRepr, ParamGroupWrapper[clientpb.AdaptiveMeshRe
|
|
|
76
82
|
self.boundary_layer_profile = [
|
|
77
83
|
BoundaryLayerProfile.from_proto(v) for v in proto.boundary_layer_profile
|
|
78
84
|
]
|
|
85
|
+
self.active_region = [ActiveRegion.from_proto(v) for v in proto.active_region]
|
|
79
86
|
return None
|
|
@@ -12,3 +12,18 @@ from .models import (
|
|
|
12
12
|
from .solution import (
|
|
13
13
|
_download_processed_solution_physics_ai as _download_processed_solution_physics_ai,
|
|
14
14
|
)
|
|
15
|
+
|
|
16
|
+
from .inference import (
|
|
17
|
+
InferenceJob as InferenceJob,
|
|
18
|
+
SurfaceForInference as SurfaceForInference,
|
|
19
|
+
VisualizationExport as VisualizationExport,
|
|
20
|
+
NumericResult as NumericResult,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
from .datasets import (
|
|
24
|
+
create_dataset as create_dataset,
|
|
25
|
+
list_datasets as list_datasets,
|
|
26
|
+
DatasetCaseInput as DatasetCaseInput,
|
|
27
|
+
ExportConfig as ExportConfig,
|
|
28
|
+
PhysicsAiDataset as PhysicsAiDataset,
|
|
29
|
+
)
|
|
@@ -53,7 +53,7 @@ class PhysicsAiArchitectureVersion(ProtoWrapperBase):
|
|
|
53
53
|
if "custom_args" not in config:
|
|
54
54
|
config["custom_args"] = ""
|
|
55
55
|
if "priority_class" not in config:
|
|
56
|
-
config["priority_class"] = "
|
|
56
|
+
config["priority_class"] = "internal-training-job-priority"
|
|
57
57
|
if "resources" not in config:
|
|
58
58
|
config["resources"] = {}
|
|
59
59
|
if "process_cpus" not in config["resources"]:
|