|
| 1 | +import flow360 as fl |
| 2 | +from flow360 import u |
| 3 | +from flow360.examples import Airplane |
| 4 | +from flow360.plugins.report.report import ReportTemplate |
| 5 | +from flow360.plugins.report.report_items import ( |
| 6 | + Camera, |
| 7 | + Chart2D, |
| 8 | + Chart3D, |
| 9 | + Inputs, |
| 10 | + Settings, |
| 11 | + Summary, |
| 12 | + Table, |
| 13 | +) |
| 14 | +from flow360.plugins.report.utils import Average, DataItem, Delta |
| 15 | + |
| 16 | +project_id = None # if running for the first time |
| 17 | + |
| 18 | +# then replace it with your project ID to avoid re-creation of projects. You can find project ID on web GUI: |
| 19 | +# project_id = "prj-...." |
| 20 | + |
| 21 | +if project_id is not None: |
| 22 | + project = fl.Project.from_cloud(project_id) |
| 23 | +else: |
| 24 | + project = fl.Project.from_geometry( |
| 25 | + Airplane.geometry, name="Python Project (Geometry, from file) - for Report" |
| 26 | + ) |
| 27 | + |
| 28 | +geo = project.geometry |
| 29 | +geo.group_faces_by_tag("groupName") |
| 30 | + |
| 31 | + |
| 32 | +def simulation_params(angle_of_attack): |
| 33 | + with fl.SI_unit_system: |
| 34 | + far_field_zone = fl.AutomatedFarfield() |
| 35 | + params = fl.SimulationParams( |
| 36 | + meshing=fl.MeshingParams( |
| 37 | + defaults=fl.MeshingDefaults( |
| 38 | + boundary_layer_first_layer_thickness=0.001, |
| 39 | + surface_max_edge_length=1, |
| 40 | + ), |
| 41 | + volume_zones=[far_field_zone], |
| 42 | + ), |
| 43 | + reference_geometry=fl.ReferenceGeometry(area=1, moment_length=1), |
| 44 | + operating_condition=fl.AerospaceCondition( |
| 45 | + velocity_magnitude=100, |
| 46 | + alpha=angle_of_attack * fl.u.deg, |
| 47 | + ), |
| 48 | + time_stepping=fl.Steady(max_steps=1000), |
| 49 | + models=[ |
| 50 | + fl.Wall( |
| 51 | + surfaces=[geo["*"]], |
| 52 | + ), |
| 53 | + fl.Freestream( |
| 54 | + surfaces=[far_field_zone.farfield], |
| 55 | + ), |
| 56 | + ], |
| 57 | + outputs=[ |
| 58 | + fl.SurfaceOutput( |
| 59 | + surfaces=geo["*"], |
| 60 | + output_fields=[ |
| 61 | + "Cp", |
| 62 | + "Cf", |
| 63 | + "yPlus", |
| 64 | + "CfVec", |
| 65 | + "primitiveVars", |
| 66 | + ], |
| 67 | + ), |
| 68 | + ], |
| 69 | + ) |
| 70 | + return params |
| 71 | + |
| 72 | + |
| 73 | +cases: list[fl.Case] = [] |
| 74 | +for alpha in [0, 2, 4]: |
| 75 | + case = project.run_case(params=simulation_params(alpha), name=f"Case for report, alpha={alpha}") |
| 76 | + cases.append(case) |
| 77 | + |
| 78 | +[print(case.short_description()) for case in cases] |
| 79 | + |
| 80 | +# waiting explicitly for all the cases to finish (report pipeline will not wait for cases) |
| 81 | +[case.wait() for case in cases] |
| 82 | + |
| 83 | + |
| 84 | +top_camera = Camera( |
| 85 | + position=(0, 0, 1), |
| 86 | + look_at=(0, 0, 0), |
| 87 | + pan_target=(5, 0, 0), |
| 88 | + up=(0, 1, 0), |
| 89 | + dimension=15, |
| 90 | + dimension_dir="width", |
| 91 | +) |
| 92 | +side_camera = Camera( |
| 93 | + position=(0, -1, 0), |
| 94 | + look_at=(0, 0, 0), |
| 95 | + pan_target=(5, 0, 0), |
| 96 | + up=(0, 0, 1), |
| 97 | + dimension=12, |
| 98 | + dimension_dir="width", |
| 99 | +) |
| 100 | +front_left_bottom_camera = Camera( |
| 101 | + position=(-1, -1, -1), |
| 102 | + look_at=(0, 0, 0), |
| 103 | + pan_target=(4, 0, 0), |
| 104 | + up=(0, 0, 1), |
| 105 | + dimension=15, |
| 106 | + dimension_dir="width", |
| 107 | +) |
| 108 | +rear_right_bottom_camera = Camera( |
| 109 | + position=(1, 1, -1), |
| 110 | + look_at=(0, 0, 0), |
| 111 | + pan_target=(4, 0, 0), |
| 112 | + up=(0, 0, 1), |
| 113 | + dimension=15, |
| 114 | + dimension_dir="width", |
| 115 | +) |
| 116 | + |
| 117 | +cameras_geo = [ |
| 118 | + top_camera, |
| 119 | + side_camera, |
| 120 | + front_left_bottom_camera, |
| 121 | + rear_right_bottom_camera, |
| 122 | +] |
| 123 | + |
| 124 | +avg = Average(fraction=0.1) |
| 125 | + |
| 126 | +CL = DataItem(data="surface_forces/totalCL", title="CL", operations=avg) |
| 127 | + |
| 128 | +CD = DataItem(data="surface_forces/totalCD", title="CD", operations=avg) |
| 129 | + |
| 130 | +statistical_data = [ |
| 131 | + "params/operating_condition/alpha", |
| 132 | + "params/reference_geometry/area", |
| 133 | + CL, |
| 134 | + Delta(data=CL), |
| 135 | + CD, |
| 136 | + "volume_mesh/stats/n_nodes", |
| 137 | + "params/time_stepping/max_steps", |
| 138 | +] |
| 139 | +statistical_table = Table( |
| 140 | + data=statistical_data, |
| 141 | + section_title="Statistical data", |
| 142 | + formatter=[ |
| 143 | + ( |
| 144 | + None |
| 145 | + if d |
| 146 | + in [ |
| 147 | + "params/reference_geometry/area", |
| 148 | + "volume_mesh/stats/n_nodes", |
| 149 | + "params/time_stepping/max_steps", |
| 150 | + ] |
| 151 | + else ".4f" |
| 152 | + ) |
| 153 | + for d in statistical_data |
| 154 | + ], |
| 155 | +) |
| 156 | + |
| 157 | +geometry_screenshots = [ |
| 158 | + Chart3D( |
| 159 | + section_title="Geometry", |
| 160 | + items_in_row=2, |
| 161 | + force_new_page=True, |
| 162 | + show="boundaries", |
| 163 | + camera=camera, |
| 164 | + fig_name=f"geo_{i}", |
| 165 | + ) |
| 166 | + for i, camera in enumerate(cameras_geo) |
| 167 | +] |
| 168 | + |
| 169 | +report = ReportTemplate( |
| 170 | + title="Geometry to report", |
| 171 | + items=[ |
| 172 | + Summary(), |
| 173 | + Inputs(), |
| 174 | + statistical_table, |
| 175 | + Chart2D( |
| 176 | + x="total_forces/pseudo_step", |
| 177 | + y="total_forces/CL", |
| 178 | + section_title="Lift Coefficient", |
| 179 | + fig_name="cl_fig", |
| 180 | + focus_x=(1 / 3, 1), |
| 181 | + ), |
| 182 | + *geometry_screenshots, |
| 183 | + ], |
| 184 | + settings=Settings(dpi=150), |
| 185 | +) |
| 186 | + |
| 187 | + |
| 188 | +report = report.create_in_cloud( |
| 189 | + f"Geometry to report - Report, dpi=150", |
| 190 | + cases, |
| 191 | +) |
| 192 | + |
| 193 | +report.wait() |
| 194 | +report.download("report.pdf") |
0 commit comments