慢慢来吧,有空的时候就整,这肯定也是一个比较好的方向,值得自己去积累与深挖的方向,并且自己要形成一些相应的标准文件来巩固自己所学。

通过api,用户可以编写程序控制sap2000,调用软件中的各种功能,实现自动建模自动分析自动调整参数迭代运行,而且自己也一直在不停的往前学,往深的方向进行专研。

pywin32库
为python提访问windows api的扩展,提供了非常完整的window常量接口线程以及com机制

系统单位值:

备注:主要有16种方式,在平时的使用种主要用到的是这样的几种:5、6、9、10
lb_in_F = 1
lb_ft_F = 2
kip_in_F = 3
kip_ft_F = 4
kN_mm_C = 5
kN_m_C = 6
kgf_mm_C = 7
kgf_m_C = 8
N_mm_C = 9
N_m_C = 10
Ton_mm_C = 11
Ton_m_C = 12
kN_cm_C = 13
kgf_cm_C = 14
N_cm_C = 15
Ton_cm_C = 16

访问sap2000

根据自己的整理,这里主要提供了以下的两种方式:
方式一:

# os模块负责程序与操作系统的交互,提供了访问操作系统底层的接口
# This module provides a portable way of using operating system dependent functionality.
import os
# sys模块负责程序与python解释器的交互,提供了一系列的函数和变量,用于操控python的运行时环境
# This module provides access to some variables used or maintained by the interpreter and to functions that interact strongly with the interpreter
import sys
import comtypes.client
# comtypes包是纯python,轻量级的COM客户端和服务框架,基于ctypes的Python的FFI包,可以在python的环境中使用该包的各类模块
import comtypes

# 首先根据类名建立COM对象,SAP2000的类名为SAP2000v1.Helper
# creat_com_object
helper = comtypes.client.CreateObject('SAP2000v1.Helper')

# 1.根据路径来运行
# 使用函数CreateObject打开软件
ProgramPath = 'D:\Program Files\Computers and Structures\SAP2000 24\SAP2000.exe'
mySapObject = helper.CreateObject(ProgramPath)

# 2.根据程序ID打开软件
mySapObject = helper.CreateObjectProgID("CSI.SAP2000.API.SapObject")

# 使用ApplicationStart函数运行SAP2000软件,并指定单位制
mySapObject.ApplicationStart(9)
SapModel = mySapObject.SapModel

方式二:其实差不多,可能是写法略微有点区别

import os
import sys
import comtypes.client
import comtypes

helper = comtypes.client.CreateObject('CSiAPIv1.Helper')
mySapObject = helper.CreateObject(r"D:\Program Files\Computers and Structures\SAP2000 24\SAP2000.exe")
#mySapObject = helper.CreateObjectProgID("CSI.SAP2000.API.SapObject")

mySapObject.ApplicationStart()
SapModel = mySapObject.SapModel

以下为一些非常简单的常规操作,也作为一个平时的记录点写下来,方便后面自己来查阅,侧重点是代码的理解与运行,并且都是自己调试过的,也大致能够理解的,能够有一些相应的实际意义的。

定义材料与截面

定义材料

在CSI_OAPI_Documentation开发文件中的CSI OAPI Functions-Definitions-Properties-Material中查看材料定义相关的函数
对于几种材料的编号要清楚:

  1. MATERIAL_STEEL(钢材)
  2. MATERIAL_CONCRETE(混凝土)
  3. MATERIAL_NODESIGN(自定义)
  4. MATERIAL_ALUMINUM(铝合金)
  5. MATERIAL_COLDFORMED(冷弯薄壁型钢)
  6. MATERIAL_REBAR(钢筋)
  7. MATERIAL_TENDON(钢索)

使用SapModel.PropMaterial.AddMaterial函数添加材料,例如添加C20混凝土

name=""
name,ret=SapModel.PropMaterial.AddMaterial(name,2,""china,"GB","GB50010 C20" )

该函数主要有6个参数:Name,MatType,Region,Standard,Grade,UserName

  1. Name为返回的材料名,为ByRef类型,该参数要按照引用的方式传递,在函数中修改这个值会造成实参的值发生相应的改变
  2. MatType为材料类型
  3. Region,Standard,Grade为一些材料的具体参数
  4. UserName 为用户指定的材料名,为可选参数(Optional ByVal),如果不传递就会使用默认值

如果添加多种材料,可以使用循环语句:

names = ["Q235","Q355","Q420","Q460"]
for mname in names:
    name,ret=SapModel.PropMaterial.AddMaterial(name,1,"china","GB",mname)

添加截面

在CSI_OAPI_Documentation开发文件中的CSi OAPI Functions-Definitions-Properties-Frame中查看框架截面定义相关的函数。
通过API函数可以查询当前模型定义的截面、添加截面以及修改截面

混凝土截面添加

矩形:SetRecangle函数
圆形:SetCircle函数

SapModel.PropFrame.SetRectangle("Beam500x300","C30",0.5,0.3)
SapModel.PropFrame,SetRecTangle("Col500x300","C30",0.5,0.5)
# 混凝土的配筋信息使用SetRebarBeam和SetRebarColumn函数
SapModel.PropFrame.SetRebarBeam("Beam500X300","HPB300","HPB300",0.002,0.002,0.00005,0.00005,0.00005,0.00005)
SapModel.PropFrame.SetRebarColumn("Col500X500","HPB300","HPB300",1,1,0.02,0,3,3,"10d","10d",0,2,2,False)

钢结构截面的定义

型钢库截面导入

# 方法一:采用老版的pro格式的
SapModel.PropFrame.ImportProp("L20X3","Q235","ChineseGB08.pro","L20x3")
# 方法二:采用新版的xml格式的
ret = SapModel.PropFrame.ImportProp("L30X3","Q235","D:\Program Files\Computers and Structures\SAP2000 24\Property Libraries\Sections\ChineseGB08.xml","L30X3")

角钢截面

SapModel.PropFrame.SetAngle("L60X5","Q235",0.06,0.06,0.005,0.005)

圆管截面

SapModel.ProFrame.SetPipe("P100X2","Q235",100,2)

杆件绘制

采用点的方式

在CSi OAPI Functions-Objects Model-Point object中查看Point绘制的函数

  1. SapModel.PointObj.AddCartesian
  2. SapModel.PointObj.AddCylindrical
  3. SapModel.PointObj.AddSpherical

按照笛卡尔坐标

Name = ""
locZ = 1
for step in range(4):
    name,ret=SapModel.PointObj.AddCartesian(1,1,1+locZ*step,Name)

其他的几种方式省略

打开文件并获取杆件的数量以及标签

参考链接:https://mp.weixin.qq.com/s/zn8QVG1aOtLgZD6swVdlTA

import comtypes.client
import sys
# 这里采用try except的方式就可以以两种方式打开sap2000,当目前有打开的sap2000时直接获取当前的COM对象,如果提示为"OSError, comtypes.COMError",直接根据程序的地址来创建COM对象
try:
    #获得当前运行的COM对象
    mySapObject = comtypes.client.GetActiveObject('CSI.SAP2000.API.SapObject')
# 如果当前没有运行的com对象,就直接打开sap2000程序
except(OSError, comtypes.COMError):
    #指定SAP2000运行地址
    ProgramPath = 'D:\Program Files\Computers and Structures\SAP2000 24\SAP2000.exe'
    #根据ID值创建COM对象,SAP2000ID值为SAP2000v1.Helper
    helper = comtypes.client.CreateObject('SAP2000v1.Helper')
    #查询目标接口
    # QueryInterface客户可以通过此函数来查询某个组件是否支持某个特定的接口
    # comtypes.gen是子包,导入comtypes.client会自动创建
    helper = helper.QueryInterface(comtypes.gen.SAP2000v1.cHelper)
    # 采用指定运行路径的方式运行 SAP2000
    # 当所给定的路径不对的时候,程序也会报错,此时再嵌套一个try except语句,并打印"当前的路径无法打开主程序"
    try:
        mySapObject = helper.CreateObject(ProgramPath)
    except (OSError, comtypes.COMError):
        print("Cannot start a new instance of the program from " + ProgramPath)
        # 非正常退出程序
        sys.exit(-1)

# 使用ApplicationStart函数运行sap2000软件,并指定单位制(此处按的默认值)
mySapObject.ApplicationStart()
#生成SapModel
SapModel = mySapObject.SapModel
#模型文件
FilePath = r'E:\光伏支架相关文档\贵州光伏\贵州光伏(导入截面)\贵州光伏(导入截面).sdb'
#打开模型文件
SapModel.File.OpenFile(FilePath)
##获得模型杆件数量并显示
FrameNum = 0
NameList = []
ret = 1
[FrameNum,NameList,ret] = SapModel.FrameObj.GetNameList(FrameNum,NameList)
print("杆件总数:",FrameNum)
print("构件列表:\n",NameList)
input("Press Any Key")

运行sap2000软件,打开指定的模型文件,并读取模型中的构件数

import comtypes.client
import sys
try:
    #获得当前运行的COM对象
    mySapObject = comtypes.client.GetActiveObject('CSI.SAP2000.API.SapObject')
except(OSError, comtypes.COMError):
    #指定SAP2000运行地址
    ProgramPath = 'D:\Program Files\Computers and Structures\SAP2000 24\SAP2000.exe'
    #根据ID值创建COM对象,SAP2000ID值为SAP2000v1.Helper
    helper = comtypes.client.CreateObject('SAP2000v1.Helper')
    #查询目标接口
    helper = helper.QueryInterface(comtypes.gen.SAP2000v1.cHelper)
    # 采用指定运行路径的方式运行 SAP2000
    try:
        mySapObject = helper.CreateObject(ProgramPath)
    except (OSError, comtypes.COMError):
        print("Cannot start a new instance of the program from " + ProgramPath)
        sys.exit(-1)

mySapObject.ApplicationStart()
#生成SapModel
SapModel = mySapObject.SapModel
#模型文件
FilePath = r'E:\光伏支架相关文档\贵州光伏\贵州光伏(导入截面)\贵州光伏(导入截面).sdb'
#打开模型文件
SapModel.File.OpenFile(FilePath)
##获得模型杆件数量并显示
FrameNum = 0
NameList = []
ret = 1
[FrameNum,NameList,ret] = SapModel.FrameObj.GetNameList(FrameNum,NameList)
print("杆件总数:",FrameNum)
print("构件列表:\n",NameList)
input("Press Any Key")

以一根梁为例进行分析

import comtypes.client
import sys
import os

# 获取当前运行的sap2000
SapObject = comtypes.client.GetActiveObject("CSI.SAP2000.API.SapObject")

#create SapModel object(创建模型对象)
SapModel = SapObject.SapModel

#initialize model(初始化模型)
SapModel.InitializeNewModel()

#create new blank model(创建新的空白模型)
ret = SapModel.File.NewBlank()
kN_mm_C = 5
ret = SapModel.SetPresentUnits(5)  # 设置模型单位

# 添加材料
MATERIAL_STEEL=1 #钢材
MATERIAL_CONCRETE = 2 #混凝土
MATERIAL_BEBAR = 8 # 钢筋
mat="C40"
ret = SapModel.PropMaterial.AddMaterial(mat,2,"china","GB","GB50010 C40")

# 定义框架截面属性
sec = "300x700"
ret = SapModel.PropFrame.SetRectangle(sec,"C40",700,300)

# 布置框架截面
x1,y1,z1=0,0,0
x2,y2,z2=5000,0,0

# 建立一根跨度为5m的梁
SapModel.FrameObj.AddByCoord(x1,y1,z1,x2,y2,z2,"L1",sec,"L1")

# 添加支座约束
Restraint=[True,True,True,False,False,False] # 三平动,三转动,此处为简支梁
PointName1=" "
PointName2=" "
[PointName1,PointName2,ret]=SapModel.Frameobj.GetPoints("L1",PointName1,PointName2)

# 简支梁支座(给两个节点添加设置好的支座)
SapModel.PointObj.SetRestraint(PointName1,Restraint)
SapModel.PointObj.SetRestraint(PointName2,Restraint)

# 定义荷载模式 常用的如下:
# DEAD=1(默认已有) SUPERDEAD(附加恒载)=2,活载2,地震荷载5,用于底部剪力法,按照多质点算的
# 风荷载6,雪荷载7,屋面活荷载11,移动荷载9,温度荷载10
LTYPE_DEAD=1 # 恒载
LTYPE_LIVE=3 # 活荷载
SapModel.LoadPatterns.Add("DEAD1",LTYPE_DEAD,0,True)
SapModel.LoadPatterns.Add("Live",LTYPE_LIVE,0,False) # 自重系数0,flase:不创建荷载工况

# 添加荷载
kN_m_C=6
ret = SapModel.SetPresentUnits(6)
SapModel.FrameObj.SetLoadGravity("L1","DEAD1",0,0,-10,True)

# 保存模型

# path="E:\GHtosap2000\Example2"
# ModelPath = path +os.sep + "test01.sdb"
# SapModel.File.Save(ModelPath)
path=r'E:\GHtosap2000\Example1\test01.sdb'
SapModel.File.Save(path)


# 分析模型
SapModel.Analyze.RunAnalysis()

# 结果查看
SapResult = [0,0,0,0,0,0]
[PointName1,PointName2,ret] = SapModel.FrameObj.GetPoints("L1",PointName1,PointName2)
SapModel.Results.Setup.DeselectAllCasesAndCombosForOutput()  # 取消选择所有工况输出
SapModel.Results.Setup.GetCaseSelectedForOutput("DEAD1") # 选择dead1工况进行输出
ret = SapModel.Results.Setup.SetCaseSelectedForOutput("DEAD1")
NumberResults=0
Obj,Elm,LoadCase,StepType,StepNum,F1,F2,F3,M1,M2,M3,=[],[],[],[],[],[],[],[],[],[],[]
[NumberResults, Obj, Elm, LoadCase, StepType, StepNum, F1, F2, F3, M1, M2, M3,ret] = SapModel.Results.JointReact(PointName1,0,NumberResults, Obj, Elm, LoadCase, StepType, StepNum, F1, F2, F3, M1, M2, M3)
print(F2)
# 关闭sap2000
# SapModel.ApplicationExit(True) # 关闭sap2000
SapModel = 0
SapObject = 0 # 不设置成0应用程序没有完全关闭,仍然占用系统内存

运用python调用sap2000分析一根跨度为6m的梁(非解构)

参考链接:https://mp.weixin.qq.com/s?__biz=MzU0Nzc5MDQxNw==&mid=2247493688&idx=1&sn=d5dae0cc6d51cfae44f3ce46a9c0be68&chksm=fb4ba306cc3c2a101eefeaeda634f2b13b5ac3e409af8b43fda65a1dc72fade9667306b1a7bf&cur_album_id=1323908580084449280&scene=190#rd
备注:我认为这个简单的例子还是非常有实际的意义的,也是一个分析的出发点,而且里面还带有迭代的思想在里面,值得自己先把这些比较小的例子先吃透再来去看那些相对比较复杂的模型的分析,也希望自己能够不断的往前迈出大的步子。相较上一个例子,这一个例子写的就稍微的简练一点并且通用性和迭代性都会强一些。

import os
import sys
import comtypes.client


def Caculation(SapModel,depth,force_z):
    #新建SAP2000模型(初始化模型-创建空白模板)
    SapModel.InitializeNewModel()
    ret = SapModel.File.NewBlank()

    #定义材料
    #AddMaterial
    SapModel.PropMaterial.AddMaterial("C40",2,"China","GB","GB50010 C40")

    #定义截面
    #SetRectangle
    SapModel.PropFrame.SetRectangle("Frame","C40",depth,400)

    #建立模型
    #AddByCoord
    # 用笛卡尔坐标系建立了两个单元,都赋予了Frame截面
    SapModel.FrameObj.AddByCoord(0,0,0,3000,0,0,"element1","Frame","element1")
    SapModel.FrameObj.AddByCoord(3000,0,0,6000,0,0,"element2","Frame","element2")

    #添加约束
    #GetPoints
    #setRestraint
    s_Point1=""
    e_Point1=""
    [s_Point1,e_Point1,ret]=SapModel.FrameObj.GetPoints("element1",s_Point1,e_Point1)

    s_Point2=""
    e_Point2=""
    [s_Point2,e_Point2,ret]=SapModel.FrameObj.GetPoints("element2",s_Point2,e_Point2)

    R=[True,True,True,True,True,True]
    SapModel.PointObj.setRestraint(s_Point1,R)
    SapModel.PointObj.setRestraint(e_Point2,R)

    #添加荷载
    SapModel.LoadPatterns.Add("Live",3)
    # 此处荷载添加竖向的荷载,用froce_z代替
    Load=[0,0,force_z,0,0,0]
    # 将荷载施加在单元1的J端
    SapModel.PointObj.SetLoadForce(e_Point1, "Live", Load)

    #保存模型(自定义一个路径)
    path=r'E:\GHtosap2000\Example2\test02.sdb'
    SapModel.File.Save(path)

    #运行分析
    SapModel.Analyze.RunAnalysis()

    #提取结果
    # 取消勾选所有工况和荷载组合
    SapModel.Results.Setup.DeselectAllCasesAndCombosForOutput()
    # 选择Live组合作为结果输出
    ret = SapModel.Results.Setup.SetCaseSelectedForOutput("Live")
    NumberResults=0
    Obj, Elm, LoadCase, StepType, StepNum, F1, F2, F3, M1, M2, M3=[],[],[],[],[],[],[],[],[],[],[]
    # 提取节点反力 
    #NumberResults:程序返回的结果总数
    #Obj:与每一个结果关联的点对象的名称组成的数组,如果没有关联就默认为0
    #Elm:包含与每个结果关联的点元素名称的数组
    #LoadCase:包含与每个结果关联的分析工况和荷载组合的数组
    #StepType:包含结果每个步骤的数组
    #StepNum:包含每个结果步骤的编号的数组
    #F1,F2,F3:点在局部1 2 3轴的反作用组成的一维数组
    #M1 M2 M3:点在局部1 2 3轴的反作用矩组成的一维数组

    [NumberResults, Obj, Elm, LoadCase, StepType, StepNum, F1, F2, F3, M1, M2, M3,ret] = SapModel.Results.JointReact(s_Point1, 0, NumberResults, Obj, Elm, LoadCase, StepType, StepNum, F1, F2, F3, M1, M2, M3)
    # 由于只关心反作用力,所以就只用打印三个反作用的数值
    print(F1)
    print(F2)
    print(F3)

#获取SAP2000对象
mySapObject = comtypes.client.GetActiveObject("CSI.SAP2000.API.SapObject")
SapModel = mySapObject.SapModel
depths=[500,600,700,800]
force_zs=[1000,2000,3000,4000]
# 修改矩形截面的高度和施加的荷载值分别循环打印以下的一些结果
# 当截面为500x400,施加的力为1000
# 当截面为600x400,施加的力为2000
# 当截面为700x400,施加的力为3000
# 当截面为800x400,施加的力为4000
for i,depth in enumerate(depths):
    force_z=force_zs[i]
    Caculation(SapModel,depth,force_z)

Sap2000自带的python的例子

# 这个例子是sap2000种自带的例子,可以说是一个入门的例子
# 对里面的一些语法值得去推敲然后触类旁通,对其他的一些相应的概念进行扩展开来,对自己后面的深入学习肯定是有帮助的。
import os 
import sys
import comtypes.client

# set the following flag to True to attach to an existing instance of the program
# 将以下的标志设置为True附加到现有的程序实例中来
# otherwise a new instance of the program will be started
# 否则程序将启动新的实例
AttachToInstance = False

# set the follwwing flag to True to manually specify the path to SAP2000.exe
# 将以下的标志设置为True来手动指定SAP2000.exe的路径
# this allows for a connection to a version of SAP200 other than the latest installation
# 这允许连接到除最新安装之外的sap2000版本
# otherwise the latest instaslled version of SAP2000 will be launched
# 否则将启动最新版本的安装
SpecifyPath = False

# if the above flag is set to True,specify the path to SAP2000.exe
# this allows for a connection to a version of SAP2000 other than the latest installation
# 如果上面的标志是True,就指定sap2000程序的运行路径,允许连接到除最新安装之外的sap2000的版本
ProgramPath = 'D:\Program Files\Computers and Structures\SAP2000 24\SAP2000.exe'

# full path to the model 模型的完整路径
# set it to the desired path of your model  将其设置为模型的所需路径
APIPath = 'C:\CSiAPIexample'
if not os.path.exists(APIPath):
    try:
        # 用于递归创建目录,如果子目录创建失败或者已经存在,会抛出一个OSError的异常
        os.makedirs(APIPath)
    except OSError:
        pass
ModelPath = APIPath + os.sep + 'API_1-001.sdb'
# creat API helper object 创建API的辅助对象
helper = comtypes.client.CreateObject('SAP2000v1.Helper')
helper = helper.QueryInterface(comtypes.gen.SAP2000v1.cHelper)

if AttachToInstance:
    # attach to a running instance of SAP2000
    # 附加到正在运行的sap2000实例中
    try:
        # get the active SapObject 获取当前运行的sap2000的进程,其中函数参数为programID
        # 对于sap2000v23版本,这个参数为CSI.SAP2000.API.SapObject
        mySapObject = helper.Getobject("CSI.SAP2000.API.SapObject")
    except (OSError,comtypes.COMError):
        # 找不到正在运行的程序实例,或未能附加
        print("No running instance of the program found or failed to attach.")
        # 所有程序(方法、类等)停止,系统停止运行(主要用于含有多个类和方法并且相应的调用关系比较复杂的情况)
        sys.exit(-1)
else:
    # 没有正在运行的实例,需要启动新的sap2000,主要有以下的两种方式
    # 1、使用函数helper.CreateObject(ProgramPath),根据exe文件路径建立SapObject实例,参数为exe文件的路径
    # 2、也可以使用helper.CreateObjectProgID("CSI.SAP2000.API.SapObject")函数根据软件的program ID启动建立SapObject实例
    # 下面的if 和else语句就是体现的两种不同的打开新的sap2000的方式,其中每一种方式都嵌套了一个try...except语句
    # 目的是为了告诉程序出现异常应该怎么做,即使是出现异常,程序也可以正常运行
    if SpecifyPath:
        try:
            # create an instance of the SAPObject from the specified path
            # 1、使用函数helper.CreateObject(ProgramPath),根据exe文件路径建立SapObject实例,参数为exe文件的路径
            mySapObject = helper.CreateObject(ProgramPath)
        except (OSError,comtypes.COMError):
            print("Cannot start a new instance of the program from" + ProgramPath)
            # 打印:无法从ProgramPath启动程序的新实例
            sys.exit(-1)
    else:
        try:
            # create an instance of the SAPObject from the latest installed SAP2000
            # 2、也可以使用helper.CreateObjectProgID("CSI.SAP2000.API.SapObject")函数根据软件的program ID启动建立SapObject实例
            mySapObject = helper.CreateObjectProgID("CSI.SAP2000.API.SapObject")
        except (OSError,comtypes.COMError):
            print("Cannot start a new instance of the program.")
            # 打印:无法启动程序的新实例
            sys.exit(-1)
   
        # start SAP2000 application
        # 经过上面的步骤建立了SapObject实例之后,通过mySapObject.ApplicationStrat()函数启动SAP2000
        mySapObject.ApplicationStart()


# 以下的这三条代码基本上是一体的,在后面写代码的过程中可以在理解之后直接这样写   
#create SapModel object
SapModel = mySapObject.SapModel

# initialize model
# 使用SapModel.InitializeNewModel()函数初始化模型(如果函数里面带有1~16的数字,就可以设置默认单位制,这里没有进行相应的设置)
SapModel.InitializeNewModel()

# creat new blank model
# 创建一个空白的模型
ret = SapModel.File.NewBlank()


# define material property
# 定义材料属性
MATERIAL_CONCRETE = 2
ret = SapModel.PropMaterial.SetMaterial('CONC',MATERIAL_CONCRETE)

# assign isotropic mechanical properties to material
# 将各项同性力学性能特性指定给材质,前面已经定义了CON截面,接下来的三个数分别是:弹性模量、泊松比以及热膨胀系数5.5e-6
ret = SapModel.PropMaterial.SetMPIsotropic('CONC',3600,  0.2, 0.0000055)

# 定义方形的截面属性,这里定义了截面为12inx12in的方形截面
# define rectangular frame section property
ret = SapModel.PropFrame.SetRectangle('R1','CONC',12,12)

# 定义截面属性修正,这里模拟轴向刚度无穷大(将轴向面积设置为1000),并且忽略2、3轴的剪切变形(剪切面积为0)
# define frame section property modifiers
ModValue = [1000,0,0,1,1,1,1,1,1]
ret = SapModel.PropFrame.SetModifiers('R1',ModValue)


# switch to k-ft units
# 转换模型的单位
# 这种单位可能不是太常用,但是在很多的示例模型中是用的最多的
kip_ft_F=4
ret = SapModel.SetPresentUnits(kip_ft_F)


# add frame object by coordinates
# 通过坐标系来添加框架单元
# 这种操作是最基础也是最重要的一部分,这里主要有三根框架单元,这里是缺省的截面,自动赋予之前定义好的方管截面
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')

# assign point object restraint at base
# 在基础的节点施加约束
# PointName1 = ' '
# PointName2 = ' '
PointName1 , PointName2 = '', ''
# 指定节点约束为:u1,u2,u3,r1,剩余的方向释放约束
Restraint = [True, True, True, True, False, False]
# 获取FrameName1的节点1和节点2
[PointName1,PointName2,ret] = SapModel.FrameObj.GetPoints(FrameName1,PointName1,PointName2)

# 将FrameName1的PointName1的约束设置为定义好的Restraint
ret = SapModel.PointObj.SetRestraint(PointName1,Restraint)


# assign point object restraint at top
# 在顶部指定点对象约束
# 指定节点的约束为:u1,u2,剩余的方向释放约束
Restraint = [True,True,False,False,False,False]
[PointName1,PointName2,ret] = SapModel.FrameObj.GetPoints(FrameName2,PointName1,PointName2)
# 将FrameName1的PointName2的约束设置为定义好的Restraint
ret = SapModel.PointObj.SetRestraint(PointName2,Restraint)


# refresh view,updata(initialize) zoom
# 刷新视图,初始化缩放
ret = SapModel.View.RefreshView(0,False)


# add load patterns
# 添加荷载模式
# 选定的荷载模式为第8种的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)


# assign loading for load pattern 2
# 为第二种荷载模式施加荷载,在FrameName3两端的节点施加相应的节点荷载
[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)


# assign loading for load pattern 3
# 为第三种荷载模式施加荷载,在FrameName3两端的节点进行相应的施加
[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)

#assign loading for load pattern 4
#对FrameName2施加荷载模式名称为4的分布荷载
ret = SapModel.FrameObj.SetLoadDistributed(FrameName2,'4',1,11,0,1,2,2)

#assign loading for load pattern 5
#对FrameName1,FrameName2施加荷载模式名称为5的分布荷载,坐标系选择为局部坐标系
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')

#assign loading for load pattern 6
#对FrameName1,FrameName2施加荷载模式名称为6的分布荷载,坐标系选择为局部坐标系
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')


#assign loading for load pattern 7
#对FrameName2局部轴的跨中位置施加荷载模式名称为7的节点荷载
ret = SapModel.FrameObj.SetLoadPoint(FrameName2,'7',1,2,0.5,-15,'Local')

# switch to k_in units
kip_in_F=3
ret = SapModel.SetPresentUnits(kip_in_F)

# save model
# 保存模型
ret = SapModel.File.Save(ModelPath)

# run model(this will creat the analysis model)
# 运行模型,在运行的过程种会创建一个分析模型
ret = SapModel.Analyze.RunAnalysis()

#initialize for Sap2000 results
# 初始化sap2000的计算结果
SapResult=[0,0,0,0,0,0,0]
[PointName1,PointName2,ret] = SapModel.FrameObj.GetPoints(FrameName2,PointName1,PointName2)

# get Sap2000 results for load cases 1 through 7
# 初始化荷载模式从1~7的sap2000的计算结果
for i in range(0,7):
        # 结果数量,这里预先定义为0
        NumberResults = 0
        # 分别是对象、单元、荷载、分析步类型、分析步数量、以及6个方向的位移
        Obj,Elm,ACase,StepType,StepNum,U1,U2,U3,R1,R2,R3 = [],[],[],[],[],[],[],[],[],[],[]
        # 定义对象单元也为0(不知道理解的对不对)
        ObjectElm = 0
        # 删除所有对荷载和荷载组合的选择
        ret = SapModel.Results.Setup.DeselectAllCasesAndCombosForOutput()
        # 按照循环来选择相应的荷载和荷载组合,i从0取到6,将7个荷载模式都循环一遍
        ret = SapModel.Results.Setup.SetCaseSelectedForOutput(str(i+1))
        # 如果是运行到前三个荷载模式
        if i <= 3:
            [NumberResults, 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)
            # 这段代码没有理解,下面的代码同理
            SapResult[i] = U3[0]
        # 运行到后面4个荷载模式
        else:
            [NumberResults, 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)
            SapResult[i] = U1[0]




# fill independent results
# 填写独立的结果
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

# fill percent diffence
PercentDiff = [0,0,0,0,0,0,0]
for i in range(0,7):
    PercentDiff[i]=(SapResult[i]/IndResult[i])-1

# display results
# 打印结果
for i in range(0,7):
    print()
    print(SapResult[i])
    print(IndResult[i])
    print(PercentDiff[i])
ToTOP