Table of Contents

Creating a simple IOM model with Python

This example runs through how a simple steel frame structure can be created using the IDEA Open Model (IOM) and Python.

This example follows along very similarly to the c# steel frame example

Define and reference IOM .dlls from the IDEA directory

Import required .dlls, including some system collections. We will reference the IdeaRS.OpenModel .dll from the IDEA installation path.

import clr
import sys
import json
import math
import os

idea_path = "C:\Program Files\IDEA StatiCa\StatiCa 22.1"
sys.path.append(idea_path);

clr.AddReference("System.Collections")
from System.Collections.Generic import List

clr.AddReference("IdeaRS.OpenModel")
#This allows us to quickly create the open Model Object
from IdeaRS.OpenModel import OpenModel

#This import allows us to quickly create objects which are referenced under the Open Model Namespace. 
from IdeaRS import OpenModel as IOM

Create Open Model

Create the open model object to which we will start to add objects.

model = OpenModel()

Project settings

Basic information about our project - such as a project name, a description, etc. Specification of the project country code is also important.

originSettings = IOM.OriginSettings() 

originSettings.CrossSectionConversionTable = IOM.CrossSectionConversionTable.SCIA
originSettings.CountryCode = IOM.CountryCode.ECEN
originSettings.ProjectName = "Project"
originSettings.Author = "IDEA StatiCa s.r.o."
originSettings.ProjectDescription = "Training example"

model.OriginSettings = originSettings

Definition of materials in the model

Note that materials are code specific.

material = IOM.Material.MatSteelEc2()

#set properties
material.Id = 1
material.Name = "S355"

#material.LoadFromLibrary = True;

material.E = 210000000000
material.G = material.E / (2 * (1 + 0.3))
material.Poisson = 0.3
material.UnitMass = 7850
material.SpecificHeat = 0.6
material.ThermalExpansion = 0.000012
material.ThermalConductivity = 45
material.IsDefaultMaterial = False
material.OrderInCode = 0
material.StateOfThermalExpansion = IOM.Material.ThermalExpansionState.Code
material.StateOfThermalConductivity = IOM.Material.ThermalConductivityState.Code
material.StateOfThermalSpecificHeat = IOM.Material.ThermalSpecificHeatState.Code
material.StateOfThermalStressStrain = IOM.Material.ThermalStressStrainState.Code
material.StateOfThermalStrain = IOM.Material.ThermalStrainState.Code
material.fy = 355000000
material.fu = 510000000
material.fy40 = 335000000
material.fu40 = 470000000
material.DiagramType = IOM.Material.SteelDiagramType.Bilinear

#add material to the model
model.AddObject(material);

Definition of cross sections in the model

We will add two different I Shape cross sections to the model: HE200B and HE240B. To create a single cross-section we will reference the material created in the previous section.

The IOM ReferenceElement is used to reference different objects to others in an IOM model.


# We can directly reference the material we create above as a reference element.

css1 = IOM.CrossSection.CrossSectionParameter()
css1.Id = 1;
css1.Name = "HE200B"
css1.Material =  IOM.ReferenceElement(material)
IOM.CrossSection.CrossSectionFactory.FillRolledI(css1, "HE200B")

css2 = IOM.CrossSection.CrossSectionParameter()
css2.Id = 2;
css2.Name = "HE240B"
css2.Material =  IOM.ReferenceElement(material)
IOM.CrossSection.CrossSectionFactory.FillRolledI(css2, "HE240B")

#add both cross-sections to the model
model.AddObject(css1)
model.AddObject(css2)
# We can save our progress at any time using the `SaveToXmlFile()` method.

model.SaveToXmlFile('progressIOM.xml')

Model Geometry

model nodes

Create Nodes

Table of all nodes with given coordinates:

Node X Y Z
N1 -2 3 0
N2 -2 3 3
N3 2 3 0
N4 2 3 3
N5 6 3 0
N6 6 3 3
N7 -2 3 6
N8 2 3 6
N9 6 3 6
# For ease I have created a List of List of Node Co-ordinates
nodes = [[-2,3,0],[-2,3,3],[2,3,0],[2,3,3],[6,3,0],[6,3,3],[-2,3,6],[2,3,6],[6,3,6]]

for i, pt in enumerate(nodes):
    Point = IOM.Geometry3D.Point3D()
    Point.X = nodes[i][0]
    Point.Y = nodes[i][1]
    Point.Z = nodes[i][2]
    Point.Name = "N{0}".format(i+1)
    Point.Id = i+1
    model.AddObject(Point)
    

Add Members to the Model

model members

Members are made up of one or more elements. Each element is to be created with a reference to a LineSegment3D. The LineSegment3D contains the local coordinate system of the member. By default a Z-up coordinate system is defined for all Line Segments.

LineSegment3D

The local coordinate system of members It its important to pay attantion to the correct setting of coordinate systems of members. It must correspond to coordinate systems which are used in your FEA model otherwise it can caused unbalanced internal forces in exported connections.

# The `transformCoordsystem` input says whether the member should be assigned based on a standard vertical member axis system or not.

def CreateLineSegment3D(startNode, endNode, transformCoordSystem):
    
    segment3D = IOM.Geometry3D.LineSegment3D()
    
    segmentid = model.GetMaxId(segment3D) + 1
    segment3D.Id = segmentid
    
    st = next((x for x in model.Point3D if x.Id == startNode), None)
    end = next((x for x in model.Point3D if x.Id == endNode), None)
    segment3D.StartPoint = IOM.ReferenceElement(st)
    segment3D.EndPoint = IOM.ReferenceElement(end)

    if transformCoordSystem:
        system = IOM.Geometry3D.CoordSystemByPoint()
        pointref =  IOM.Geometry3D.Point3D()
        pointref.X = 100000
        pointref.Y = 0
        pointref.Z = 0
        system.Point = pointref
        system.InPlane = IOM.Geometry3D.Plane.ZX;
        segment3D.LocalCoordinateSystem = system;

    return segment3D;

Member Helper Functions

Below are two helper functions that allow for the required elements of a member to be automatically created. The first helper function will create a member between two nodes only, while the second creates a continuous member with an intermediate node.


#Creates a member with only a start and end point
def CreateSingleMember(memberType, startNode, endNode):
    member = IOM.Model.Member1D()
    
    columnLCS = False
    
    if memberType == "C":
        columnLCS = True
    
    #create line segment
    line = CreateLineSegment3D(startNode, endNode, columnLCS)
    model.AddObject(line)
    
    #create Element
    element = IOM.Model.Element1D()
    elementid = model.GetMaxId(element) + 1
    element.Id = elementid
    element.Name = "E{0}".format(elementid)
    element.Segment = IOM.ReferenceElement(line)
    
    model.AddObject(element)
    
    #assign Elements
    member.Elements1D.Add(IOM.ReferenceElement(element))
    
    return member
    
#Creates a member with a start an end and a middle point
def CreateDoubleMember(memberType, startNode, middleNode, endNode):
    member = IOM.Model.Member1D()
    
    columnLCS = False
    
    if memberType == "C":
        columnLCS = True                      
                          
    #create line segments
    line1 = IOM.Geometry3D.LineSegment3D()
    line2 = IOM.Geometry3D.LineSegment3D()
    
    line1 = CreateLineSegment3D(startNode, middleNode, columnLCS)
    model.AddObject(line1)
    
    line2 = CreateLineSegment3D(middleNode, endNode, columnLCS)
    model.AddObject(line2)
    
    #create Element 1
    element1 = IOM.Model.Element1D()
    elementid = model.GetMaxId(element1) + 1
    element1.Id = elementid
    element1.Name = "E{0}".format(elementid)
    element1.Segment = IOM.ReferenceElement(line1)
    
    model.AddObject(element1)
    
    #create Element 1
    element2 = IOM.Model.Element1D()
    elementid = model.GetMaxId(element2) + 1
    element2.Id = elementid
    element2.Name = "E{0}".format(elementid)
    element2.Segment = IOM.ReferenceElement(line2)
    
    model.AddObject(element2)
    
    #assign Elements
    member.Elements1D.Add(IOM.ReferenceElement(element1))
    member.Elements1D.Add(IOM.ReferenceElement(element2))
    
    return member
    

Create Members

Using the helper functions defined above we will create and add members to the model based on the basic input provided below. Here the 'B' defined at the start of the list denotes a beam and the 'C' denotes a column. The Integers denote the start, intermediate (if any) and end nodes.

[["B",2,4],["B",4,6],["C",1,2,7],["C",3,4,8],["C",5,6,9],["B",7,8,9]]


#For simplicity create a List of List of the Member Type and Start, Middle and End Nodes
memberNodeDefs = [["B",2,4],["B",4,6],["C",1,2,7],["C",3,4,8],["C",5,6,9],["B",7,8,9]]

#We can retrieve the appropriate cross-sections from the Model that we want to apply to the beams and columns respectively.
css_he_200b = next((x for x in model.CrossSection if x.Name == "HE200B"), None) 
css_he_240b = next((x for x in model.CrossSection if x.Name == "HE240B"), None) 

#create all members
for i, memberDef in enumerate(memberNodeDefs):
    memberType = memberDef[0]
    memberid = i+1
    
    member = IOM.Model.Member1D()
    
    if len(memberDef) < 4:
        member = CreateSingleMember(memberType, memberDef[1], memberDef[2])
    else:
        member = CreateDoubleMember(memberType, memberDef[1], memberDef[2], memberDef[3])  
    
    member.Name = "M{0}".format(i+1)
    member.Id = i+1
    
    if memberType == "C":
        member.Member1DType = IOM.Model.Member1DType.Column
        member.CrossSection = IOM.ReferenceElement(css_he_240b)
    else:
        member.Member1DType = IOM.Model.Member1DType.Beam
        member.CrossSection = IOM.ReferenceElement(css_he_200b)
        
    model.AddObject(member)

Loading of the Steel Frame

Define Load Groups and Load Cases

# Create the load group for permanent load cases
LG1 = IOM.Loading.LoadGroupEC()
LG1.Id = 1
LG1.Name = "PERM1"
LG1.Relation = IOM.Loading.Relation.Standard
LG1.GroupType = IOM.Loading.LoadGroupType.Permanent
LG1.GammaQ = 1.35
LG1.Dzeta = 0.85
LG1.GammaGInf = 1
LG1.GammaGSup = 1.35
model.AddObject(LG1)

# Create the second load group for variable loadcases
LG2 = IOM.Loading.LoadGroupEC()
LG2.Id = 2;
LG2.Name = "VAR1";
LG2.Relation = IOM.Loading.Relation.Exclusive;
LG2.GroupType = IOM.Loading.LoadGroupType.Variable;
LG2.GammaQ = 1.5;
LG2.Dzeta = 0.85;
LG2.GammaGInf = 0;
LG2.GammaGSup = 1.5;
LG2.Psi0 = 0.7;
LG2.Psi1 = 0.5;
LG2.Psi2 = 0.3;
model.AddObject(LG2);


# Create the first load case representing SelfWeight
LC1 = IOM.Loading.LoadCase()

LC1.Id = 1
LC1.Name = "SelfWeight"
LC1.LoadType = IOM.Loading.LoadCaseType.Permanent
LC1.Type = IOM.Loading.LoadCaseSubType.PermanentStandard
LC1.Variable = IOM.Loading.VariableType.Standard
LC1.LoadGroup = IOM.ReferenceElement(LG1)

# Create the second load case representing Pernament Loading
LC2 = IOM.Loading.LoadCase()

LC2.Id = 2
LC2.Name = "PernamentLoading"
LC2.LoadType = IOM.Loading.LoadCaseType.Permanent
LC2.Type = IOM.Loading.LoadCaseSubType.PermanentStandard
LC2.Variable = IOM.Loading.VariableType.Standard
LC2.LoadGroup = IOM.ReferenceElement(LG1)

# Create the third load case representing LiveLoad
LC3 = IOM.Loading.LoadCase()

LC3.Id = 3
LC3.Name = "LiveLoad"
LC3.LoadType = IOM.Loading.LoadCaseType.Variable
LC3.Type = IOM.Loading.LoadCaseSubType.VariableStatic
LC3.Variable = IOM.Loading.VariableType.Standard
LC3.LoadGroup = IOM.ReferenceElement(LG2)

# Add load cases to the model
model.AddObject(LC1);
model.AddObject(LC2);
model.AddObject(LC3);

Define Load Combinations

# create first combination input
CI1 = IOM.Loading.CombiInputEC()

CI1.Id = model.GetMaxId(CI1) + 1
CI1.Name = "Co.#1"
CI1.Description = "SelfWeight + PernamentLoading + LiveLoad"
CI1.TypeCombiEC = IOM.Loading.TypeOfCombiEC.ULS
CI1.TypeCalculationCombi = IOM.Loading.TypeCalculationCombiEC.Linear

item = IOM.Loading.CombiItem()
item.Id = 1;
item.Coeff = 1.35;
item.LoadCase = IOM.ReferenceElement(next((x for x in model.CrossSection if x.Name == "SelfWeight"), None));
CI1.Items.Add(item);

item = IOM.Loading.CombiItem();
item.Id = 2;
item.Coeff = 1.35;
item.LoadCase = IOM.ReferenceElement(next((x for x in model.CrossSection if x.Name == "PernamentLoading"), None));
CI1.Items.Add(item);

item = IOM.Loading.CombiItem();
item.Id = 3;
item.Coeff = 1.5;
item.LoadCase = IOM.ReferenceElement(next((x for x in model.CrossSection if x.Name == "LiveLoad"), None));
CI1.Items.Add(item);

model.AddObject(CI1);

#create second combination input
CI2 = IOM.Loading.CombiInputEC()

CI2.Id = model.GetMaxId(CI2) + 1
CI2.Name = "Co.#2"
CI2.Description = "SelfWeight"
CI2.TypeCombiEC = IOM.Loading.TypeOfCombiEC.ULS
CI2.TypeCalculationCombi = IOM.Loading.TypeCalculationCombiEC.Linear

item = IOM.Loading.CombiItem();
item.Id = 1;
item.Coeff = 1;
item.LoadCase = IOM.ReferenceElement(next((x for x in model.CrossSection if x.Name == "SelfWeight"), None));
CI2.Items.Add(item);

model.AddObject(CI2);

IOM Model Results

We will not define the results here but results can also be created using this means. We will reference a previously defined result file for this example. You can find some further information here:

https://github.com/idea-statica/ideastatica-public/tree/main/src/Examples/IOM

Congratulations, you have created an IOM Model from Scratch. Now let's define a Connection Point to allow us to import into IDEA StatiCa Connection.

Define a Connection within the Model

Now that the model has been created we should define a connection point and add the relevant members to it. A connection is defined by its reference node and connected members. A member can be ended or continuous.

# create a connection point
CP1 = IOM.Connection.ConnectionPoint()

CP1.Node = IOM.ReferenceElement(next((x for x in model.Point3D if x.Name == "N2"), None));
conId = model.GetMaxId(CP1) + 1;
CP1.Id = conId;
CP1.Name = "CON {0}".format(conId);

# members from the previous section
# Let's get the members we want to connect in the connection. These will be M1 and M3. M3 will be continuous in the Connection while M1 will be ended.

connectedMem1 = IOM.Connection.ConnectedMember()
connectedMem1.IsContinuous = False;
connectedMem1.Id = 1;
connectedMem1.MemberId = IOM.ReferenceElement(next((x for x in model.Member1D if x.Name == "M1"), None))

connectedMem3 = IOM.Connection.ConnectedMember()
connectedMem3.IsContinuous = True;
connectedMem3.Id = 3;
connectedMem3.MemberId = IOM.ReferenceElement(next((x for x in model.Member1D if x.Name == "M3"), None))

CP1.ConnectedMembers.Add(connectedMem1);
CP1.ConnectedMembers.Add(connectedMem3);

model.AddObject(CP1);

Defining the ConnectionData

We can now add additional connection data such as beam information, Plate, Bolt, Weld, and Cut information. We will only add some basic beam information here. Further information on adding additional info is explained here: https://github.com/idea-statica/ideastatica-public/tree/main/src/Examples/IOM

conData = IOM.Connection.ConnectionData()

beamData = List[IOM.Connection.BeamData]()

beamData1 = IOM.Connection.BeamData()
beamData1.Id = 1
beamData1.Name = "M1"
beamData1.OriginalModelId = "1"

beamData2 = IOM.Connection.BeamData()
beamData2.Id = 3
beamData2.Name = "M3"
beamData2.OriginalModelId = "3"

beamData.Add(beamData1)
beamData.Add(beamData2)

conData.Beams = beamData

model.Connections.Add(conData)

Saving the Model

Let's save the final model to drive.

model.SaveToXmlFile('IOM-SteelFrame.xml')

Congratulations, you have successfully created an IOM model and a connection point that can be imported into IDEA StatiCa Connection.

Using IDEA Plugin to Generate the Connection

Using the clr we need to reference the IdeaStatiCa.Plugin dll from the Idea Directory.

Then Plugin Namespace we need to import the ConnHiddenClientFactory. The Client Factory allows us to safely create connection clients that we can use to interact with IDEA Connection.

clr.AddReference('IdeaStatiCa.Plugin')

from IdeaStatiCa.Plugin import ConnHiddenClientFactory

We then again need to provide the path to the Client Factory and safely create a client.

factory = ConnHiddenClientFactory(idea_path)
client = factory.Create()

Finally, create an Idea Connection file from an IOM referencing the saved filepath of the model, results and a new filepath to save the IDEA Connection (. IdeaCon) file to.

client.CreateConProjFromIOM('IOM-SteelFrame.xml', 'IOM-SteelFrame.xmlR', 'SteelFrame.ideaCon')

# Ensure closing of any open project and flush the client.
client.CloseProject()
client.Close()