4.1. Cloud assets#
Cloud assets refer to geometry, mesh and cases that have been uploaded to/generated in the cloud. User can use the IDs of existing cloud assets to reference them and interact with them.
Referencing existing cloud assets#
existing_cloud_project = fl.Project.from_cloud("prj-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
existing_cloud_geometry = fl.Geometry.from_cloud("geo-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
existing_cloud_volume_mesh = fl.VolumeMesh.from_cloud("vm-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
existing_cloud_case = fl.Case.from_cloud("case-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
Accessing the entities within cloud assets#
For Geometry, VolumeMesh assets, user can access the entities within them by using the entity name. A full list of entities contained within each type of cloud asset is shown below:
Geometry
Grouped faces
Grouped edges
VolumeMesh
Boundaries
Volume zones
For example when specifying the Wall
boundary condition, user can access the boundaries in the above existing_cloud_volume_mesh
by:
wall = fl.Wall(
name="Wall",
entities=[
existing_cloud_volume_mesh["leftWing"],
existing_cloud_volume_mesh["rightWing"],
],
)
which will select both the leftWing
and rightWing
boundaries in the volume mesh.
Note
Before selecting entities in Geometry
, user needs to specify grouping tags for faces and edges. See below for more information.
We also support naming pattern with wildcard/regular expression for selecting entities. For example, let’s say the existing_cloud_volume_mesh
has the following boundaries and zones:
Boundaries:
leftWing
rightWing
fuselage
farfield
Volume zones:
ZoneWithWing
Farfield
User can achieve the same operation as above by:
wall = fl.Wall(
name="Wall",
entities=[
existing_cloud_volume_mesh["*Wing"],
],
)
which will use wildcard to automatically match all the entities with that naming pattern. This results in the following entities being selected:
Boundaries:
leftWing
rightWing
Volume zones:
ZoneWithWing
However since the Wall.entities
in Wall
knows it only accepts surface-type entities. The ZoneWithWing
will be automatically filtered out, resulting in only the leftWing
and rightWing
being selected.
Therefore if the user wants SurfaceOutput
for all the boundaries, the user can do:
wall = fl.SurfaceOutput(
name="OutputOnAllBCs",
entities=[
existing_cloud_volume_mesh["*"],
],
output_fields=["Cp"],
)
which will dump outputs on all the boundaries (leftWing
, rightWing
, fuselage
, farfield
).
Project#
Project serves as the container of all generated cloud assets (like the surface meshes, volume meshes and cases) that share the same root asset. It also is the interface for user to generate new cloud assets. For example forking an existing case to create a new case. An illustration of the content of project (also known as the “Project Tree”) is shown below:
graph TD subgraph Project["Project"] Geometry["Geometry"] SurfaceMesh1["SurfaceMesh 1"] SurfaceMesh2["SurfaceMesh 2"] VolumeMesh1["VolumeMesh 1"] VolumeMesh2["VolumeMesh 2"] Case1["Case 1"] Case2["Case 2"] Case3["Case 3"] Geometry --> SurfaceMesh1 Geometry --> SurfaceMesh2 SurfaceMesh1 --> VolumeMesh1 SurfaceMesh1 --> VolumeMesh2 VolumeMesh1 --> Case1 VolumeMesh2 --> Case2 Case2 --> Case3 end
Create a project#
Project can be created by uploading a geometry or a volume mesh which will become the root asset of the project. Currently we do not support creating project from a surface mesh file.
graph TD Geometry -->|upload and creates| Project VolumeMesh -->|upload and creates| Project
To create a project from a geometry or a volume mesh with PythonAPI:
project_from_geometry = fl.Project.from_file(
"my_geometry.csm", name="Project from geometry"
)
project_from_geometry = fl.Project.from_file(
"my_volume_mesh.cgns", name="Project from volume mesh"
)
Creating new cloud assets from a project#
Once the project is created user can use the project and creates new cloud assets via the project. For example, if I want to run a case from “my_geometry.csm”, I can do the following:
project_from_geometry.run_case(my_params, name="my new case")
where my_params
is a SimulationParams
instance. This new case will be associated with the project.
The new asset will be then appended to the project tree. The node to which the new asset is appended is completely determined by the user setting. We will analyze the setting and try to browse through the project assets to see if any asset has the exact same meshing or case setting. If such asset is found the new asset will be appended to that node or the asset corresponding to that node will be returned directly and no meshing/case will be run.
For example, in the above example, let’s say VolumeMesh 2
has the same meshing
setting as my_params
. Then the new case will be appended to the VolumeMesh 2
and only
the mesh generation will be skipped.
graph TD classDef grayNode fill:#ddd,stroke:#bbb,stroke-width:2px; classDef grayText color:#bbb,fill-opacity:0.3; classDef highlightText color:#ff5436,fill-opacity:0.9; subgraph Project["Project"] Geometry["Geometry"] SurfaceMesh1["SurfaceMesh 1"] SurfaceMesh2["SurfaceMesh 2"] VolumeMesh1["VolumeMesh 1"] VolumeMesh2["VolumeMesh 2"] Case1["Case 1"] Case2["Case 2"] Case3["Case 3"] Case4["**my new case**"] Geometry --> SurfaceMesh1 Geometry --> SurfaceMesh2 SurfaceMesh1 --> VolumeMesh1 SurfaceMesh1 --> VolumeMesh2 VolumeMesh1 --> Case1 VolumeMesh1 --> Case4 VolumeMesh2 --> Case2 Case2 --> Case3 end %% These are irrelevant nodes class SurfaceMesh2,VolumeMesh2,Case1,Case2,Case3 grayNode; class SurfaceMesh2,VolumeMesh2,Case1,Case2,Case3 grayText; %% These are highlighted nodes class Case4 highlightText;
Another scenario is that if the user happens to have a case with the exact same setting (meshing and case)
as my_params
in the project, there will be no new case created and the existing case will be returned.
For example if my_params
is exactly the same as the one that created Case 2
,
then Case 2
will be returned.
graph TD classDef grayNode fill:#ddd,stroke:#bbb,stroke-width:2px; classDef grayText color:#bbb,fill-opacity:0.3; classDef highlightText color:#ff5436,fill-opacity:0.9; subgraph Project["Project"] Geometry["Geometry"] SurfaceMesh1["SurfaceMesh 1"] SurfaceMesh2["SurfaceMesh 2"] VolumeMesh1["VolumeMesh 1"] VolumeMesh2["VolumeMesh 2"] Case1["Case 1"] Case2["**Case 2**"] Case3["Case 3"] Geometry --> SurfaceMesh1 Geometry --> SurfaceMesh2 SurfaceMesh1 --> VolumeMesh1 SurfaceMesh1 --> VolumeMesh2 VolumeMesh1 --> Case1 VolumeMesh2 --> Case2 Case2 --> Case3 end %% These are irrelevant nodes class SurfaceMesh2,VolumeMesh1,Case1,Case3 grayNode; class SurfaceMesh2,VolumeMesh1,Case1,Case3 grayText; %% These are highlighted nodes class Case2 highlightText;
Geometry#
User can use Geometry
asset to specify the grouping of faces and edges and these grouping information will be
used when generating the mesh and running the case.
Note that only the grouping/tagging information stored in the geometry file can be used.
Currently we do not support creating new groups/tags.
For example in the quick start example, we tried to access the available groupings in the geometry:
geo.show_available_groupings(verbose_mode=True)
and we can see output:
INFO: >> Available attribute tags for grouping **faces**:
INFO: >> Tag 0: groupName. Grouping with this tag results in:
INFO: >> Group 0: leftWing `
INFO: IDs: ['body0001_face0001', 'body0001_face0002', 'body0001_face0003', 'body0001_face0004']
INFO: >> Group 1: fuselage
INFO: IDs: ['body0001_face0005', 'body0001_face0006', 'body0001_face0007', 'body0001_face0008', 'body0001_face0009', 'body0001_face0010']
INFO: >> Group 2: rightWing
INFO: IDs: ['body0001_face0011', 'body0001_face0012', 'body0001_face0013', 'body0001_face0014']
INFO: >> Available attribute tags for grouping **edges**:
INFO: >> Tag 0: edgeName. Grouping with this tag results in:
INFO: >> Group 0: trailingEdge
INFO: IDs: ['body0001_edge0001', 'body0001_edge0005', 'body0001_edge0026', 'body0001_edge0030']
INFO: >> Group 1: leadingEdge
INFO: IDs: ['body0001_edge0007', 'body0001_edge0032']
INFO: >> Group 2: body0001_edge0002
INFO: IDs: ['body0001_edge0002']
INFO: >> Group 3: body0001_edge0004
INFO: IDs: ['body0001_edge0004']
INFO: >> Group 4: body0001_edge0006
INFO: IDs: ['body0001_edge0006']
INFO: >> Group 5: body0001_edge0008
INFO: IDs: ['body0001_edge0008']
INFO: >> Group 6: body0001_edge0009
...
Note that the above geometry file only specifies tag for some of the edges
("body0001_edge0001"
, "body0001_edge0005"
, "body0001_edge0026"
, "body0001_edge0030"
, "body0001_edge0007"
, "body0001_edge0032"
)
, all the other edges does not have the tag “edgeName”. If “edgeName” is specified as the edge tag, the edges without this tag will be grouped by themselves (one edge per group).
In other words when user do:
geo.group_edges_by_tag("edgeName")
The resulting grouped edges will be:
trailingEdge
leadingEdge
body0001_edge0002
body0001_edge0004
body0001_edge0006
…
For face grouping user can call:
geo.group_faces_by_tag("groupName")
User can always use “faceId” and “edgeId” to group faces and edges respectively. This results in each individual face/edge being grouped.