|
| 1 | +# # IPM geometry optimization |
| 2 | +# |
| 3 | +# This example shows how to use PyAEDT to find the best machine 2D geometry |
| 4 | +# to achieve high torque and low losses. |
| 5 | +# The example shows how to setup an optimetrics analysis to sweep geometries |
| 6 | +# for a single value of stator current angle. |
| 7 | +# The torque and losses results are then exported in a .csv file. |
| 8 | +# |
| 9 | +# Keywords: **Maxwell 2D**, **transient**, **motor**, **optimization**. |
| 10 | + |
| 11 | +# ## Perform imports and define constants |
| 12 | +# |
| 13 | +# Perform required imports. |
| 14 | + |
| 15 | +import csv |
| 16 | +import os |
| 17 | +import tempfile |
| 18 | +import time |
| 19 | + |
| 20 | +import ansys.aedt.core |
| 21 | + |
| 22 | +# Define constants. |
| 23 | + |
| 24 | +AEDT_VERSION = "2024.2" |
| 25 | +NUM_CORES = 4 |
| 26 | +NG_MODE = False # Open AEDT UI when it is launched. |
| 27 | + |
| 28 | +# ## Create temporary directory and download files |
| 29 | +# |
| 30 | +# Create a temporary directory where downloaded data or |
| 31 | +# dumped data can be stored. |
| 32 | +# If you'd like to retrieve the project data for subsequent use, |
| 33 | +# the temporary folder name is given by ``temp_folder.name``. |
| 34 | + |
| 35 | +temp_folder = tempfile.TemporaryDirectory(suffix=".ansys") |
| 36 | + |
| 37 | +# ## Download AEDT file example |
| 38 | +# |
| 39 | +# Set the local temporary folder to export the AEDT file to. |
| 40 | + |
| 41 | +aedt_file = ansys.aedt.core.downloads.download_file( |
| 42 | + source="maxwell_motor_optimization", |
| 43 | + name="IPM_optimization.aedt", |
| 44 | + destination=temp_folder.name, |
| 45 | +) |
| 46 | + |
| 47 | +# ## Launch Maxwell 2D |
| 48 | +# |
| 49 | +# Launch AEDT and Maxwell 2D after first setting up the project, the version and the graphical mode. |
| 50 | + |
| 51 | +m2d = ansys.aedt.core.Maxwell2d( |
| 52 | + project=aedt_file, |
| 53 | + version=AEDT_VERSION, |
| 54 | + new_desktop=True, |
| 55 | + non_graphical=NG_MODE, |
| 56 | +) |
| 57 | + |
| 58 | +# ## Add parametric setup |
| 59 | +# |
| 60 | +# Add a parametric setup made up of geometry variable sweep definitions and single value for the stator current angle. |
| 61 | +# Note: Step variations have been minimized to reduce the analysis time. If needed they can be increased by changing |
| 62 | +# the ``step`` argument. |
| 63 | + |
| 64 | +param_sweep = m2d.parametrics.add( |
| 65 | + variable="bridge", |
| 66 | + start_point="0.5mm", |
| 67 | + end_point="1mm", |
| 68 | + step="0.5mm", |
| 69 | + variation_type="LinearStep", |
| 70 | +) |
| 71 | +param_sweep.add_variation( |
| 72 | + sweep_variable="din", |
| 73 | + start_point=70, |
| 74 | + end_point=80, |
| 75 | + step=10, |
| 76 | + units="mm", |
| 77 | + variation_type="LinearStep", |
| 78 | +) |
| 79 | +param_sweep.add_variation( |
| 80 | + sweep_variable="phase_advance", |
| 81 | + start_point=0, |
| 82 | + end_point=45, |
| 83 | + step=45, |
| 84 | + units="deg", |
| 85 | + variation_type="LinearStep", |
| 86 | +) |
| 87 | +param_sweep.add_variation( |
| 88 | + sweep_variable="Ipeak", start_point=200, units="A", variation_type="SingleValue" |
| 89 | +) |
| 90 | + |
| 91 | +# ## Analyze parametric sweep |
| 92 | + |
| 93 | +param_sweep.analyze(cores=NUM_CORES) |
| 94 | + |
| 95 | +# ## Post-processing |
| 96 | +# |
| 97 | +# Create reports to get torque and loss results for all variations. |
| 98 | + |
| 99 | +report_torque = m2d.post.create_report( |
| 100 | + expressions="Moving1.Torque", |
| 101 | + domain="Sweep", |
| 102 | + variations={"bridge": "All", "din": "All", "Ipeak": "All"}, |
| 103 | + primary_sweep_variable="Time", |
| 104 | + plot_type="Rectangular Plot", |
| 105 | + plot_name="TorqueAllVariations", |
| 106 | +) |
| 107 | + |
| 108 | +report_solid_loss = m2d.post.create_report( |
| 109 | + expressions="SolidLoss", |
| 110 | + domain="Sweep", |
| 111 | + variations={"bridge": "All", "din": "All", "Ipeak": "All"}, |
| 112 | + primary_sweep_variable="Time", |
| 113 | + plot_type="Rectangular Plot", |
| 114 | + plot_name="SolidLossAllVariations", |
| 115 | +) |
| 116 | + |
| 117 | +report_core_loss = m2d.post.create_report( |
| 118 | + expressions="CoreLoss", |
| 119 | + domain="Sweep", |
| 120 | + variations={"bridge": "All", "din": "All", "Ipeak": "All"}, |
| 121 | + primary_sweep_variable="Time", |
| 122 | + plot_type="Rectangular Plot", |
| 123 | + plot_name="CoreLossAllVariations", |
| 124 | +) |
| 125 | + |
| 126 | +# Get torque and loss solution data for all available variations. |
| 127 | + |
| 128 | +torque_data = m2d.post.get_solution_data( |
| 129 | + expressions=["Moving1.Torque"], |
| 130 | + setup_sweep_name=m2d.nominal_sweep, |
| 131 | + domain="Sweep", |
| 132 | + variations={"bridge": "All", "din": "All", "Ipeak": "All"}, |
| 133 | + primary_sweep_variable="Time", |
| 134 | + report_category="Standard", |
| 135 | +) |
| 136 | + |
| 137 | +solid_loss_data = m2d.post.get_solution_data( |
| 138 | + expressions=["CoreLoss"], |
| 139 | + setup_sweep_name=m2d.nominal_sweep, |
| 140 | + domain="Sweep", |
| 141 | + variations={"bridge": "All", "din": "All", "Ipeak": "All"}, |
| 142 | + primary_sweep_variable="Time", |
| 143 | + report_category="Standard", |
| 144 | +) |
| 145 | + |
| 146 | +core_loss_data = m2d.post.get_solution_data( |
| 147 | + expressions=["SolidLoss"], |
| 148 | + setup_sweep_name=m2d.nominal_sweep, |
| 149 | + domain="Sweep", |
| 150 | + variations={"bridge": "All", "din": "All", "Ipeak": "All"}, |
| 151 | + primary_sweep_variable="Time", |
| 152 | + report_category="Standard", |
| 153 | +) |
| 154 | + |
| 155 | +# Calculate torque and loss average values for each variation and write data in a .csv file. |
| 156 | + |
| 157 | +csv_data = [] |
| 158 | +for var in core_loss_data.variations: |
| 159 | + torque_data.active_variation = var |
| 160 | + core_loss_data.active_variation = var |
| 161 | + solid_loss_data.active_variation = var |
| 162 | + |
| 163 | + torque_values = torque_data.data_magnitude() |
| 164 | + core_loss_values = core_loss_data.data_magnitude() |
| 165 | + solid_loss_values = solid_loss_data.data_magnitude() |
| 166 | + |
| 167 | + torque_data_average = sum(torque_values) / len(torque_values) |
| 168 | + core_loss_average = sum(core_loss_values) / len(core_loss_values) |
| 169 | + solid_loss_average = sum(solid_loss_values) / len(solid_loss_values) |
| 170 | + |
| 171 | + csv_data.append( |
| 172 | + { |
| 173 | + "active_variation": str(torque_data.active_variation), |
| 174 | + "average_torque": str(torque_data_average), |
| 175 | + "average_core_loss": str(core_loss_average), |
| 176 | + "average_solid_loss": str(solid_loss_average), |
| 177 | + } |
| 178 | + ) |
| 179 | + |
| 180 | + with open( |
| 181 | + os.path.join(temp_folder.name, "motor_optimization.csv"), "w", newline="" |
| 182 | + ) as csvfile: |
| 183 | + fields = [ |
| 184 | + "active_variation", |
| 185 | + "average_torque", |
| 186 | + "average_core_loss", |
| 187 | + "average_solid_loss", |
| 188 | + ] |
| 189 | + writer = csv.DictWriter(csvfile, fieldnames=fields) |
| 190 | + writer.writeheader() |
| 191 | + writer.writerows(csv_data) |
| 192 | + |
| 193 | +# ## Release AEDT |
| 194 | + |
| 195 | +m2d.save_project() |
| 196 | +m2d.release_desktop() |
| 197 | +# Wait 3 seconds to allow AEDT to shut down before cleaning the temporary directory. |
| 198 | +time.sleep(3) |
| 199 | + |
| 200 | +# ## Clean up |
| 201 | +# |
| 202 | +# All project files are saved in the folder ``temp_folder.name``. |
| 203 | +# If you've run this example as a Jupyter notebook, you |
| 204 | +# can retrieve those project files. The following cell |
| 205 | +# removes all temporary files, including the project folder. |
| 206 | + |
| 207 | +temp_folder.cleanup() |
0 commit comments