How to create a simulation#
This tutorial demonstrates how to create a simulation.
What is a simulation?#
A simulation contains selected sensors, sources to model ray-trace in space.
Prerequisites#
Perform imports#
[1]:
from pathlib import Path
from ansys.speos.core import Project, Speos, launcher
from ansys.speos.core.simulation import SimulationInteractive, SimulationInverse
Define constants#
The constants help ensure consistency and avoid repetition throughout the example.
[2]:
HOSTNAME = "localhost"
GRPC_PORT = 50098 # Be sure the Speos GRPC Server has been started on this port.
USE_DOCKER = True # Set to False if you're running this example locally as a Notebook.
SOURCE_NAME = "Surface.1"
SENSOR_NAME = "Irradiance.1"
Model Setup#
Load assets#
The assets used to run this example are available in the PySpeos repository on GitHub.
Note: Make sure you have downloaded simulation assets and set
assets_data_path
to point to the assets folder.
[3]:
if USE_DOCKER: # Running on the remote server.
assets_data_path = Path("/app") / "assets"
else:
assets_data_path = Path("/path/to/your/download/assets/directory")
Connect to the RPC Server#
This Python client connects to a server where the Speos engine is running as a service. In this example, the server and client are the same machine. The launch_local_speos_rpc_method can be used to start a local instance of the service..
[4]:
if USE_DOCKER:
speos = Speos(host=HOSTNAME, port=GRPC_PORT)
else:
speos = launcher.launch_local_speos_rpc_server(port=GRPC_PORT)
Create a new project#
The only way to create a simulation using the core layer, is to create it from a project. The Project
class is instantiated by passing a Speos
instance.
[5]:
p = Project(speos=speos)
print(p)
{
"name": "",
"description": "",
"metadata": {},
"part_guid": "",
"sources": [],
"sensors": [],
"simulations": [],
"materials": [],
"scenes": []
}
Prepare prerequisites#
Create the necessary elements for a simulation: Sensor, source, root part, optical property are prerequisites.
Prepare the root part#
[6]:
root_part = p.create_root_part()
body_1 = root_part.create_body(name="Body.1")
face_1 = (
body_1.create_face(name="Face.1")
.set_vertices([0, 1, 2, 0, 2, 2, 1, 2, 2])
.set_facets([0, 1, 2])
.set_normals([0, 0, 1, 0, 0, 1, 0, 0, 1])
)
root_part.commit()
[6]:
<ansys.speos.core.part.Part at 0x7f86805854e0>
Prepare an optical property#
Create Optical Property
[7]:
opt_prop = p.create_optical_property("Material.1")
opt_prop.set_volume_opaque().set_surface_mirror()
[7]:
<ansys.speos.core.opt_prop.OptProp at 0x7f8680586830>
Choose the geometry for this optical property : Body.1
[8]:
opt_prop.set_geometries(geometries=[body_1])
opt_prop.commit()
[8]:
<ansys.speos.core.opt_prop.OptProp at 0x7f8680586830>
Prepare an irradiance sensor#
[9]:
sensor1 = p.create_sensor(name=SENSOR_NAME)
# set type to colorimetric or spectral so that the sensor can be used both in
# direct and inverse simulation
sensor1.set_type_colorimetric()
sensor1.commit()
[9]:
<ansys.speos.core.sensor.SensorIrradiance at 0x7f8680586230>
Prepare a surface source#
[10]:
source1 = p.create_source(name=SOURCE_NAME)
source1.set_exitance_constant(geometries=[(face_1, True)])
# define a spectrum which is not monochromatic so it can be used in both direct and inverse
# simulation
source1.set_spectrum().set_blackbody()
source1.commit()
/home/runner/work/pyspeos/pyspeos/.venv/lib/python3.10/site-packages/ansys/speos/core/project.py:200: UserWarning: The pySpeos feature : SourceSurface needs a Speos Version of 2025 R2 SP0 or higher.
feature = SourceSurface(
[10]:
<ansys.speos.core.source.SourceSurface at 0x7f8680587ac0>
Create a simulation#
[11]:
simulation1 = p.create_simulation(name="Simulation.1")
simulation1.set_sensor_paths([SENSOR_NAME]).set_source_paths([SOURCE_NAME])
print(simulation1)
simulation1.commit()
print(simulation1)
local: {
"name": "Simulation.1",
"sensor_paths": [
"Irradiance.1"
],
"source_paths": [
"Surface.1"
],
"description": "",
"metadata": {},
"simulation_guid": "",
"simulation": {
"direct_mc_simulation_template": {
"geom_distance_tolerance": 0.01,
"max_impact": 100,
"weight": {
"minimum_energy_percentage": 0.005
},
"dispersion": true,
"colorimetric_standard": "CIE_1931",
"fast_transmission_gathering": false,
"ambient_material_uri": "",
"stop_condition_rays_number": "200000",
"automatic_save_frequency": 1800
},
"name": "Simulation.1",
"description": "",
"metadata": {},
"scene_guid": "7f3702cd-d431-4cb8-bb42-4dcdfc736939",
"simulation_path": "Simulation.1",
"job_type": "CPU"
}
}
{
"name": "Simulation.1",
"metadata": {
"UniqueId": "474e3285-7f1d-4e24-bf77-8cd51a428dae"
},
"simulation_guid": "210564ec-2fe5-47af-bb5c-a4ddd8d09302",
"sensor_paths": [
"Irradiance.1"
],
"source_paths": [
"Surface.1"
],
"description": "",
"simulation": {
"direct_mc_simulation_template": {
"geom_distance_tolerance": 0.01,
"max_impact": 100,
"weight": {
"minimum_energy_percentage": 0.005
},
"dispersion": true,
"colorimetric_standard": "CIE_1931",
"fast_transmission_gathering": false,
"ambient_material_uri": "",
"stop_condition_rays_number": "200000",
"automatic_save_frequency": 1800
},
"name": "Simulation.1",
"description": "",
"metadata": {},
"scene_guid": "7f3702cd-d431-4cb8-bb42-4dcdfc736939",
"simulation_path": "Simulation.1",
"job_type": "CPU"
}
}
/home/runner/work/pyspeos/pyspeos/.venv/lib/python3.10/site-packages/ansys/speos/core/project.py:280: UserWarning: The pySpeos feature : SimulationDirect needs a Speos Version of 2025 R2 SP0 or higher.
feature = SimulationDirect(
/home/runner/work/pyspeos/pyspeos/.venv/lib/python3.10/site-packages/ansys/speos/core/simulation.py:622: UserWarning: Please note that setting a value for light expert option forces a sensorcommit when committing the Simulation class
self.set_light_expert()
Set simulation characteristics#
Simulation is defined with the same default values as the GUI speos.
If the user would like to modify the simulation characteristics, it is possible to do so by setting the simulation characteristics as below.
[12]:
simulation2_direct = p.create_simulation(name="Simulation.2")
simulation2_direct.set_ambient_material_file_uri(
uri=str(assets_data_path / "AIR.material")
).set_colorimetric_standard_CIE_1964().set_weight_none().set_geom_distance_tolerance(
0.01
).set_max_impact(200).set_dispersion(False)
simulation2_direct.set_sensor_paths([SENSOR_NAME]).set_source_paths([SOURCE_NAME]).commit()
print(simulation2_direct)
{
"name": "Simulation.2",
"metadata": {
"UniqueId": "6e5917fa-94d3-428b-9dc7-e09770880222"
},
"simulation_guid": "70524f24-9f2e-4ec6-bfe5-811ae64a464d",
"sensor_paths": [
"Irradiance.1"
],
"source_paths": [
"Surface.1"
],
"description": "",
"simulation": {
"direct_mc_simulation_template": {
"geom_distance_tolerance": 0.01,
"max_impact": 200,
"colorimetric_standard": "CIE_1964",
"ambient_material_uri": "/app/assets/AIR.material",
"dispersion": false,
"fast_transmission_gathering": false,
"stop_condition_rays_number": "200000",
"automatic_save_frequency": 1800
},
"name": "Simulation.2",
"description": "",
"metadata": {},
"scene_guid": "7f3702cd-d431-4cb8-bb42-4dcdfc736939",
"simulation_path": "Simulation.2",
"job_type": "CPU"
}
}
Read information#
Read simulation information
[13]:
print(simulation1)
{
"name": "Simulation.1",
"metadata": {
"UniqueId": "474e3285-7f1d-4e24-bf77-8cd51a428dae"
},
"simulation_guid": "210564ec-2fe5-47af-bb5c-a4ddd8d09302",
"sensor_paths": [
"Irradiance.1"
],
"source_paths": [
"Surface.1"
],
"description": "",
"simulation": {
"direct_mc_simulation_template": {
"geom_distance_tolerance": 0.01,
"max_impact": 100,
"weight": {
"minimum_energy_percentage": 0.005
},
"dispersion": true,
"colorimetric_standard": "CIE_1931",
"fast_transmission_gathering": false,
"ambient_material_uri": "",
"stop_condition_rays_number": "200000",
"automatic_save_frequency": 1800
},
"name": "Simulation.1",
"description": "",
"metadata": {},
"scene_guid": "7f3702cd-d431-4cb8-bb42-4dcdfc736939",
"simulation_path": "Simulation.1",
"job_type": "CPU"
}
}
Read project information
[14]:
print(p)
{
"part_guid": "e5dd3c2f-d357-43d2-ae31-a826abdbb0f1",
"sources": [
{
"name": "Surface.1",
"metadata": {
"UniqueId": "43c10260-630c-4f63-b18f-86cc2151f8e6"
},
"source_guid": "36a9bb0d-b8a3-46b3-9c4a-f9c9890672a4",
"description": "",
"source": {
"name": "Surface.1",
"surface": {
"luminous_flux": {
"luminous_value": 683.0
},
"intensity_guid": "3b8e928a-d3c3-454f-8e82-07b07bb20c08",
"exitance_constant": {
"geo_paths": [
{
"geo_path": "Body.1/Face.1",
"reverse_normal": true
}
]
},
"spectrum_guid": "da6c512d-60ba-43df-a9ee-0c7cc8a66d87",
"intensity": {
"name": "Surface.1.Intensity",
"cos": {
"N": 1.0,
"total_angle": 180.0
},
"description": "",
"metadata": {}
},
"spectrum": {
"name": "Surface.1.Spectrum",
"blackbody": {
"temperature": 2856.0
},
"description": "",
"metadata": {}
}
},
"description": "",
"metadata": {}
}
}
],
"sensors": [
{
"name": "Irradiance.1",
"metadata": {
"UniqueId": "5bfa854f-3830-4475-9f5d-e09fa3ffa8c7"
},
"sensor_guid": "22a4eafc-2516-42d5-af07-1592c8f6d529",
"description": "",
"result_file_name": "",
"sensor": {
"irradiance_sensor_template": {
"sensor_type_colorimetric": {
"wavelengths_range": {
"w_start": 400.0,
"w_end": 700.0,
"w_sampling": 13
}
},
"illuminance_type_planar": {},
"dimensions": {
"x_start": -50.0,
"x_end": 50.0,
"x_sampling": 100,
"y_start": -50.0,
"y_end": 50.0,
"y_sampling": 100
},
"axis_system": [
0.0,
0.0,
0.0,
1.0,
0.0,
0.0,
0.0,
1.0,
0.0,
0.0,
0.0,
1.0
],
"layer_type_none": {},
"ray_file_type": "RayFileNone",
"integration_direction": []
},
"name": "Irradiance.1",
"description": "",
"metadata": {}
}
}
],
"simulations": [
{
"name": "Simulation.1",
"metadata": {
"UniqueId": "474e3285-7f1d-4e24-bf77-8cd51a428dae"
},
"simulation_guid": "210564ec-2fe5-47af-bb5c-a4ddd8d09302",
"sensor_paths": [
"Irradiance.1"
],
"source_paths": [
"Surface.1"
],
"description": "",
"simulation": {
"direct_mc_simulation_template": {
"geom_distance_tolerance": 0.01,
"max_impact": 100,
"weight": {
"minimum_energy_percentage": 0.005
},
"dispersion": true,
"colorimetric_standard": "CIE_1931",
"fast_transmission_gathering": false,
"ambient_material_uri": "",
"stop_condition_rays_number": "200000",
"automatic_save_frequency": 1800
},
"name": "Simulation.1",
"description": "",
"metadata": {},
"scene_guid": "7f3702cd-d431-4cb8-bb42-4dcdfc736939",
"simulation_path": "Simulation.1",
"job_type": "CPU"
}
},
{
"name": "Simulation.2",
"metadata": {
"UniqueId": "6e5917fa-94d3-428b-9dc7-e09770880222"
},
"simulation_guid": "70524f24-9f2e-4ec6-bfe5-811ae64a464d",
"sensor_paths": [
"Irradiance.1"
],
"source_paths": [
"Surface.1"
],
"description": "",
"simulation": {
"direct_mc_simulation_template": {
"geom_distance_tolerance": 0.01,
"max_impact": 200,
"colorimetric_standard": "CIE_1964",
"ambient_material_uri": "/app/assets/AIR.material",
"dispersion": false,
"fast_transmission_gathering": false,
"stop_condition_rays_number": "200000",
"automatic_save_frequency": 1800
},
"name": "Simulation.2",
"description": "",
"metadata": {},
"scene_guid": "7f3702cd-d431-4cb8-bb42-4dcdfc736939",
"simulation_path": "Simulation.2",
"job_type": "CPU"
}
}
],
"materials": [
{
"name": "Material.1",
"metadata": {
"UniqueId": "18987061-5008-484f-9cb7-74d7e6177531"
},
"vop_guid": "d5c66ab4-0b92-4394-9c2a-e7b61ba40b69",
"sop_guids": [
"4a17cb20-b1a9-44b3-b04b-2d67a25fc341"
],
"geometries": {
"geo_paths": [
"Body.1"
]
},
"description": "",
"vop": {
"name": "Material.1.VOP",
"opaque": {},
"description": "",
"metadata": {}
},
"sops": [
{
"name": "Material.1.SOP",
"mirror": {
"reflectance": 100.0
},
"description": "",
"metadata": {}
}
]
}
],
"name": "",
"description": "",
"metadata": {},
"scenes": []
}
Update simulation settings#
If you are manipulating a simulation already committed, remember to commit your changes.
If you don’t, you will still only watch what is committed on the server.
[15]:
simulation1.set_ambient_material_file_uri(uri=str(assets_data_path / "AIR.material"))
simulation1.commit()
print(simulation1)
{
"name": "Simulation.1",
"metadata": {
"UniqueId": "474e3285-7f1d-4e24-bf77-8cd51a428dae"
},
"simulation_guid": "210564ec-2fe5-47af-bb5c-a4ddd8d09302",
"sensor_paths": [
"Irradiance.1"
],
"source_paths": [
"Surface.1"
],
"description": "",
"simulation": {
"direct_mc_simulation_template": {
"geom_distance_tolerance": 0.01,
"max_impact": 100,
"weight": {
"minimum_energy_percentage": 0.005
},
"dispersion": true,
"ambient_material_uri": "/app/assets/AIR.material",
"colorimetric_standard": "CIE_1931",
"fast_transmission_gathering": false,
"stop_condition_rays_number": "200000",
"automatic_save_frequency": 1800
},
"name": "Simulation.1",
"description": "",
"metadata": {},
"scene_guid": "7f3702cd-d431-4cb8-bb42-4dcdfc736939",
"simulation_path": "Simulation.1",
"job_type": "CPU"
}
}
Reset#
Possibility to reset local values from the one available in the server.
[16]:
simulation1.set_max_impact(1000) # adjust max impact but no commit
simulation1.reset() # reset -> this will apply the server value to the local value
simulation1.delete() # delete (to display the local value with the below print)
print(simulation1)
local: {
"name": "Simulation.1",
"sensor_paths": [
"Irradiance.1"
],
"source_paths": [
"Surface.1"
],
"description": "",
"metadata": {},
"simulation_guid": "",
"simulation": {
"direct_mc_simulation_template": {
"geom_distance_tolerance": 0.01,
"max_impact": 100,
"weight": {
"minimum_energy_percentage": 0.005
},
"dispersion": true,
"ambient_material_uri": "/app/assets/AIR.material",
"colorimetric_standard": "CIE_1931",
"fast_transmission_gathering": false,
"stop_condition_rays_number": "200000",
"automatic_save_frequency": 1800
},
"name": "Simulation.1",
"description": "",
"metadata": {},
"scene_guid": "7f3702cd-d431-4cb8-bb42-4dcdfc736939",
"simulation_path": "Simulation.1",
"job_type": "CPU"
}
}
Other simulation examples#
Inverse simulation#
[17]:
simulation3 = p.create_simulation(name="Simulation.3", feature_type=SimulationInverse)
simulation3.set_sensor_paths(sensor_paths=[SENSOR_NAME]).set_source_paths(
source_paths=[SOURCE_NAME]
).commit()
print(simulation3)
/home/runner/work/pyspeos/pyspeos/.venv/lib/python3.10/site-packages/ansys/speos/core/project.py:287: UserWarning: The pySpeos feature : SimulationInverse needs a Speos Version of 2025 R2 SP0 or higher.
feature = SimulationInverse(
{
"name": "Simulation.3",
"metadata": {
"UniqueId": "a800c7b8-6811-4ddc-8022-c0dd3bff9b12"
},
"simulation_guid": "47cfccb0-17c6-4afb-922a-ff083559ec54",
"sensor_paths": [
"Irradiance.1"
],
"source_paths": [
"Surface.1"
],
"description": "",
"simulation": {
"inverse_mc_simulation_template": {
"geom_distance_tolerance": 0.01,
"max_impact": 100,
"weight": {
"minimum_energy_percentage": 0.005
},
"number_of_gathering_rays_per_source": 1,
"colorimetric_standard": "CIE_1931",
"dispersion": false,
"splitting": false,
"maximum_gathering_error": 0,
"maximum_gathering_error_percentage": 0.0,
"fast_transmission_gathering": false,
"ambient_material_uri": "",
"optimized_propagation_none": {
"stop_condition_passes_number": 5
},
"automatic_save_frequency": 1800
},
"name": "Simulation.3",
"description": "",
"metadata": {},
"scene_guid": "7f3702cd-d431-4cb8-bb42-4dcdfc736939",
"simulation_path": "Simulation.3",
"job_type": "CPU"
}
}
Interactive simulation#
[18]:
simulation4 = p.create_simulation(name="Simulation.4", feature_type=SimulationInteractive)
simulation4.set_source_paths(source_paths=[SOURCE_NAME]).commit()
print(simulation4)
{
"name": "Simulation.4",
"metadata": {
"UniqueId": "bf3256c2-9d37-413e-8df5-506974d6cb15"
},
"simulation_guid": "3ea1266c-74dd-43eb-adb3-52f57e0cd7e9",
"source_paths": [
"Surface.1"
],
"description": "",
"sensor_paths": [],
"simulation": {
"name": "Simulation.4",
"interactive_simulation_template": {
"geom_distance_tolerance": 0.01,
"max_impact": 100,
"weight": {
"minimum_energy_percentage": 0.005
},
"colorimetric_standard": "CIE_1931",
"ambient_material_uri": "",
"rays_number_per_sources": [],
"light_expert": false,
"impact_report": false
},
"description": "",
"metadata": {},
"scene_guid": "7f3702cd-d431-4cb8-bb42-4dcdfc736939",
"simulation_path": "Simulation.4",
"job_type": "CPU"
}
}
[19]:
speos.close()
[19]:
True