Geometry Upload and Import ========================== All simulations in the SimScale platform are built on top of a geometry model, and physics concepts such as material models, boundary conditions and interactions are assigned to geometrical elements such as volumes and faces. The geometrical model is defined via a CAD file. Some of the CAD formats supported in the platform include: * Parasolid * Solidworks * Inventor * Rinho * CATIA * ACIS * STEP * IGES * STL The full list can be found in the `documentation `_ For a CAD geometry to be available for simulation use via the SDK, a two-step process is performed: 1. Upload the CAD file to the platform storage 2. Import the stored file into the project After the geometry is imported to the project, it can be used to build a simulation on top of it. Uploading the CAD File ---------------------- In order to upload a CAD file to the platform, a ``storage`` is first created, by making use of the ``StorageApi`` module: .. code-block:: python import simscale_sdk as sim storage_api = sim.StorageApi(api_client) storage = storage_api.create_storage() Then we can read the CAD file stored locally and upload it with a ``PUT`` request. The ``URL`` for the request is available in the ``storage`` object: .. code-block:: python with open("pipe_junction_model_tutorial.x_t", "rb") as file: api_client.rest_client.PUT( url=storage.url, headers={ "Content-Type": "application/octet-stream" }, body=file.read() ) The CAD file for the tutorial can be downloaded from the following link: `Pipe Junction CAD Model `_ After the request is completed, the file is available in the SimScale's cloud storage and ready to be imported into a simulation project. For instance, the storage is identified by an ``UUID``: .. code-block:: python storage_id = storage.storage_id print(f"{storage_id=}") Importing the Geometry into the Project --------------------------------------- In order to deal with geometry data and the related operations, the SDK offers the ``GeometryImportRequest`` object and the ``GeometryImportsApi`` module. We first define the relevant data for the CAD file, because the platform still doesn't know about the format, name, import options, etc., of the file, and then use the ``GeometryImportsApi.import_geometry`` function call to start the import operation: .. code-block:: python import simscale_sdk as sim geometry_import_api = sim.GeometryImportsApi(api_client) geometry_import_req = sim.GeometryImportRequest( name="Geometry", location=sim.GeometryImportRequestLocation(storage_id), format="PARASOLID", input_unit="m", options=sim.GeometryImportRequestOptions( facet_split=False, sewing=False, improve=True, optimize_for_lbm_solver=False ), ) geometry_import = geometry_import_api.import_geometry(project_id, geometry_import_req) geometry_import_id = geometry_import.geometry_import_id The ``GeometryImportsApi.import_geometry`` method takes some time to complete its work, and is a non-blocking call because the action happens in the platform. In order to sync our code with the execution of the task, we create a loop to check the status of the operation at a given frequency, which is every 10 seconds in this example: .. code-block:: python import time while geometry_import.status not in ("FINISHED", "CANCELED", "FAILED"): geometry_import = geometry_import_api.get_geometry_import(project_id, geometry_import_id) time.sleep(10) Notice how the loop executes while the status is finsihed (successfuly), canceled or failed. An improved version of this snippet also adds a time-out check: .. code-block:: python import time GEOMETRY_IMPORT_TIMEOUT = 900 import_start = time.time() while geometry_import.status not in ("FINISHED", "CANCELED", "FAILED"): if time.time() > import_start + GEOMETRY_IMPORT_TIMEOUT: raise TimeoutError() geometry_import = geometry_import_api.get_geometry_import(project_id, geometry_import_id) time.sleep(10) When the loop exits, because the operation reaches one of the expected status, we can process the result, such as getting the id for the imported geometry: .. code-block:: python if geometry_import.status != "FINISHED": raise Exception("Geometry import operation was canceled or failed.") geometry_id = geometry_import.geometry_id print(f"{geometry_id=}") This is a common pattern that we will encounter on non-blocking operations that are launched with the API, but that we need to sync with because the results are to be used in suqsequent operations. Such cases would include mesh computation, simulation run execution, etc. Also, this loop is a great opportunity for async execution break points. If you are running multiple such operations in a parallel asyncio loop, instead of waiting some seconds on a blocking ``time.sleep()`` call, you can mark the hypervisor to switch tasks at this point. For instance, take a look at the following snippet: .. code-block:: python import asyncio async def async_import_geometry(geoemetry_import_req, project_id): # Do the preparation tasks and launch the import while geometry_import.status not in ("FINISHED", "CANCELED", "FAILED"): if time.time() > import_start + GEOMETRY_IMPORT_TIMEOUT: raise TimeoutError() geometry_import = geometry_import_api.get_geometry_import(project_id, geometry_import_id) await asyncio.sleep(10) return geometry_import.geometry_id