sap2000自带的python开发小例子

案例背景

​ 这个例子的来源是sap2000的验证问题示例1-001,例子通过从头开始创建示例来验证软件计算问题,通过运行分析、提取结果并将软件计算结果与手算的值进行比较。例子比较简短,适合用来做相应的测试与后面的学习拓展。

步骤详解

打开软件

​ 需要安装python的comtypes包,通过comtypes库提供的CreateObject创建Sap2000的实例,函数参数为所要创建的应用程序类名,先尝试打开已经运行的sap2000,如果没有,就再打开新的sap2000。以下的代码就是为了实现这个过程,这里是考虑到了各种可能的情况,实际使用的时候往往不需要这么复杂(比如直接开一个活动模型)。

# 导入需要的模块
# os模块负责程序与操作系统的交互,提供访问操作系统底层的接口
import os
# sys模块负责程序与python解释器的交互,提供一系列的函数和变量,用于操控python的运行时的环境(访问python编译器使用的变量及交互函数)
import sys 
# comtypes包是纯python,轻量级的COM客户端和服务框架,基于ctypes的Python的FFI包,可以在python的环境中使用该包的各类模块
import comtypes.client

# 程序启动新的实例
AttachToInstance = False
# 是否指明程序的路径
SpecifyPath = False
# 程序路径
ProgramePath = "D:\Program Files\Computers and Structures\SAP2000 24\SAP2000.exe"
# 创建API文件的地址(所需要存储的目标地址,这个可以自定义)
APIPath = 'E:\SAP2000APItest\Example3'

# os.path模块主要用于文件的属性获取
# 如果系统中的'APIPath'这个文件夹的路径不存在,直接报一个"OSError"然后程序终止
if not os.path.exists(APIPath):
    try:
        os.makerdirs(APIPath)
    except OSError:
        pass
# os.sep表示分隔符/或者\,在后续需要添加子文件夹或者读取文件夹下的所有的文件,需要加上相应的分隔符
ModelPath = APIPath +os.sep +'test03.sdb'

helper = comtypes.client.CreateObject('SAP2000v1.Helper')
# QueryInterface:可以通过此函数来查询某个组件是否支持某个特定的接口
# 导入comtypes.client会自动创建comtypes.gen子包
# 若支持QueryInterface将返回一个指向些接口的指针,不支持返回值将是一个错误代码
helper = helper.QueryInterface(comtypes.gen.SAP2000v1.cHelper)

if AttachToInstance:
    # 附加到正在运行的sap2000实例中来,需要获取相应的参数(活动模型)
    try:
        mySapObject = helper.Getobject('CSI.SAP2000.API.SapObject')
    except (OSError,comtypes.COMError):
        # 找不到正在运行的实例或未能附加
        print('No running instance of the programe found or failed to attach.')
        sys.exit(-1)
else:
# 此时需要启动新的sap2000,主要有一下的两种方式
# 1、使用函数helper.CreateObject(ProgramPath),根据程序文件路径建立SapObject实例
# 2、使用helper.CreatObjectProgID('CSI.SAP2000.API.SapObject')函数根据软件的program ID启动建立SapObject实例
    if SpecifyPath:
        try:
            mySapObject = helper.CreatObject(ProgramePath)
        except(OSError,comtypes.COMError):
            print('Cannot start a new instance of the program from" + ProgramPath')
            sys.exit(-1)
    else:
        try:
            mySapObject = helper.CreateObjectProgID('CSI.SAP2000.API.SapObject')
        except(OSError,comtypes.COMError):
            print('Cannot start a new instance of the program')
            sys.exit(-1)
        # 最后通过mySapObject.ApplicationStart()函数启动sap2000
        mySapObject.ApplicationStart()

创建一个新的空白模型

SapModel = mySapObject.SapModel
SapModel.InitializeNewModel()
ret = SapModel.File.NewBlank()

定义各项同性属性数据

#assign isotropic mechanical properties to material
# 将各项力学性能指定给材质,相关的4个参数分别为:材质名称、弹性模量、泊松比、热膨胀系数
ret = SapModel.PropMaterial.SetMPIsotropic('CONC',3600,0.2,5.5E-6)

设置截面的属性修正

​ 添加自定义材料使用SapModel.PropMaterial.SetMaterial函数,然后根据材料类型设置参数,使用set开头的函数进行材料参数的设置(例如使用SapModel.PropMaterial.SetMpIsotropic函数设置材料的弹性模量、泊松比、热膨胀系数,函数的具体使用需要查看相关的函数说明:最大的资料就是帮助文档,也是最原始最全面的文档)。

在截面定义这一块主要是截面定义、编辑、删除、参数设置等,每种类型的截面均有单独的定义函数,具体可以查看以set开头的函数(这里面的截面种类还是特别特别的多的,值得自己去注意)

代码层面

# 修改截面的属性
ModValue = [1000,0,0,1,1,1,1,1,1]
ret = SapModel.PropFrame.SetModifiers('R1',ModValue)

软件操作层面

然后就是构件的绘制:在帮助文件中查看Frame单元的相关函数,包括单元绘制、荷载指定以及相关参数的调整一种是通过坐标值建立杆件另一种通过节点编号建立杆件

通过坐标系来添加框架单元

代码部分:这里主要通过坐标值来添加Frame单元,使用函数SapModel.FrameObj.AddByCoord通过坐标值添加杆件,FrameName1为ByRef变量,要得到在函数中改变后的值,需要将变量名放在等号的左侧得到改变后的值。在建模的过程中,可以随时根据需要调整模型的单位制,使用函数SapModel.SetPresentUnits()设置当前单位制,此后的代码输入的数据要与设置的单元相统一。

# 通过坐标系来添加框架单元
FrameName1,FrameName2,FrameName3 = '' , '' , ''
[FrameName1,ret] = SapModel.FrameObj.AddByCoord(0,0,0,0,0,10,FrameName1,'R1','1','Global')
[FrameName2,ret] = SapModel.FrameObj.AddByCoord(0,0,10,8,0,16,FrameName2,'R1','2','Global')
[FrameName3,ret] = SapModel.FrameObj.AddByCoord(-4,0,10,0,0,10,FrameName3,'R1','3','Global')

施加基础节点约束

使用SapModel.FrameObj.GetPoints函数得到杆件端部的节点编号,使用SapModel.PointObj.SetRestraint函数设定节点的约束条件

代码部分

# 施加节点约束
PointName1 , PointName2 = '', ''
# 指定节点约束为u1,u2,u3.r1,剩余的方向全部释放约束
Restraint = [True,True,True,True,False,False]
# 获取FrameName1的节点1和节点2,并将其中的节点1设置为定义好的约束形式
[PointName1,PointName2,ret] = SapModel.FrameObj.GetPoints(FrameName1,PointName1,PointName2)
ret = SapModel.PointObj.SetRestraint(PointName1,Restraint)

# 同样的方式对FrameName2的节点2施加节点约束
Restraint = [True,True,False,False,False,False]
[PointName1,PointName2,ret] = SapModel.FrameObj.GetPoints(FrameName2,PointName1,PointName2)
ret = SapModel.PointObj.SetRestraint(PointName2,Restraint)

软件操作部分:略

设置7种荷载模式

  1. 使用函数SapModel.PointObj.SetLoadForce为节点指定集中荷载
  2. 使用函数SapModel.FrameObj.SetLoadDistributed函数指定杆件上的均布荷载
# 添加荷载模式
# 选定荷载模式为第八种的Other方式
LTYPE_OTHER = 8

# 设置名称为1~7的荷载模式
ret = SapModel.LoadPatterns.Add('1',LTYPE_OTHER,1,True)
ret = SapModel.LoadPatterns.Add('2',LTYPE_OTHER,0,True)
ret = SapModel.LoadPatterns.Add('3',LTYPE_OTHER,0,True)
ret = SapModel.LoadPatterns.Add('4',LTYPE_OTHER,0,True)
ret = SapModel.LoadPatterns.Add('5',LTYPE_OTHER,0,True)
ret = SapModel.LoadPatterns.Add('6',LTYPE_OTHER,0,True)
ret = SapModel.LoadPatterns.Add('7',LTYPE_OTHER,0,True)

施加荷载

# 以下为施加荷载的一些过程
# 对FrameName3的节点1施加荷载模式名称为2的集中荷载
[PointName1,PointName2,ret] = SapModel.FrameObj.GetPoints(FrameName3,PointName1,PointName2)
PointLoadValue = [0,0,-10,0,0,0]
ret = SapModel.PointObj.SetLoadForce(PointName1,'2',PointLoadValue)
# 对FrameName3施加荷载模式名称为2的分布荷载(重力方向)
ret = SapModel.FrameObj.SetLoadDistributed(FrameName3,'2',1,10,0,1,1.8,1.8)

# 对FrameName3的节点2施加荷载模式名称为3的集中荷载
[PointName1,PointName2,ret] = SapModel.FrameObj.GetPoints(FrameName3,PointName1,PointName2)
PointLoadValue = [0,0,-17.2,0,-54.4,0]
ret = SapModel.PointObj.SetLoadForce(PointName2,'3',PointLoadValue)

# 对FrameName2施加荷载模式名称为4的分布荷载(重力投影方向)
ret = SapModel.FrameObj.SetLoadDistributed(FrameName2,'4',1,11,0,1,2,2)


# 对FrameName1,2施加荷载模式名称为5的分布荷载(坐标系选择局部坐标系:2轴)
ret = SapModel.FrameObj.SetLoadDistributed(FrameName1,'5',1,2,0,1,2,2,'Local')
ret = SapModel.FrameObj.SetLoadDistributed(FrameName2,'5',1,2,0,1,-2,-2,'Local')

# 对FrameName1,2施加荷载模式名称为6的分布荷载(坐标系选择局部坐标系:2轴)
ret = SapModel.FrameObj.SetLoadDistributed(FrameName1,'6',1,2,0,1,0.9984,0.3744,'Local')
ret = SapModel.FrameObj.SetLoadDistributed(FrameName2,'6',1,2,0,1,-0.3744,0,'Local')

# 对FrameName2施加荷载模式名称为7的跨中的集中荷载(局部二轴方向)
ret = SapModel.FrameObj.SetLoadPoint(FrameName2,'7',1,2,0.5,-15,'Local')

软件中的施加

对于荷载模式6:

  1. 在框架1左端的荷载为0.9987,右端的荷载为0.3744
  2. 在框架2左端的荷载为-0.3744,右端为0

对于荷载模式7:在框架2的跨中位置施加集中荷载

保存并创建分析模型

# 保存模型
set = SapModel.File.Save(ModelPath)
# 运行模型,在分析的过程中会创建一个分析模型
set = SapModel.Analyze.RunAnalysis()

初始化sap2000的计算结果

# 初始化sap2000的计算结果,结合后面的代码,这里主要是想输出不同荷载模式下的FrameName2的节点2的位移。
SapResult = [0,0,0,0,0,0,0]
[PointName1,PointName2,ret] = SapModel.FrameObj.GetPoints(FrameName2,PointName1,PointName2)

初始化荷载模式从1~7的sap2000的计算结果:这里采用的是for循环的方式保存建立的模型,并进行分析,在分析完成后提取工况下的位移结果,使用SapModel.Results.JointDispl函数得到节点位移结果,在输出位移结果前,清除设置的荷载工况,然后在设置要输出结果的荷载工况再使用节点位移函数输出结果,保存建立的模型,并运行分析,分析完成后读取某一节点所有工况的位移

# 初始化荷载模式1~7的sap2000的计算结果
for i in range(0,7):
    NumberResults = 0
    # 对象,单元,工况、分析步类型、分析步数量以及6个方向的位移
    Obj,Elm,ACase,StepType,StepNum,U1,U2,U3,R1,R2,R3 = [],[],[],[],[],[],[],[],[],[],[]
    ObjectElm = 0
    # 对于输出的结果:删除所有对荷载模式和荷载组合的选择
    ret = SapModel.Results.Setup.DeselectAllCasesAndCombosForOutput()
    # 按照循环来选择相应的荷载和荷载组合,将7个荷载模式都循环一遍
    ret = SapModel.Results.Setup.SetCaseSelectedForOutput(str(i+1))

    # 运行前四个荷载模式
    if i <=3:
        [NumberResult,Obj,Elm,ACase,StepType,StepNum,U1,U2,U3,R1,R2,R3,ret] = SapModel.Results.JointDispl(PointName2,ObjectElm,NumberResults,Obj,Elm,ACase,StepType,StepNum,U1,U2,U3,R1,R2,R3)
        # 提取前三个荷载模式下的Z方向的节点位移
        SapResult[i] = U3[0]
    # 运行后面的三个荷载模式
    else:
        [NumberResult,Obj,Elm,ACase,StepType,StepNum,U1,U2,U3,R1,R2,R3,ret] = SapModel.Results.JointDispl(PointName1,ObjectElm,NumberResults,Obj,Elm,ACase,StepType,StepNum,U1,U2,U3,R1,R2,R3)
        # 提取后四个荷载模式下的X方向的节点位移
        SapResult[i] = U1[0]

对结果进行相应的打印

# 填写独立的结果,因为有七个荷载模式,组成了一个数组
IndResult = [0,0,0,0,0,0,0]
IndResult[0] = -0.02639
IndResult[1] = 0.06296
IndResult[2] = 0.06296
IndResult[3] = -0.2963
IndResult[4] = 0.3125
IndResult[5] = 0.11556
IndResult[6] = 0.00651

# 填写差异百分比
PercentDiff = [0,0,0,0,0,0,0]
for i in range(0,7):
    PercentDiff[i] = (SapResult[i]/IndResult[i])-1
for i in range(0,7):
    # 换行并分别打印:sap2000的计算结果、独立的结果(手算)以及相应的差异百分比
    print()
    print(SapResult[i])
    print(IndResult[i])
    print(PercentDiff[i])
  1. 第一行是软件计算结果
  2. 第二行是手算结结果
  3. 第三行是误差百分比
-0.026389708333499594  
-0.02639
-1.1052159924473948e-05

0.0629596111115078     
0.06296
-6.1767549587310455e-06

0.0629596111115078     
0.06296
-6.1767549587310455e-06

-0.2963018518537188    
-0.2963
6.249928176993436e-06  

0.3125018518538204
0.3125
5.92593222537019e-06

0.11555582518591315
0.11556
-3.612680933584578e-05

0.006511371527818799
0.00651
0.0002106801564976113

后记

​ 后续话还需要进行相应的输出,还是以例子的形式展示出来。

ToTOP