From 7f7bacebd0ea3129ff2686b82cd1ac4e8ba24e56 Mon Sep 17 00:00:00 2001 From: Lorenzo Vecchietti <58366962+lorenzovecchietti@users.noreply.github.com> Date: Fri, 19 Jan 2024 09:39:11 +0100 Subject: [PATCH] Icepak csv example improvement (#4100) * small fix to example * improve example --- examples/04-Icepak/Icepak_CSV_Import.py | 186 ++++++------------------ pyaedt/icepak.py | 3 +- 2 files changed, 45 insertions(+), 144 deletions(-) diff --git a/examples/04-Icepak/Icepak_CSV_Import.py b/examples/04-Icepak/Icepak_CSV_Import.py index b8268e3d626..b098c2e28be 100644 --- a/examples/04-Icepak/Icepak_CSV_Import.py +++ b/examples/04-Icepak/Icepak_CSV_Import.py @@ -40,164 +40,66 @@ ipk.autosave_disable() +# Create the PCB as a simple block. +board = ipk.modeler.create_box([-30.48, -27.305, 0], [146.685, 71.755, 0.4064], "board_outline", matname="FR-4_Ref") + ############################################################################### -# Import the CSV file -# ~~~~~~~~~~~~~~~~~~~~ -# Import the CSV file that lists the name of blocks, their type and material properties. -# +# Blocks creation with a CSV file +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# The CSV file lists the name of blocks, their type and material properties. # Block types (solid, network, hollow), block name, block starting and end points, solid material, and power are listed. -# # Hollow and network blocks do not need the material name. -# -# Network blocks must have the Board side listed as well as Rjb and Rjc values. -# +# Network blocks must have Rjb and Rjc values. # Monitor points can be created for any types of block if the last column is assigned to be 1 (0 and 1 are the only options). # # The following image does not show the entire rows and data and only serves as a sample. # -# # .. image:: ../../_static/CSV_Import.png # :width: 400 # :alt: CSV Screenshot. # # - -filename = pyaedt.downloads.download_file('icepak','blocks-list.csv',destination=temp_folder) -fields = [] -rows = [] - -with open(filename, 'r') as csvFile: - csvReader = csv.reader(csvFile) - fields = next(csvReader) - for row in csvReader: - rows.append(row) - -############################################################################### -# Defining a function for network block types -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# This function will be called in the next step if the block type is network. -# It will read the board side as well as thetaj values and assign them to the block. - -def create_2R_network_BC(object3d, power, rjb, rjc, board_side): - - board_side = board_side.casefold() # returns the board side with all letters in lower case - - if board_side == "minx": - board_faceID = object3d.bottom_face_x.id - case_faceID = object3d.top_face_x.id - case_side = "maxx" - elif board_side == "maxx": - board_faceID = object3d.top_face_x.id - case_faceID = object3d.bottom_face_x.id - case_side = "minx" - elif board_side == "miny": - board_faceID = object3d.bottom_face_y.id - case_faceID = object3d.top_face_y.id - case_side = "maxy" - elif board_side == "maxy": - board_faceID = object3d.top_face_y.id - case_faceID = object3d.bottom_face_y.id - case_side = "miny" - elif board_side == "minz": - board_faceID = object3d.bottom_face_z.id - case_faceID = object3d.top_face_z.id - case_side = "maxz" - else: - board_faceID = object3d.top_face_z.id - case_faceID = object3d.bottom_face_z.id - case_side = "minz" - - # Define network properties in props dictionary - props = {} - props["Faces"] = [board_faceID, case_faceID] - - props["Nodes"] = OrderedDict( - { - "Case_side(" + case_side + ")": [case_faceID, "NoResistance"], - "Board_side(" + board_side + ")": [board_faceID, "NoResistance"], - "Internal": [power + 'W'], - } - ) - - props["Links"] = OrderedDict( - { - "Rjc": ["Case_side(" + case_side + ")", "Internal", "R", str(rjc) + "cel_per_w"], - "Rjb": ["Board_side(" + board_side + ")", "Internal", "R", str(rjb) + "cel_per_w"], - } - ) - - props["SchematicData"] = OrderedDict({}) - - # Default material is Ceramic material - ipk.modeler.primitives[object3d.name].material_name = "Ceramic_material" - - # Create boundary condition and set Solve Inside to No - bound = BoundaryObject(ipk, object3d.name, props, "Network") - if bound.create(): - ipk.boundaries.append(bound) - ipk.modeler.primitives[object3d.name].solve_inside = False - -############################################################################### -# Final stage to create the blocks -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# It will loop over the csv file lines and creates the blocks. +# In this step the code will loop over the csv file lines and creates the blocks. # It will create solid blocks and assign BCs. -# Every row in the list has information of a particular block. -# This information is extracted via a "for" loop. -# For example, rows[i][1] is the first item in the list that has the block name information. - -for i in range(len(rows)): - - origin = [float(rows[i][2]), float(rows[i][3]), float(rows[i][4])] # block starting point - dimensions = [float(rows[i][5]), float(rows[i][6]), float(rows[i][7])] # block lengths in 3 dimensions - block_name = rows[i][1] # block name - block_name = re.sub("\W", "_", block_name) - - # Define material name - - if rows[i][8] == "": - material_name = "Al-Extruded" - else: - material_name = rows[i][8] - - # creates the block with the given name, coordinates, material, and type - block = ipk.modeler.primitives.create_box(origin, dimensions, name=block_name, matname=material_name) - - # Assign boundary conditions - - if rows[i][0] == "solid": - ipk.create_source_block(block_name, rows[i][9] + "W", assign_material=False, use_object_for_name=True) - - elif rows[i][0] == "network": - create_2R_network_BC(block, rows[i][9], rows[i][11], rows[i][12], rows[i][10]) - - else: - ipk.create_source_block(block_name, rows[i][9] + "W", assign_material=False, use_object_for_name=True) - ipk.modeler.primitives[block.name].solve_inside = False - - # Create temperature monitor points if assigned value is 1 in the last column of the csv file - - if rows[i][13] == '1': - # calculates the location of the monitoir point based on the starting point an dlength of the block - - mon_loc_x = float(rows[i][2]) + 0.5 * float(rows[i][5]) - mon_loc_y = float(rows[i][3]) + 0.5 * float(rows[i][6]) - mon_loc_z = float(rows[i][4]) + 0.5 * float(rows[i][7]) - mon_loc = [mon_loc_x, mon_loc_y, mon_loc_z] - ipk.assign_point_monitor(mon_loc, monitor_name=block_name) # creates the monitor point +# Every row of the csv has information of a particular block. + +filename = pyaedt.downloads.download_file('icepak', 'blocks-list.csv', destination=temp_folder) + +with open(filename, 'r') as csv_file: + csv_reader = csv.DictReader(csv_file) + for row in csv_reader: + origin = [float(row["xs"]), float(row["ys"]), float(row["zs"])] # block starting point + dimensions = [float(row["xd"]), float(row["yd"]), float(row["zd"])] # block lengths in 3 dimensions + block_name = row["name"] # block name + + # Define material name + if row["matname"]: + material_name = row["matname"] + + # creates the block with the given name, coordinates, material, and type + block = ipk.modeler.create_box(origin, dimensions, name=block_name, matname=material_name) + + # Assign boundary conditions + if row["block_type"] == "solid": + ipk.assign_solid_block(block_name, row["power"] + "W", block_name) + elif row["block_type"] == "network": + ipk.create_two_resistor_network_block(block_name, board.name, row["power"] + "W", row["Rjb"], row[ + "Rjc"]) # board and case sides are automatically computed based on the position relative to the board + else: + ipk.modeler[block.name].solve_inside = False + ipk.assign_hollow_block(block_name, assignment_type="Total Power", assignment_value=row["power"] + "W", + boundary_name=block_name) + + # Create temperature monitor points if assigned value is 1 in the last column of the csv file + if row["Monitor_point"] == '1': + ipk.monitor.assign_point_monitor_in_object(row["name"], monitor_quantity="Temperature", monitor_name=row[ + "name"]) # creates the monitor point at the center of the object ############################################################################### -# Fit to scale, save the project +# Save the project and close # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # This will scale to fit all objects in AEDT and save the project. ipk.modeler.fit_all() -ipk.save_project() - -############################################################################### -# Closing and releasing AEDT -# ~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Release the AEDT session. If this step is missing, AEDT cannot be closed. - -ipk.close_project() -ipk.release_desktop(True, True) +ipk.close_project(save_project=True) +ipk.close_desktop() \ No newline at end of file diff --git a/pyaedt/icepak.py b/pyaedt/icepak.py index a8a7d9b5c58..d77f0190f7d 100644 --- a/pyaedt/icepak.py +++ b/pyaedt/icepak.py @@ -3157,7 +3157,6 @@ def import_idf( @pyaedt_function_handler() def create_two_resistor_network_block(self, object_name, pcb, power, rjb, rjc): """Function to create 2-Resistor network object. - This method is going to replace create_network_block method. Parameters ---------- @@ -3187,7 +3186,7 @@ def create_two_resistor_network_block(self, object_name, pcb, power, rjb, rjc): -------- >>> board = icepak.modeler.create_box([0, 0, 0], [50, 100, 2], "board", "copper") >>> box = icepak.modeler.create_box([20, 20, 2], [10, 10, 3], "network_box1", "copper") - >>> network_block = icepak.create_two_resistor_network_block_new("network_box1", "board", "5W", 2.5, 5) + >>> network_block = icepak.create_two_resistor_network_block("network_box1", "board", "5W", 2.5, 5) >>> network_block.props["Nodes"]["Internal"][0] '5W' """