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.
Files changed (78) hide show
  1. luminarycloud/_client/client.py +5 -3
  2. luminarycloud/_client/retry_interceptor.py +13 -2
  3. luminarycloud/_helpers/__init__.py +9 -0
  4. luminarycloud/_helpers/_inference_jobs.py +227 -0
  5. luminarycloud/_helpers/_parse_iso_datetime.py +54 -0
  6. luminarycloud/_helpers/proto_decorator.py +38 -7
  7. luminarycloud/_proto/api/v0/luminarycloud/geometry/geometry_pb2.py +45 -25
  8. luminarycloud/_proto/api/v0/luminarycloud/geometry/geometry_pb2.pyi +30 -0
  9. luminarycloud/_proto/api/v0/luminarycloud/geometry/geometry_pb2_grpc.py +34 -0
  10. luminarycloud/_proto/api/v0/luminarycloud/geometry/geometry_pb2_grpc.pyi +12 -0
  11. luminarycloud/_proto/api/v0/luminarycloud/named_variable_set/named_variable_set_pb2.py +25 -3
  12. luminarycloud/_proto/api/v0/luminarycloud/named_variable_set/named_variable_set_pb2.pyi +30 -0
  13. luminarycloud/_proto/api/v0/luminarycloud/named_variable_set/named_variable_set_pb2_grpc.py +34 -0
  14. luminarycloud/_proto/api/v0/luminarycloud/named_variable_set/named_variable_set_pb2_grpc.pyi +12 -0
  15. luminarycloud/_proto/api/v0/luminarycloud/physics_ai/physics_ai_pb2.py +140 -45
  16. luminarycloud/_proto/api/v0/luminarycloud/physics_ai/physics_ai_pb2.pyi +322 -8
  17. luminarycloud/_proto/api/v0/luminarycloud/physics_ai/physics_ai_pb2_grpc.py +68 -0
  18. luminarycloud/_proto/api/v0/luminarycloud/physics_ai/physics_ai_pb2_grpc.pyi +24 -0
  19. luminarycloud/_proto/api/v0/luminarycloud/physicsaiinference/physicsaiinference_pb2.py +93 -33
  20. luminarycloud/_proto/api/v0/luminarycloud/physicsaiinference/physicsaiinference_pb2.pyi +105 -0
  21. luminarycloud/_proto/api/v0/luminarycloud/physicsaiinference/physicsaiinference_pb2_grpc.py +70 -0
  22. luminarycloud/_proto/api/v0/luminarycloud/physicsaiinference/physicsaiinference_pb2_grpc.pyi +29 -0
  23. luminarycloud/_proto/api/v0/luminarycloud/simulation/simulation_pb2.py +29 -7
  24. luminarycloud/_proto/api/v0/luminarycloud/simulation/simulation_pb2.pyi +39 -0
  25. luminarycloud/_proto/api/v0/luminarycloud/simulation/simulation_pb2_grpc.py +36 -0
  26. luminarycloud/_proto/api/v0/luminarycloud/simulation/simulation_pb2_grpc.pyi +18 -0
  27. luminarycloud/_proto/api/v0/luminarycloud/thirdpartyintegration/onshape/onshape_pb2.py +70 -70
  28. luminarycloud/_proto/api/v0/luminarycloud/thirdpartyintegration/onshape/onshape_pb2.pyi +5 -5
  29. luminarycloud/_proto/api/v0/luminarycloud/vis/vis_pb2.py +163 -153
  30. luminarycloud/_proto/api/v0/luminarycloud/vis/vis_pb2.pyi +37 -3
  31. luminarycloud/_proto/client/simulation_pb2.py +356 -337
  32. luminarycloud/_proto/client/simulation_pb2.pyi +89 -3
  33. luminarycloud/_proto/lcstatus/details/geometry/geometry_pb2.py +256 -0
  34. luminarycloud/_proto/lcstatus/details/geometry/geometry_pb2.pyi +472 -0
  35. luminarycloud/_proto/physicsaiinferenceservice/physicsaiinferenceservice_pb2.py +9 -4
  36. luminarycloud/_proto/physicsaitrainingservice/physicsaitrainingservice_pb2.py +6 -3
  37. luminarycloud/_proto/physicsaitrainingservice/physicsaitrainingservice_pb2_grpc.py +68 -0
  38. luminarycloud/_proto/physicsaitrainingservice/physicsaitrainingservice_pb2_grpc.pyi +24 -0
  39. luminarycloud/_proto/quantity/quantity_pb2.pyi +1 -1
  40. luminarycloud/_wrapper.py +53 -7
  41. luminarycloud/feature_modification.py +25 -32
  42. luminarycloud/geometry.py +6 -6
  43. luminarycloud/outputs/__init__.py +2 -0
  44. luminarycloud/outputs/output_definitions.py +3 -3
  45. luminarycloud/outputs/stopping_conditions.py +94 -0
  46. luminarycloud/params/enum/_enum_wrappers.py +16 -0
  47. luminarycloud/params/geometry/shapes.py +33 -33
  48. luminarycloud/params/simulation/adaptive_mesh_refinement/__init__.py +1 -0
  49. luminarycloud/params/simulation/adaptive_mesh_refinement/active_region_.py +83 -0
  50. luminarycloud/params/simulation/adaptive_mesh_refinement/boundary_layer_profile_.py +1 -1
  51. luminarycloud/params/simulation/adaptive_mesh_refinement_.py +8 -1
  52. luminarycloud/physics_ai/__init__.py +15 -0
  53. luminarycloud/physics_ai/architectures.py +1 -1
  54. luminarycloud/physics_ai/datasets.py +246 -0
  55. luminarycloud/physics_ai/inference.py +166 -199
  56. luminarycloud/physics_ai/models.py +22 -0
  57. luminarycloud/pipelines/__init__.py +11 -0
  58. luminarycloud/pipelines/api.py +106 -9
  59. luminarycloud/pipelines/core.py +358 -45
  60. luminarycloud/pipelines/flowables.py +138 -0
  61. luminarycloud/pipelines/stages.py +7 -31
  62. luminarycloud/project.py +56 -2
  63. luminarycloud/simulation.py +25 -0
  64. luminarycloud/types/__init__.py +2 -0
  65. luminarycloud/types/ids.py +2 -0
  66. luminarycloud/vis/__init__.py +1 -0
  67. luminarycloud/vis/filters.py +97 -0
  68. luminarycloud/vis/visualization.py +3 -0
  69. luminarycloud/volume_selection.py +6 -6
  70. luminarycloud/workflow_utils.py +149 -0
  71. {luminarycloud-0.22.1.dist-info → luminarycloud-0.22.3.dist-info}/METADATA +1 -1
  72. {luminarycloud-0.22.1.dist-info → luminarycloud-0.22.3.dist-info}/RECORD +73 -70
  73. luminarycloud/_proto/api/v0/luminarycloud/inference/inference_pb2.py +0 -61
  74. luminarycloud/_proto/api/v0/luminarycloud/inference/inference_pb2.pyi +0 -85
  75. luminarycloud/_proto/api/v0/luminarycloud/inference/inference_pb2_grpc.py +0 -67
  76. luminarycloud/_proto/api/v0/luminarycloud/inference/inference_pb2_grpc.pyi +0 -26
  77. luminarycloud/_proto/inferenceservice/inferenceservice_pb2.py +0 -69
  78. {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[ProtoWrapperBase]) -> Any:
107
- return lambda self: wrapper(getattr(self._proto, field_name))
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
- setattr(self._proto, field_name, value._proto)
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 issubclass(_type, Enum) or issubclass(_type, ProtoWrapperBase):
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.ClearField("shape")
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
- create_op = gpb.Create()
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()) # type: ignore
181
+ create_proto.sphere.CopyFrom(shape._to_proto())
182
182
  elif isinstance(shape, shapes.Cube):
183
- create_proto.box.CopyFrom(shape._to_proto()) # type: ignore
183
+ create_proto.box.CopyFrom(shape._to_proto())
184
184
  elif isinstance(shape, shapes.Cylinder):
185
- create_proto.cylinder.CopyFrom(shape._to_proto()) # type: ignore
185
+ create_proto.cylinder.CopyFrom(shape._to_proto())
186
186
  elif isinstance(shape, shapes.Torus):
187
- create_proto.torus.CopyFrom(shape._to_proto()) # type: ignore
187
+ create_proto.torus.CopyFrom(shape._to_proto())
188
188
  elif isinstance(shape, shapes.Cone):
189
- create_proto.cone.CopyFrom(shape._to_proto()) # type: ignore
189
+ create_proto.cone.CopyFrom(shape._to_proto())
190
190
  elif isinstance(shape, shapes.HalfSphere):
191
- create_proto.half_sphere.CopyFrom(shape._to_proto()) # type: ignore
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.types import Vector3
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
@@ -1 +1,2 @@
1
+ from .active_region_ import ActiveRegion
1
2
  from .boundary_layer_profile_ import BoundaryLayerProfile
@@ -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"] = "prod-batch-priority"
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"]: