I have a series of force magnitude values in a spreadsheet, and I am interested in applying those forces on the base faces of a circular geometry pattern like in the picture below:
Let’s assume that the force values are listed in a meaningful way e.g. in the same order as the sequence of the target faces.
This solution relies on a strategically placed cylindrical coordinate system and utilizes worksheet-based filtering to generate named selections and assign each force value to the corresponding surface. The procedure will be automated with Python scripting inside Mechanical.
An archive of the example project file is also attached for the interested reader to experiment with. A simple spreadsheet with input data is included in the user_files directory of the project.
The first step to implement this workflow is to define a coordinate system. In this example, we set the X axis towards the face where the first load in the list will be applied. Each subsequent force in our data column corresponds to the next face moving counterclockwise. Hence the coordinate system is set accordingly (positive angular coordinates (Y) towards the direction where the next force value is applied). In this example, the coordinate system is renamed to ‘CylCS’ and to reference it in the Python script. We have also set the angle units to degrees for convenience.
In the beginning of the script, we need to define some parameters. In particular:
n_sectors
tolerance
level
n_sectors = 8 angle = 360/n_sectors tolerance = 1 level = 40
Next, let’s import the force magnitude data from the external spreadsheet. For this example, we created a simple column of data in csv format. Like below:
100
200
300
400
500
600
700
800
The data file is placed in the user_files folder in the project directory, which path we can quickly retrieve with Python in Mechanical using the ExtAPI.DataModel.Project.ProjectDirectory command line.
ExtAPI.DataModel.Project.ProjectDirectory
import csv my_data_dir = ExtAPI.DataModel.Project.ProjectDirectory+'user_files\my_data.csv' magnitude = [] with open(my_data_dir, "r") as f: reader = csv.reader(f) for row in reader: magnitude.append(float(row[0]))
Finally, for each face we need to iterate over the following steps:
my_sels = [] for step in range(0,n_sectors): my_sels.append(Model.NamedSelections.AddNamedSelection()) my_sel = my_sels[step] my_sel.ScopingMethod = GeometryDefineByType.Worksheet my_sel.GenerationCriteria.Add(None) my_sel.GenerationCriteria[0].EntityType = SelectionType.GeoFace my_sel.GenerationCriteria[0].Criterion = SelectionCriterionType.LocationY my_sel.GenerationCriteria[0].CoordinateSystem = DataModel.GetObjectsByName('CylCS')[0] my_sel.GenerationCriteria[0].Operator = SelectionOperatorType.RangeInclude my_sel.GenerationCriteria.Add(None) my_sel.GenerationCriteria[1].Action = SelectionActionType.Filter my_sel.GenerationCriteria[1].Criterion = SelectionCriterionType.LocationZ my_sel.GenerationCriteria[1].Operator = SelectionOperatorType.Equal my_sel.GenerationCriteria[1].Value = Quantity(str(level)+' [mm]') sec_angle = step*angle my_sel.GenerationCriteria[0].LowerBound = Quantity(str(sec_angle-tolerance)+' [deg]') my_sel.GenerationCriteria[0].UpperBound = Quantity(str(sec_angle+tolerance)+' [deg]') my_sel.Generate() my_force = DataModel.AnalysisList[0].AddForce() my_force.Location = my_sel my_force.DefineBy = LoadDefineBy.Components my_force.ZComponent.Output.SetDiscreteValue(0,Quantity(str(magnitude[step])+' [N]'))