luminarycloud 0.17.0__py3-none-any.whl → 0.18.1__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 (73) hide show
  1. luminarycloud/__init__.py +4 -0
  2. luminarycloud/_client/client.py +3 -0
  3. luminarycloud/_helpers/_create_geometry.py +134 -32
  4. luminarycloud/_helpers/cond.py +0 -1
  5. luminarycloud/_proto/api/v0/luminarycloud/geometry/geometry_pb2.py +146 -123
  6. luminarycloud/_proto/api/v0/luminarycloud/geometry/geometry_pb2.pyi +81 -8
  7. luminarycloud/_proto/api/v0/luminarycloud/geometry/geometry_pb2_grpc.py +34 -0
  8. luminarycloud/_proto/api/v0/luminarycloud/geometry/geometry_pb2_grpc.pyi +12 -0
  9. luminarycloud/_proto/api/v0/luminarycloud/inference/inference_pb2.py +8 -8
  10. luminarycloud/_proto/api/v0/luminarycloud/inference/inference_pb2.pyi +12 -7
  11. luminarycloud/_proto/api/v0/luminarycloud/pipelines/pipelines_pb2.py +246 -0
  12. luminarycloud/_proto/api/v0/luminarycloud/pipelines/pipelines_pb2.pyi +420 -0
  13. luminarycloud/_proto/api/v0/luminarycloud/pipelines/pipelines_pb2_grpc.py +240 -0
  14. luminarycloud/_proto/api/v0/luminarycloud/pipelines/pipelines_pb2_grpc.pyi +90 -0
  15. luminarycloud/_proto/api/v0/luminarycloud/project/project_pb2.py +54 -3
  16. luminarycloud/_proto/api/v0/luminarycloud/project/project_pb2.pyi +92 -1
  17. luminarycloud/_proto/api/v0/luminarycloud/project/project_pb2_grpc.py +132 -0
  18. luminarycloud/_proto/api/v0/luminarycloud/project/project_pb2_grpc.pyi +40 -0
  19. luminarycloud/_proto/api/v0/luminarycloud/simulation/simulation_pb2.py +88 -55
  20. luminarycloud/_proto/api/v0/luminarycloud/simulation/simulation_pb2.pyi +108 -1
  21. luminarycloud/_proto/api/v0/luminarycloud/simulation/simulation_pb2_grpc.py +35 -0
  22. luminarycloud/_proto/api/v0/luminarycloud/simulation/simulation_pb2_grpc.pyi +16 -0
  23. luminarycloud/_proto/api/v0/luminarycloud/simulation_template/simulation_template_pb2.py +48 -26
  24. luminarycloud/_proto/api/v0/luminarycloud/simulation_template/simulation_template_pb2.pyi +30 -2
  25. luminarycloud/_proto/api/v0/luminarycloud/simulation_template/simulation_template_pb2_grpc.py +36 -0
  26. luminarycloud/_proto/api/v0/luminarycloud/simulation_template/simulation_template_pb2_grpc.pyi +18 -0
  27. luminarycloud/_proto/client/simulation_pb2.py +261 -251
  28. luminarycloud/_proto/client/simulation_pb2.pyi +40 -3
  29. luminarycloud/_proto/frontend/output/output_pb2.py +24 -24
  30. luminarycloud/_proto/frontend/output/output_pb2.pyi +6 -3
  31. luminarycloud/_proto/geometry/geometry_pb2.py +63 -63
  32. luminarycloud/_proto/geometry/geometry_pb2.pyi +14 -4
  33. luminarycloud/_proto/inferenceservice/inferenceservice_pb2.py +10 -10
  34. luminarycloud/_proto/inferenceservice/inferenceservice_pb2.pyi +12 -7
  35. luminarycloud/_proto/output/output_pb2.py +43 -36
  36. luminarycloud/_proto/output/output_pb2.pyi +28 -1
  37. luminarycloud/_proto/quantity/quantity_options_pb2.py +5 -4
  38. luminarycloud/_proto/quantity/quantity_options_pb2.pyi +4 -0
  39. luminarycloud/_proto/quantity/quantity_pb2.py +8 -8
  40. luminarycloud/enum/__init__.py +1 -0
  41. luminarycloud/enum/geometry_status.py +15 -8
  42. luminarycloud/enum/moment_convention_type.py +19 -0
  43. luminarycloud/enum/pipeline_job_status.py +23 -0
  44. luminarycloud/feature_modification.py +3 -1
  45. luminarycloud/geometry.py +12 -0
  46. luminarycloud/geometry_version.py +23 -0
  47. luminarycloud/outputs/output_definitions.py +5 -0
  48. luminarycloud/params/enum/_enum_wrappers.py +29 -0
  49. luminarycloud/params/simulation/monitor_plane_.py +1 -1
  50. luminarycloud/params/simulation/physics/fluid/boundary_conditions/inlet/fan_curve_inlet_.py +1 -1
  51. luminarycloud/params/simulation/physics/fluid/boundary_conditions/inlet/mach_inlet_.py +5 -1
  52. luminarycloud/params/simulation/physics/fluid/boundary_conditions/inlet/mass_flow_inlet_.py +5 -1
  53. luminarycloud/params/simulation/physics/fluid/boundary_conditions/inlet/total_pressure_inlet_.py +5 -1
  54. luminarycloud/params/simulation/physics/fluid/boundary_conditions/inlet/velocity_magnitude_inlet_.py +5 -1
  55. luminarycloud/physics_ai/inference.py +57 -30
  56. luminarycloud/pipelines/__init__.py +7 -0
  57. luminarycloud/pipelines/api.py +213 -0
  58. luminarycloud/pipelines/operators.py +4 -4
  59. luminarycloud/project.py +66 -6
  60. luminarycloud/simulation.py +6 -0
  61. luminarycloud/simulation_param.py +4 -2
  62. luminarycloud/simulation_queue.py +130 -0
  63. luminarycloud/simulation_template.py +21 -7
  64. luminarycloud/types/adfloat.py +3 -0
  65. luminarycloud/vis/__init__.py +4 -0
  66. luminarycloud/vis/interactive_inference.py +153 -0
  67. luminarycloud/vis/interactive_scene.py +49 -17
  68. luminarycloud/vis/primitives.py +9 -0
  69. luminarycloud/vis/visualization.py +22 -0
  70. luminarycloud/volume_selection.py +3 -2
  71. {luminarycloud-0.17.0.dist-info → luminarycloud-0.18.1.dist-info}/METADATA +18 -18
  72. {luminarycloud-0.17.0.dist-info → luminarycloud-0.18.1.dist-info}/RECORD +73 -64
  73. {luminarycloud-0.17.0.dist-info → luminarycloud-0.18.1.dist-info}/WHEEL +0 -0
@@ -11,18 +11,25 @@ class GeometryStatus(IntEnum):
11
11
  ----------
12
12
  UNKNOWN
13
13
  Status is unknown.
14
- IMPORTING
15
- Geometry is still being processed.
16
- NEEDS_CHECK
17
- Geometry was created but has not yet been checked.
14
+ BUSY
15
+ Geometry is being processed (importing, modifying, or other operations).
16
+ HAS_FEATURE_ERRORS
17
+ Geometry has feature errors, which should be resolved.
18
+ READY_FOR_CHECK
19
+ Geometry has no feature errors and is ready to be checked for meshing validity.
20
+ CHECKING
21
+ Geometry check is currently running to validate the geometry.
18
22
  FAILED_CHECK
19
- Geometry is not well-formed and cannot be used.
23
+ Geometry is not well-formed and cannot be used for meshing or
24
+ simulation.
20
25
  READY
21
- Geometry is ready to use.
26
+ Geometry is ready to use for meshing and simulation.
22
27
  """
23
28
 
24
29
  UNKNOWN = geometry_pb2.Geometry.UNKNOWN
25
- IMPORTING = geometry_pb2.Geometry.IMPORTING
26
- NEEDS_CHECK = geometry_pb2.Geometry.NEEDS_CHECK
30
+ BUSY = geometry_pb2.Geometry.BUSY
31
+ HAS_FEATURE_ERRORS = geometry_pb2.Geometry.HAS_FEATURE_ERRORS
32
+ READY_FOR_CHECK = geometry_pb2.Geometry.READY_FOR_CHECK
33
+ CHECKING = geometry_pb2.Geometry.CHECKING
27
34
  FAILED_CHECK = geometry_pb2.Geometry.FAILED_CHECK
28
35
  READY = geometry_pb2.Geometry.READY
@@ -0,0 +1,19 @@
1
+ # Copyright 2025 Luminary Cloud, Inc. All Rights Reserved.
2
+ from enum import IntEnum
3
+ from .._proto.output import output_pb2 as outputpb
4
+
5
+
6
+ class MomentConventionType(IntEnum):
7
+ """
8
+ Whether the body frame or stability frame is used for pitch, roll and yaw moment calculations.
9
+
10
+ Attributes
11
+ ----------
12
+ BODY_FRAME
13
+ STABILITY_FRAME
14
+ """
15
+
16
+ UNSPECIFIED = outputpb.INVALID_MOMENT_CONVENTION_TYPE
17
+
18
+ BODY_FRAME = outputpb.MOMENT_CONVENTION_BODY_FRAME
19
+ STABILITY_FRAME = outputpb.MOMENT_CONVENTION_STABILITY_FRAME
@@ -0,0 +1,23 @@
1
+ # Copyright 2025 Luminary Cloud, Inc. All Rights Reserved.
2
+ from enum import IntEnum
3
+ from .._proto.api.v0.luminarycloud.pipelines import pipelines_pb2 as pipelinespb
4
+
5
+
6
+ class PipelineJobStatus(IntEnum):
7
+ """
8
+ Status of a pipeline job.
9
+
10
+ Attributes
11
+ ----------
12
+ PENDING
13
+ RUNNING
14
+ COMPLETED
15
+ FAILED
16
+ """
17
+
18
+ UNSPECIFIED = pipelinespb.PIPELINE_JOB_STATUS_UNSPECIFIED
19
+
20
+ PENDING = pipelinespb.PIPELINE_JOB_STATUS_PENDING
21
+ RUNNING = pipelinespb.PIPELINE_JOB_STATUS_RUNNING
22
+ COMPLETED = pipelinespb.PIPELINE_JOB_STATUS_COMPLETED
23
+ FAILED = pipelinespb.PIPELINE_JOB_STATUS_FAILED
@@ -2,6 +2,8 @@
2
2
  from enum import Enum, auto
3
3
  from typing import Dict, Iterable, List, Optional, cast
4
4
  from copy import deepcopy
5
+
6
+ from luminarycloud.types.adfloat import _to_ad_proto, _from_ad_proto
5
7
  from ._proto.geometry import geometry_pb2 as gpb
6
8
  from .types import Vector3Like
7
9
  from .types.vector3 import _to_vector3
@@ -173,7 +175,7 @@ def modify_import(
173
175
  feature_copy.import_geometry.geometry_url = geometry_url
174
176
 
175
177
  if scaling is not None:
176
- feature_copy.import_geometry.scaling = scaling
178
+ feature_copy.import_geometry.scaling.CopyFrom(_to_ad_proto(scaling))
177
179
 
178
180
  return gpb.Modification(
179
181
  mod_type=gpb.Modification.ModificationType.MODIFICATION_TYPE_UPDATE_FEATURE,
luminarycloud/geometry.py CHANGED
@@ -29,6 +29,7 @@ from .named_variable_set import NamedVariableSet, get_named_variable_set
29
29
 
30
30
  if TYPE_CHECKING:
31
31
  from .project import Project
32
+ from .geometry_version import GeometryVersion
32
33
 
33
34
 
34
35
  @ProtoWrapper(geometrypb.Geometry)
@@ -289,6 +290,17 @@ class Geometry(ProtoWrapperBase):
289
290
  )
290
291
  )
291
292
 
293
+ def latest_version(self) -> GeometryVersion:
294
+ """
295
+ Get the latest version of the geometry.
296
+ """
297
+ from .geometry_version import get_geometry_version
298
+
299
+ req = geometrypb.GetGeometryRequest(geometry_id=self.id)
300
+ res_geo: geometrypb.GetGeometryResponse = get_default_client().GetGeometry(req)
301
+ geometry_version_id = res_geo.geometry.last_version_id
302
+ return get_geometry_version(geometry_version_id)
303
+
292
304
  def check(self) -> tuple[bool, list[str]]:
293
305
  """
294
306
  Check the geometry for any issues that may prevent meshing.
@@ -87,6 +87,29 @@ class GeometryVersion(ProtoWrapperBase):
87
87
  ]
88
88
  return surfaces, volumes
89
89
 
90
+ def copy_to_new_geometry(self, name: str = "") -> Geometry:
91
+ """
92
+ Copy this GeometryVersion and create a new Geometry containing only that newly copied version.
93
+
94
+ Parameters
95
+ ----------
96
+ name : str, optional
97
+ The name of the new Geometry. If not provided, a default name will be used.
98
+
99
+ Returns
100
+ -------
101
+ Geometry
102
+ The new Geometry containing only the newly copied GeometryVersion.
103
+ """
104
+ req = geometrypb.CopyGeometryFromVersionRequest(
105
+ geometry_version_id=self.id,
106
+ name=name,
107
+ )
108
+ res: geometrypb.CopyGeometryFromVersionResponse = (
109
+ get_default_client().CopyGeometryFromVersion(req)
110
+ )
111
+ return Geometry(res.geometry)
112
+
90
113
  def _list_features(
91
114
  self,
92
115
  ) -> list[gpb.Feature]:
@@ -9,6 +9,7 @@ from ..types import Vector3
9
9
  from typing import cast, overload
10
10
  from ..enum import (
11
11
  CalculationType,
12
+ MomentConventionType,
12
13
  OutputDefinitionIncludes,
13
14
  QuantityType,
14
15
  ResidualType,
@@ -185,6 +186,8 @@ class ForceOutputDefinition(CodeRepr):
185
186
  "Center point for moment calculations."
186
187
  porous: bool = False
187
188
  "Whether the surfaces involved are porous."
189
+ moment_convention_type: MomentConventionType = MomentConventionType.BODY_FRAME
190
+ "Frame type for moment calculations (body or stability frame)."
188
191
  # TODO: it seems clumsy to make the user set `porous` correctly. we could probably set it
189
192
  # automatically based on the set of surfaces selected.
190
193
 
@@ -201,6 +204,7 @@ class ForceOutputDefinition(CodeRepr):
201
204
  force_direction=self.force_direction._to_ad_proto(),
202
205
  moment_center=self.moment_center._to_ad_proto(),
203
206
  porous=self.porous,
207
+ moment_convention_type=self.moment_convention_type.value,
204
208
  ),
205
209
  ),
206
210
  )
@@ -220,6 +224,7 @@ class ForceOutputDefinition(CodeRepr):
220
224
  force_direction=Vector3.from_ad_proto(proto.force.props.force_direction),
221
225
  moment_center=Vector3.from_ad_proto(proto.force.props.moment_center),
222
226
  porous=proto.force.props.porous,
227
+ moment_convention_type=MomentConventionType(proto.force.props.moment_convention_type),
223
228
  )
224
229
 
225
230
 
@@ -1776,6 +1776,9 @@ class DirectionSpecification(_IntEnum):
1776
1776
  Impose a flow direction normal to the inlet boundary toward the interior of the domain.
1777
1777
  DIRECTION_VECTOR
1778
1778
  Specify a vector for the inlet flow direction.
1779
+ CYLINDRICAL_DIRECTIONS
1780
+ Specify the inlet flow direction in a cylindrical coordinate system whose main axis
1781
+ is defined by the z axis of the inlet frame.
1779
1782
 
1780
1783
 
1781
1784
  Examples
@@ -1783,11 +1786,37 @@ class DirectionSpecification(_IntEnum):
1783
1786
  >>> from luminarycloud.params.enum import DirectionSpecification
1784
1787
  >>> DirectionSpecification.NORMAL_TO_BOUNDARY
1785
1788
  >>> DirectionSpecification.DIRECTION_VECTOR
1789
+ >>> DirectionSpecification.CYLINDRICAL_DIRECTIONS
1786
1790
  """
1787
1791
 
1788
1792
  INVALID = _clientpb.INVALID_DIRECTION_SPECIFICATION
1789
1793
  NORMAL_TO_BOUNDARY = _clientpb.NORMAL_TO_BOUNDARY
1790
1794
  DIRECTION_VECTOR = _clientpb.DIRECTION_VECTOR
1795
+ CYLINDRICAL_DIRECTIONS = _clientpb.CYLINDRICAL_DIRECTIONS
1796
+
1797
+
1798
+ class DirectionFrame(_IntEnum):
1799
+ """
1800
+ Frame used to define the flow direction.
1801
+
1802
+ Attributes
1803
+ ----------
1804
+ DIRECTION_FRAME_GLOBAL
1805
+ The direction vectors are defined by the global frame.
1806
+ DIRECTION_FRAME_BOUNDARY
1807
+ The direction vectors are defined by the frame to which the boundary surfaces are attached.
1808
+
1809
+
1810
+ Examples
1811
+ --------
1812
+ >>> from luminarycloud.params.enum import DirectionFrame
1813
+ >>> DirectionFrame.DIRECTION_FRAME_GLOBAL
1814
+ >>> DirectionFrame.DIRECTION_FRAME_BOUNDARY
1815
+ """
1816
+
1817
+ INVALID = _clientpb.INVALID_DIRECTION_FRAME
1818
+ DIRECTION_FRAME_GLOBAL = _clientpb.DIRECTION_FRAME_GLOBAL
1819
+ DIRECTION_FRAME_BOUNDARY = _clientpb.DIRECTION_FRAME_BOUNDARY
1791
1820
 
1792
1821
 
1793
1822
  class OutletPressureConstraint(_IntEnum):
@@ -40,7 +40,7 @@ class MonitorPlane(CodeRepr, ParamGroupWrapper[clientpb.MonitorPlane]):
40
40
  "Rotation vector of Euler angles (XYZ order) that transforms the box used to clip the monitor plane."
41
41
  enable_volume_clip: bool = False
42
42
  "Turn on or off the ability to constrain a monitor plane to specific volumes of the geometry."
43
- volumes: list[EntityIdentifier] = field(default_factory=_create_entity_identifier, init=True)
43
+ volumes: list[EntityIdentifier] = field(default_factory=list)
44
44
  "List of volumes used to clip the monitor plane."
45
45
 
46
46
  def _to_proto(self) -> clientpb.MonitorPlane:
@@ -32,7 +32,7 @@ class FanCurveInlet(Inlet):
32
32
  )
33
33
  "Method of defining the flow direction at the inlet."
34
34
  direction: Vector3 = field(default_factory=lambda: Vector3(1.0, 0.0, 0.0))
35
- "Vector (x,y,z) defining the flow direction. Automatically scaled to a unit vector internally."
35
+ "Vector (x,y,z) or (ρ,φ,z) defining the flow direction. Automatically scaled to a unit vector internally."
36
36
  fan_curve_table: RectilinearTable | None = None
37
37
  "Correlation between fan pressure rise and volume flow rate."
38
38
  head_loss_coefficient: LcFloat = 0.0
@@ -33,8 +33,10 @@ class MachInlet(Inlet):
33
33
  enum.DirectionSpecification.NORMAL_TO_BOUNDARY
34
34
  )
35
35
  "Method of defining the flow direction at the inlet."
36
+ direction_frame: enum.DirectionFrame = enum.DirectionFrame.DIRECTION_FRAME_GLOBAL
37
+ "Frame used to define the flow direction."
36
38
  direction: Vector3 = field(default_factory=lambda: Vector3(1.0, 0.0, 0.0))
37
- "Vector (x,y,z) defining the flow direction. Automatically scaled to a unit vector internally."
39
+ "Vector (x,y,z) or (ρ,φ,z) defining the flow direction. Automatically scaled to a unit vector internally."
38
40
 
39
41
  def _to_proto(self) -> clientpb.BoundaryConditionsFluid:
40
42
  _proto = super()._to_proto()
@@ -42,6 +44,7 @@ class MachInlet(Inlet):
42
44
  _proto.farfield_mach_number.CopyFrom(_to_ad_proto(self.mach_number))
43
45
  _proto.farfield_pressure.CopyFrom(_to_ad_proto(self.pressure))
44
46
  _proto.direction_specification = self.direction_specification.value
47
+ _proto.direction_frame = self.direction_frame.value
45
48
  _proto.flow_direction.CopyFrom(self.direction._to_ad_proto())
46
49
  return _proto
47
50
 
@@ -51,5 +54,6 @@ class MachInlet(Inlet):
51
54
  self.mach_number = _from_ad_proto(proto.farfield_mach_number)
52
55
  self.pressure = _from_ad_proto(proto.farfield_pressure)
53
56
  self.direction_specification = enum.DirectionSpecification(proto.direction_specification)
57
+ self.direction_frame = enum.DirectionFrame(proto.direction_frame)
54
58
  self.direction._from_ad_proto(proto.flow_direction)
55
59
  return None
@@ -31,14 +31,17 @@ class MassFlowInlet(Inlet):
31
31
  enum.DirectionSpecification.NORMAL_TO_BOUNDARY
32
32
  )
33
33
  "Method of defining the flow direction at the inlet."
34
+ direction_frame: enum.DirectionFrame = enum.DirectionFrame.DIRECTION_FRAME_GLOBAL
35
+ "Frame used to define the flow direction."
34
36
  direction: Vector3 = field(default_factory=lambda: Vector3(1.0, 0.0, 0.0))
35
- "Vector (x,y,z) defining the flow direction. Automatically scaled to a unit vector internally."
37
+ "Vector (x,y,z) or (ρ,φ,z) defining the flow direction. Automatically scaled to a unit vector internally."
36
38
 
37
39
  def _to_proto(self) -> clientpb.BoundaryConditionsFluid:
38
40
  _proto = super()._to_proto()
39
41
  _proto.inlet_momentum = clientpb.InletMomentum.MASS_FLOW_INLET
40
42
  _proto.mass_flow_rate.CopyFrom(_to_ad_proto(self.mass_flow_rate))
41
43
  _proto.direction_specification = self.direction_specification.value
44
+ _proto.direction_frame = self.direction_frame.value
42
45
  _proto.flow_direction.CopyFrom(self.direction._to_ad_proto())
43
46
  return _proto
44
47
 
@@ -47,5 +50,6 @@ class MassFlowInlet(Inlet):
47
50
  assert proto.inlet_momentum == clientpb.InletMomentum.MASS_FLOW_INLET
48
51
  self.mass_flow_rate = _from_ad_proto(proto.mass_flow_rate)
49
52
  self.direction_specification = enum.DirectionSpecification(proto.direction_specification)
53
+ self.direction_frame = enum.DirectionFrame(proto.direction_frame)
50
54
  self.direction._from_ad_proto(proto.flow_direction)
51
55
  return None
@@ -33,8 +33,10 @@ class TotalPressureInlet(Inlet):
33
33
  enum.DirectionSpecification.NORMAL_TO_BOUNDARY
34
34
  )
35
35
  "Method of defining the flow direction at the inlet."
36
+ direction_frame: enum.DirectionFrame = enum.DirectionFrame.DIRECTION_FRAME_GLOBAL
37
+ "Frame used to define the flow direction."
36
38
  direction: Vector3 = field(default_factory=lambda: Vector3(1.0, 0.0, 0.0))
37
- "Vector (x,y,z) defining the flow direction. Automatically scaled to a unit vector internally."
39
+ "Vector (x,y,z) or (ρ,φ,z) defining the flow direction. Automatically scaled to a unit vector internally."
38
40
 
39
41
  def _to_proto(self) -> clientpb.BoundaryConditionsFluid:
40
42
  _proto = super()._to_proto()
@@ -42,6 +44,7 @@ class TotalPressureInlet(Inlet):
42
44
  _proto.total_pressure.CopyFrom(_to_ad_proto(self.total_pressure))
43
45
  _proto.total_pressure_col.value = self.total_pressure_column_index
44
46
  _proto.direction_specification = self.direction_specification.value
47
+ _proto.direction_frame = self.direction_frame.value
45
48
  _proto.flow_direction.CopyFrom(self.direction._to_ad_proto())
46
49
  return _proto
47
50
 
@@ -51,5 +54,6 @@ class TotalPressureInlet(Inlet):
51
54
  self.total_pressure = _from_ad_proto(proto.total_pressure)
52
55
  self.total_pressure_column_index = proto.total_pressure_col.value
53
56
  self.direction_specification = enum.DirectionSpecification(proto.direction_specification)
57
+ self.direction_frame = enum.DirectionFrame(proto.direction_frame)
54
58
  self.direction._from_ad_proto(proto.flow_direction)
55
59
  return None
@@ -33,8 +33,10 @@ class VelocityMagnitudeInlet(Inlet):
33
33
  enum.DirectionSpecification.NORMAL_TO_BOUNDARY
34
34
  )
35
35
  "Method of defining the flow direction at the inlet."
36
+ direction_frame: enum.DirectionFrame = enum.DirectionFrame.DIRECTION_FRAME_GLOBAL
37
+ "Frame used to define the flow direction."
36
38
  direction: Vector3 = field(default_factory=lambda: Vector3(1.0, 0.0, 0.0))
37
- "Vector (x,y,z) defining the flow direction. Automatically scaled to a unit vector internally."
39
+ "Vector (x,y,z) or (ρ,φ,z) defining the flow direction. Automatically scaled to a unit vector internally."
38
40
  pressure: LcFloat = 101325
39
41
  "Static pressure at the boundary relative to the material reference pressure."
40
42
 
@@ -44,6 +46,7 @@ class VelocityMagnitudeInlet(Inlet):
44
46
  _proto.inlet_velocity_magnitude.CopyFrom(_to_ad_proto(self.velocity))
45
47
  _proto.inlet_velocity_magnitude_col.value = self.velocity_column_index
46
48
  _proto.direction_specification = self.direction_specification.value
49
+ _proto.direction_frame = self.direction_frame.value
47
50
  _proto.flow_direction.CopyFrom(self.direction._to_ad_proto())
48
51
  _proto.farfield_pressure.CopyFrom(_to_ad_proto(self.pressure))
49
52
  return _proto
@@ -54,6 +57,7 @@ class VelocityMagnitudeInlet(Inlet):
54
57
  self.velocity = _from_ad_proto(proto.inlet_velocity_magnitude)
55
58
  self.velocity_column_index = proto.inlet_velocity_magnitude_col.value
56
59
  self.direction_specification = enum.DirectionSpecification(proto.direction_specification)
60
+ self.direction_frame = enum.DirectionFrame(proto.direction_frame)
57
61
  self.direction._from_ad_proto(proto.flow_direction)
58
62
  self.pressure = _from_ad_proto(proto.farfield_pressure)
59
63
  return None
@@ -1,8 +1,8 @@
1
1
  # File: python/sdk/luminarycloud/inference/inference.py
2
2
  # Copyright 2025 Luminary Cloud, Inc. All Rights Reserved.
3
3
  from datetime import datetime
4
- from typing import Any, Callable
5
- from json import loads as json_loads
4
+ from typing import Any, Callable, Dict, Optional
5
+ from json import loads as json_loads, dumps as json_dumps
6
6
  from dataclasses import dataclass
7
7
  import base64
8
8
  import os
@@ -48,7 +48,12 @@ class ExtAeroInferenceResult:
48
48
 
49
49
 
50
50
  def external_aero_inference(
51
- project: Project, stl_file: str, checkpoint_file: str, config_name: str, stencil_size: int
51
+ project: Project,
52
+ stl_file: str,
53
+ artifact_url: str,
54
+ parameters: Optional[Dict[str, Any]] = None,
55
+ stencil_size: int = 1,
56
+ write_visualization_data=False,
52
57
  ) -> ExtAeroInferenceResult:
53
58
  """Performs an inference job returning external aerodynamic results.
54
59
  Parameters
@@ -57,12 +62,15 @@ def external_aero_inference(
57
62
  The project to which the inference files will be added.
58
63
  stl_file : str
59
64
  Fullpath the STL file to be used for inference.
60
- checkpoint_file : str
61
- Fullpath of the model to be used for inference.
62
- config_name :str
63
- Name of the configuration to be used for inference.
64
- stencil_size :int
65
- Size of the stencil to be used for inference.
65
+ artifact_url : str
66
+ Fullpath of the model artifact directory to be used for inference.
67
+ parameters : Dict[str, Any], optional
68
+ Dictionary of parameters to be passed to the inference service (e.g., alpha, beta, etc.).
69
+ stencil_size : int, optional
70
+ Size of the stencil to be used for inference. Defaults to 1.
71
+ write_visualization_data : bool, optional
72
+ Whether to write LC visualization data for visualization by Luminary.
73
+
66
74
 
67
75
  Returns
68
76
  ExtAeroInferenceResult
@@ -71,12 +79,19 @@ def external_aero_inference(
71
79
  warning:: This feature is experimental and may change or be removed without notice.
72
80
  """
73
81
 
74
- result = perform_inference(project, stl_file, checkpoint_file, config_name, stencil_size)
82
+ result = perform_inference(
83
+ project, stl_file, artifact_url, parameters, stencil_size, write_visualization_data
84
+ )
75
85
  return ExtAeroInferenceResult(result)
76
86
 
77
87
 
78
88
  def perform_inference(
79
- project: Project, stl_file: str, checkpoint_file: str, config_name: str, stencil_size: int
89
+ project: Project,
90
+ stl_file: str,
91
+ artifact_url: str,
92
+ parameters: Optional[Dict[str, Any]] = None,
93
+ stencil_size: int = 1,
94
+ write_visualization_data=False,
80
95
  ) -> dict[str, Any]:
81
96
  """Creates an inference service job.
82
97
  Parameters
@@ -85,12 +100,14 @@ def perform_inference(
85
100
  The project to which the inference files will be added.
86
101
  stl_file : str
87
102
  Fullpath the STL file to be used for inference.
88
- checkpoint_file : str
89
- Fullpath of the model to be used for inference.
90
- config_name :str
91
- Name of the configuration to be used for inference.
92
- stencil_size :int
93
- Size of the stencil to be used for inference.
103
+ artifact_url : str
104
+ Fullpath of the model artifact directory to be used for inference.
105
+ parameters : Dict[str, Any], optional
106
+ Dictionary of parameters to be passed to the inference service (e.g., alpha, beta, etc.).
107
+ stencil_size : int, optional
108
+ Size of the stencil to be used for inference. Defaults to 1.
109
+ write_visualization_data : bool, optional
110
+ Whether to write LC visualization data for visualization by Luminary.
94
111
 
95
112
 
96
113
  Returns
@@ -123,9 +140,10 @@ def perform_inference(
123
140
  return download_file
124
141
 
125
142
  stl_url = upload_if_file(stl_file)
126
- check_url = upload_if_file(checkpoint_file)
127
143
 
128
- raw = start_inference_job(project, stl_url, check_url, config_name, stencil_size)
144
+ raw = start_inference_job(
145
+ project, stl_url, artifact_url, parameters, stencil_size, write_visualization_data
146
+ )
129
147
  currated: dict[str, Any] = {}
130
148
  for k, v in raw.items():
131
149
  if isinstance(v, str) and v.startswith("https://"):
@@ -144,9 +162,10 @@ def perform_inference(
144
162
  def start_inference_job(
145
163
  project: Project,
146
164
  stl_url: str,
147
- checkpoint_url: str,
148
- config_name: str,
149
- stencil_size: int,
165
+ artifact_url: str,
166
+ parameters: Optional[Dict[str, Any]] = None,
167
+ stencil_size: int = 1,
168
+ write_visualization_data=False,
150
169
  ) -> dict[str, Any]:
151
170
  """Creates an inference service job.
152
171
  Parameters
@@ -155,12 +174,14 @@ def start_inference_job(
155
174
  Reference to a project.
156
175
  stl_url : str
157
176
  URL of the STL file to be used for inference.
158
- checkpoint_url : str
159
- URL of the model to be used for inference.
160
- config_name :str
161
- Name of the configuration to be used for inference.
162
- stencil_size :int
163
- Size of the stencil to be used for inference.
177
+ artifact_url : str
178
+ URL of the model artifact directory to be used for inference.
179
+ parameters : Dict[str, Any], optional
180
+ Dictionary of parameters to be passed to the inference service (e.g., alpha, beta, etc.).
181
+ stencil_size : int, optional
182
+ Size of the stencil to be used for inference. Defaults to 1.
183
+ write_visualization_data : bool, optional
184
+ Whether to write LC visualization data for visualization by Luminary.
164
185
 
165
186
 
166
187
  Returns
@@ -170,12 +191,18 @@ def start_inference_job(
170
191
  warning:: This feature is experimental and may change or be removed without notice.
171
192
  """
172
193
 
194
+ # Convert parameters dict to bytes if provided
195
+ parameters_bytes = b""
196
+ if parameters is not None:
197
+ parameters_bytes = json_dumps(parameters).encode("utf-8")
198
+
173
199
  req = inferencepb.CreateInferenceServiceJobRequest(
174
200
  stl_url=stl_url,
175
- checkpoint_url=checkpoint_url,
176
- config_name=config_name,
201
+ artifact_url=artifact_url,
202
+ parameters=parameters_bytes,
177
203
  stencil_size=stencil_size,
178
204
  project_id=project.id,
205
+ write_visualization_data=write_visualization_data,
179
206
  )
180
207
 
181
208
  res: inferencepb.CreateInferenceServiceJobResponse = (
@@ -33,3 +33,10 @@ from .arguments import (
33
33
  PipelineArgs as PipelineArgs,
34
34
  ArgNamedVariableSet as ArgNamedVariableSet,
35
35
  )
36
+
37
+ from .api import (
38
+ create_pipeline as create_pipeline,
39
+ list_pipelines as list_pipelines,
40
+ get_pipeline as get_pipeline,
41
+ create_pipeline_job as create_pipeline_job,
42
+ )