Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
0f11fee
Pushed draft branch for thermic source
ansmcailler Jul 2, 2025
87864cb
Merge branch 'main' into feat/thermicsource
Jul 2, 2025
9debcf0
Merge branch 'main' into MCR_thermicsource
pluAtAnsys Jul 2, 2025
ddf82a6
ci: auto fixes from pre-commit.com hooks.
pre-commit-ci[bot] Jul 2, 2025
a12a993
Merge remote-tracking branch 'origin/MCR_thermicsource' into feat/the…
Jul 2, 2025
5f00348
Re-adding full project.py script
ansmcailler Jul 2, 2025
5466a49
ci: auto fixes from pre-commit.com hooks.
pre-commit-ci[bot] Jul 2, 2025
6c6d0d7
chore: adding changelog file 651.added.md [dependabot-skip]
pyansys-ci-bot Jul 2, 2025
3a9263d
run pre-commit to add missing docstring
Jul 2, 2025
dcbb88a
refactor the test code into example as temp location.
Jul 2, 2025
fd1f665
Merge remote-tracking branch 'origin/feat/thermicsource' into feat/th…
Jul 2, 2025
7de324e
add key to the Intensity class to be filled
Jul 3, 2025
ee721b9
remove no need to check if it is temperature field
Jul 3, 2025
76274b5
Fix issue with intensity template
echambla Jul 3, 2025
e5f8132
property and setter method
Jul 3, 2025
81f0f61
add unittest
Jul 3, 2025
5ebe14b
add example
Jul 3, 2025
ff25390
improve the unittest coverage
Jul 3, 2025
8092f7e
Merge branch 'main' into feat/thermicsource
pluAtAnsys Jul 4, 2025
54501ef
Merge branch 'main' into feat/thermicsource
pluAtAnsys Jul 7, 2025
a0c6f78
Merge branch 'main' into feat/thermicsource
pluAtAnsys Jul 7, 2025
47f7a83
Merge branch 'main' into feat/thermicsource
pluAtAnsys Jul 9, 2025
2e8be76
Merge branch 'main' into feat/thermicsource
pluAtAnsys Jul 30, 2025
9b60e42
Merge branch 'main' into feat/thermicsource
pluAtAnsys Aug 4, 2025
ff5d345
Finalized thermic source basic development (incl unit test)
ansmcailler Sep 5, 2025
2855c91
ci: auto fixes from pre-commit.com hooks.
pre-commit-ci[bot] Sep 5, 2025
ae44b32
chore: adding changelog file 651.added.md [dependabot-skip]
pyansys-ci-bot Sep 5, 2025
4e60a56
Merge branch 'main' into feat/thermicsource
pluAtAnsys Sep 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/changelog.d/651.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add thermic source
17 changes: 17 additions & 0 deletions examples/core/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
SourceLuminaire,
SourceRayFile,
SourceSurface,
SourceThermic,
)

# -
Expand Down Expand Up @@ -254,6 +255,22 @@ def create_face(body):
source5.delete()
# -

# ### Thermic source

# +
source6 = p.create_source(name="Thermic.1", feature_type=SourceThermic)
source6.set_emissive_faces(geometries=[(GeoRef.from_native_link("TheBodyB/TheFaceF"), False)])
print(source6)

source6.commit()
print(source6)
# -

# +
source6.delete()
# -


# When creating sources, this creates some intermediate objects (spectrums, intensity templates).
#
# Deleting a source does not delete in cascade those objects
Expand Down
22 changes: 20 additions & 2 deletions src/ansys/speos/core/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
SourceLuminaire,
SourceRayFile,
SourceSurface,
SourceThermic,
)
from ansys.speos.core.speos import Speos

Expand Down Expand Up @@ -158,7 +159,9 @@ def create_source(
description: str = "",
feature_type: type = SourceSurface,
metadata: Optional[Mapping[str, str]] = None,
) -> Union[SourceSurface, SourceRayFile, SourceLuminaire, SourceAmbientNaturalLight]:
) -> Union[
SourceSurface, SourceRayFile, SourceLuminaire, SourceAmbientNaturalLight, SourceThermic
]:
"""Create a new Source feature.

Parameters
Expand Down Expand Up @@ -224,9 +227,16 @@ def create_source(
description=description,
metadata=metadata,
)
case "SourceThermic":
feature = SourceThermic(
project=self,
name=name,
description=description,
metadata=metadata,
)
case _:
msg = "Requested feature {} does not exist in supported list {}".format(
feature_type, [SourceSurface, SourceLuminaire, SourceRayFile]
feature_type, [SourceSurface, SourceLuminaire, SourceRayFile, SourceThermic]
)
raise TypeError(msg)
self._features.append(feature)
Expand Down Expand Up @@ -438,6 +448,7 @@ def find(
SourceSurface,
SourceLuminaire,
SourceRayFile,
SourceThermic,
SensorIrradiance,
SensorRadiance,
SensorCamera,
Expand Down Expand Up @@ -815,6 +826,13 @@ def _fill_features(self):
source_instance=src_inst,
default_values=False,
)
elif src_inst.HasField("thermic_properties"):
src_feat = SourceThermic(
project=self,
name=src_inst.name,
source_instance=src_inst,
default_values=False,
)
if src_feat is not None:
self._features.append(src_feat)

Expand Down
238 changes: 238 additions & 0 deletions src/ansys/speos/core/source.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
from ansys.speos.core.kernel.client import SpeosClient
from ansys.speos.core.kernel.scene import ProtoScene
from ansys.speos.core.kernel.source_template import ProtoSourceTemplate
from ansys.speos.core.opt_prop import OptProp
from ansys.speos.core.spectrum import Spectrum


Expand Down Expand Up @@ -1255,6 +1256,243 @@ def delete(self) -> SourceSurface:
return self


class SourceThermic(BaseSource):
"""ThermicSource.

By default, a flux from intensity file is chosen, with an incandescent spectrum.

Parameters
----------
project : ansys.speos.core.project.Project
Project that will own the feature.
name : str
Name of the feature.
description : str
Description of the feature.
By default, ``""``.
metadata : Optional[Mapping[str, str]]
Metadata of the feature.
By default, ``{}``.
default_values : bool
Uses default values when True.
"""

def __init__(
self,
project: project.Project,
name: str,
description: str = "",
metadata: Optional[Mapping[str, str]] = None,
source_instance: Optional[ProtoScene.SourceInstance] = None,
default_values: bool = True,
) -> None:
if metadata is None:
metadata = {}

super().__init__(
project=project,
name=name,
description=description,
metadata=metadata,
source_instance=source_instance,
)
self._speos_client = self._project.client
self._name = name

self._intensity = Intensity(
speos_client=self._speos_client,
name=name + ".Intensity",
key=self._source_template.thermic.intensity_guid,
)

self._sop = OptProp(
project=self._project,
name=self._name,
)

if default_values:
self.set_emissive_faces(geometries=[])
self.emissive_faces_temperature = 2000
self._sop.set_surface_mirror(0)

def set_emissive_faces(
self, geometries: List[tuple[Union[GeoRef, face.Face, body.Body], bool]]
) -> SourceThermic:
"""Set emssive faces for thermic source.

Parameters
----------
geometries : List[tuple[ansys.speos.core.geo_ref.GeoRef, bool]]
List of (face, reverseNormal).

Returns
-------
ansys.speos.core.source.SourceThermic
Thermic source.
"""
self._source_instance.thermic_properties.emissive_faces_properties.ClearField("geo_paths")
if geometries != []:
my_list = [
ProtoScene.GeoPath(geo_path=gr.to_native_link(), reverse_normal=reverse_normal)
for (gr, reverse_normal) in geometries
]
self._source_instance.thermic_properties.emissive_faces_properties.geo_paths.extend(
my_list
)
self._source_template.thermic.emissives_faces.SetInParent()
return self

@property
def emissive_faces_temperature(self) -> float:
"""Get temperature settings for emissive faces.

Returns
-------
float
temperature settings for emissive faces.

"""
if self._source_template.thermic.HasField("emissives_faces"):
return self._source_template.thermic.emissives_faces.temperature
else:
raise AttributeError("This feature is not defined as emissive faces.")

@emissive_faces_temperature.setter
def emissive_faces_temperature(self, value: float) -> None:
"""Set temperature settings for emissive faces.

Parameters
----------
value: float
temperature settings for emissive faces.

Returns
-------
None

"""
self._source_template.thermic.emissives_faces.temperature = value

def set_temperature_field(self) -> SourceThermic:
"""Set thermic source in temperature field mode.

Parameters
----------
None

Returns
-------
ansys.speos.core.source.SourceThermic
Thermic source.
"""
if not self._source_template.thermic.HasField("temperature_field"):
self._source_template.thermic.temperature_field.SetInParent()
if self._source_instance.thermic_properties.temperature_field_properties.axis_plane is None:
axis_plane = [0, 0, 0, 1, 0, 0, 0, 1, 0]
self._source_instance.thermic_properties.temperature_field_properties.axis_plane[:] = (
axis_plane
)
return self

@property
def temperature_field_uri(self) -> str:
"""Get temperature field file uri.

Returns
-------
string
temperature field file uri.

"""
if self._source_template.thermic.HasField("temperature_field"):
return self._source_template.thermic.temperature_field.temperature_field_uri
else:
raise AttributeError("This feature is not defined with temperature field.")

def set_temperature_field_uri(self, file: str) -> None:
"""Set temperature field file path.

Parameters
----------
file: str
temperature field file path.

Returns
-------
None

"""
self._source_template.thermic.temperature_field.temperature_field_uri = file

@property
def sop(self) -> OptProp:
"""Get SOP for thermic source in temperature field mode.

Returns
-------
ansys.speos.core.opt_prop.OptProp
Surface Optical property.

"""
if self._source_template.thermic.HasField("temperature_field"):
return self._sop
else:
raise AttributeError("This feature is not defined with temperature field.")

@sop.setter
def sop(self, new_sop: OptProp) -> None:
"""Set SOP for thermic source in temperature field mode.

Parameters
----------
ansys.speos.core.opt_prop.OptProp
Surface Optical property.

Returns
-------
None

"""
self._sop = new_sop
self._source_template.thermic.temperature_field.sop_guid = self._sop.sop_template_link.key

def commit(self) -> SourceThermic:
"""Save feature: send the local data to the speos server database.

Returns
-------
ansys.speos.core.source.SourceThermic
Thermic source feature.
"""
# intensity
self._intensity.commit()
self._source_template.thermic.intensity_guid = self._intensity.intensity_template_link.key

# sop
if self._source_template.thermic.HasField("temperature_field"):
self._sop.commit()
self._source_template.thermic.temperature_field.sop_guid = (
self._sop.sop_template_link.key
)

# source base
super().commit()
return self

def reset(self) -> SourceThermic:
"""Reset feature: override local data by the one from the speos server database.

Returns
-------
ansys.speos.core.source.SourceThermic
Thermic source feature.
"""
self._intensity.reset()
# source base
super().reset()
return self


class BaseSourceAmbient(BaseSource):
"""
Super Class for ambient sources.
Expand Down
Loading
Loading