To carry out the optimization calculation, it is necessary that the following conditions are met:
- Installed Python v.3.8 or higher;
- Installed vtk library for Python;
- Installed numpy library for Python.
To meet these conditions, you must do the following::
- Download Python 3.8 or higher from python.org and install.
- Open the Windows command line (cmd.exe) and write:
pip3 install numpy (then press Enter and let the installation complete);
pip3 install vtk (then press Enter and let the installation complete).
After all the necessary steps have been completed, you can start solving the problem.
The problem of optimization of the diameter of the base of a billboard pillar, loaded with a wind load, is considered.
Geometry Creation
1. Create a brick.
Select volume geometry generation section on Command Panel (Mode — Geometry, Entity — Volume, Action — Create).
From the list of geometric primitives, select Brick.
Set the following parameters:
- X (width): 20;
- Y (heigtht): 0.5;
- Z (depth): 10;
Click Apply.
Then the volume needs to be moved.
Go to (Mode — Geometry, Entity — Volume, Action — Transform).
Select Move from the list of operations.
Set the following parameters:
- Volume ID's: 1;
- Method: Distance
- X Distance: 0;
- Y Distance: 0;
- Z Distance: 30.
Click Apply.
2. Create a frusto-cone pillar.
Go to (Mode — Geometry, Entity — Volume, Action — Create).
Select Cone from the list of geometric primitives.
Set the following parameters:
- Height: 25;
- Top radius: 0.25;
- Circular;
- Radius: 0.3.
Click Apply.
Next, the pillar must be moved.
Go to (Mode — Geometry, Entity — Volume, Action — Transform).
Select Move from the list of operations.
Set the following parameters:
- Volume ID's: 2;
- Method: Distance ;
- X Distance: 0;
- Y Distance: 0;
- Z Distance: 12.5.
Click Apply.
3. Create common surfaces to generate the correct mesh.
Go to (Mode — Geometry, Entity — Volume, Action — Imprint and Merge).
Select Imprint/Merge Volumes from the list of operations.
Set the following parameters:
- Volume ID's: all
Click Apply.
Meshing
1. Create a mesh.
Go to (Mode — Mesh, Entity — Volume, Action — Mesh).
Select Tetmesh from the list of algorithms.
Set the following parameters:
- Select volumes: all
Click Mesh.
If everything was done correctly, you will see a model like this:
Specifying the material
1. Create the material.
Go to (Mode — Material, Entity — Materials Management).
In the Material Management window, drag&drop "Steel" from the third column to the second.
Click Apply.
2. Create a block.
Go to (Mode — Blocks, Entity — Block, Action — Add).
Select Volume in the Entity List.
Set the following parameters:
- Entity ID's: all
Click Apply.
3. Set the block properties.
Go to (Mode — Blocks, Entity — Block, Action — Block properties/parameters).
Set the following parameters:
- Block ID's: 1
- Material: Steel;
- Coordinate system: Global Cartesian;
- Категория: Solid;
- Order: 1.
Click Apply.
Setting boundary conditions
1. Fix all displacements of the surface of the base of the pillar
Go to (Mode — Boundary Conditions, Entity — Displacement, Action — Create).
Set the following parameters:
- Entity list: Surface;
- Entity ID's: 8;
- Degrees Of Freedom: All;
- DOF Value: 0.
Click Apply.
2. Set the distributed wind force on the billboard surface to p = 230 N/m^2.
Go to (Mode — Boundary Conditions, Entity — Distributed force, Action — Create).
Select Surface from the Entity List.
Set the following parameters:
- Entity ID(s): 3;
- Force type: Distributed Force;
- Force: 230;
- Direction Vector: (X: 0, Y: 1, Z: 0).
Click Apply.
3. Add gravity.
Go to (Mode — Boundary Conditions, Entity — Gravity, Action — Create).
Select Global from the Entity List.
Set the following parameters:
- Directions: Z -9.81.
Click Apply.
Preparing for calculation
1. Set the calculation settings.
Go to (Mode — Calculation Settings, Calculation settings — Static, Static — General).
Set the following parameters:
- Dimensions: 3D;
- Model: Elasticity.
Click Apply.
Extracting and Transforming of the Script
1. Extract the model script from History.
Go to the Command line and switch the tab to "History" , where you will see the script of the model you generated:
reset brick x 20 y 0.5 z 10 move Volume 1 x 0 y 0 z 30 include_merged create frustum height 25 radius 0.25 top 0.25 move Volume 2 x 0 y 0 z 12.5 include_merged undo group begin imprint volume all merge volume all undo group end volume all scheme tetmesh mesh volume all create material 1 from 'Steel' set duplicate block elements off block 1 add volume all block 'Block 1' material 1 cs 1 element solid order 1 create displacement on surface 8 dof all fix create distributed force on surface 3 force value 230 moment value 0 direction 0 1 0 specific create gravity global modify gravity 1 dof 3 value -9.81 analysis type static elasticity dim3
Right-click anywhere on the command line and select Select All , then right-click the selected script again and select Copy .
This is how you copied the script to the clipboard.
2. Convert the script to Python syntax.
Open the Journal Editor and paste the script you copied earlier into its window.
Convert the script to Python syntax via Tools - Translate - Python.
If everything is done correctly, then you will get the following script in the window:
Copy the resulting Python script from the Journal Editor.
Create and run a Python script
1. Create a Python script file.
Start Python IDLE, select File - New File from the menu, and a window for editing the script will open.
2. Copy and paste the script below into a blank window that opens.
This Python script already contains the portion of the Fidesys model script that we got earlier. The place where the Fidesys model script is inserted is marked with appropriate comments.
Please note that the bottom diameter of the pillar is varied by modifying of the cone creating command:
- the initial view of the command: fidesys.cmd("create frustum height 25 radius 0.25 top 0.25")
- view of the changed command: fidesys.cmd("create frustum height 25 radius "+str(r)+"top 0.25").
Inserting "+str(r)+" adds a radius value to the text command break.
Script for Fidesys 4.1:
import vtk # Library for working with output data from vtk.util.numpy_support import vtk_to_numpy # Library for converting results import sys # System library import os # System library fidesys_path = r'C:\Program Files\Fidesys\CAE-Fidesys-4.1' # Location of Fidesys base_dir = os.path.dirname(os.path.abspath(__file__)) # Directory where the script is located pvd_file = os.path.join(base_dir, '1.pvd') # Results Links File prep_path = os.path.join(fidesys_path, 'preprocessor', 'bin') # Directory where the preprocessor is os.environ['PATH'] += prep_path # Adding preprocessor path to PATH sys.path.append(prep_path) # Adding preprocessor path to PATH import cubit # Preprocessing library import fidesys # Library of Fidesys cubit.init([""]) # Initializing the preprocessor fc = fidesys.FidesysComponent() # Create a required Fidesys fc component fc.initApplication(prep_path) # Initializing the path to the preprocessor fc.start_up_no_args() # Launch of the required Fidesys fc component r = 0.25 # Initial bottom radius of the pillar print("Initial bottom diameter: ", 2*r) # Output to the data console - the initial value of the diameter isOptimized = False # Initially False - initial construction is not optimized iteration = 1 # Initial value of the counter of passes (iterations) while isOptimized == False: # The loop repeats until the condition isOptimized == True print("Iteration № ",iteration) # Write to the console which iteration overstressed = [] # Create an empty array to fill with overstressed nodes # ---------Start script from Fidesys------------- fidesys.cmd('reset') fidesys.cmd('brick x 20 y 0.5 z 10') fidesys.cmd('move Volume 1 x 0 y 0 z 30 include_merged ') fidesys.cmd("create frustum height 25 radius "+str(r)+"top 0.25") fidesys.cmd('move Volume 2 x 0 y 0 z 12.5 include_merged ') fidesys.cmd('undo group begin') fidesys.cmd('imprint volume all ') fidesys.cmd('merge volume all ') fidesys.cmd('undo group end') fidesys.cmd('volume all scheme tetmesh') fidesys.cmd('mesh volume all') fidesys.cmd('create material 1 from \'Steel\'') fidesys.cmd('set duplicate block elements off') fidesys.cmd('block 1 add volume all') fidesys.cmd('block \'Block 1\' material 1 cs 1 element solid order 1') fidesys.cmd('create displacement on surface 8 dof all fix ') fidesys.cmd('create distributed force on surface 3 force value 230 moment value 0 direction 0 1 0 specific') fidesys.cmd('create gravity global') fidesys.cmd('modify gravity 1 dof 3 value -9.81') fidesys.cmd('analysis type static elasticity dim3') # ---------End script from Fidesys------------- output_pvd_path = os.path.join(base_dir + "\\" + "1.pvd") # We declare the directory and the save file print("strarting calculation to " + output_pvd_path) # We output the directory and the save file to the console fidesys.cmd("calculation start path '" + output_pvd_path + "'") # We ask Fidesys to start the calculation in the specified directory print(" ") print("Calculation completed successfully!") print(" ") reader = vtk.vtkXMLUnstructuredGridReader() # Connect the reader print("Reading the results from ",str(base_dir)+r"\1\case1_step0001_substep0001.vtu") # Writes where we get the results from filename = os.path.join(str(base_dir)+r"\1\case1_step0001_substep0001.vtu") # Specifying the path to the file reader.SetFileName(filename) # We connect the path to the reader and read reader.Update() # Needed because of GetScalarRange grid = reader.GetOutput() # We take the output point_data = grid.GetPointData() # We collect data for points arrayOfStress = vtk_to_numpy(point_data.GetArray("Stress")) # Reading stresses from the array of results node_id = vtk_to_numpy(point_data.GetArray("Node ID")) # Reading node numbers from the result array print("Start searching for overstressed nodes") print(" ") for point in range(len(arrayOfStress)): if arrayOfStress[point][6] > 106e6: # Checking the von Mises stresses in the nodes overstressed.append(node_id[point]) # Fill the array with numbers of overstressed nodes if len(overstressed) == 0: # The size of the array of overstressed nodes is checked, if it is 0 then isOptimized = True # set the variable isOptimized = True to exit the loop print("Design optimized!") else: print("Overstressed nodes: ",len(overstressed)) # Displaying information about the number of overstressed nodes print(" ") r = r + 0.05 # Increase the radius by 0.05 iteration = iteration + 1 # Increasing the value of the iteration counter fc.deleteApplication() # Removing the completed task from memory print(" ") print("Complete! Optimal diameter is at least: ", 2*r)
3. Run the script.
Select Run - Run Module from the menu and when the system asks to save this file, save it to the "Example" folder created in a directory with no Cyrillic characters in its path to avoid errors.
The following messages will appear in the console.
The results will be saved to the folder where the script file was located. Upon completion of the calculation, you can open and view the 1.pvd results file.
