用python替换odb中的状态变量名

2024-09-30 16:24:53 发布

您现在位置:Python中文网/ 问答频道 /正文

在Abaqus我有自己的材料描述(VUMAT)。这些变量存储在SDV1.qu文件中,其他变量被存储在这个文件中。因为我有大量的这些,我想给它们起一个有意义的名字,比如S1,S2,E1,E2等等。所以当.odb在Abaqus查看器中查看时,可以清楚地看到哪个变量是哪个。在

现在,abaqus提供了python接口来读写那个.odb文件。但就我所能搜索到的,我找不到一个可以重命名这些变量的方法。当我试图改变它们时,我得到了只读错误。在

因此,我尝试用Notepad++打开.odb,发现如果手动将该文件中的所有SDV条目替换为我想要的并保存它。在Abaqus查看器中,名称也会更改。太好了!在

但我想自动化这个过程。所以我编写了一个python脚本来读取初始的.odb,替换sdv并将修改后的.odb另存为一个不同的文件。在

import sys
with open('User.odb','rb') as f:
    content = f.read()
    if b"SDV2" in content:
        print('Found')
        content = content.replace(b'SDV2',b'works')
with open('User.temp.odb','wb') as fw:
    fw.write(content)

但是当我在abaqus查看器中打开new.odb时,我收到了以下消息:

***ERROR: The Abaqus database file is corrupt. If this file was transferred from another machine using FTP or equivalent, ensure that the file was copied using the binary mode instead of ASCII mode.

而且,目前这段代码也代替了SDV20,如何避免这种情况,只替换SDV2而不替换SDV20、SDV21等的部分。?在

我错过了什么?我使用的是python2.7。在

编辑:

如果在十六进制编辑器中打开ODB,可以看到以下模式: 对于SDV9后接SDV10:

^{pr2}$

可以观察到编码是从字符数开始的。SDV9为04,SDV10为05,后跟空值。SDV1至SDV9为3,其余为6。我试着把SDV9部分改成:

05 53 44 56 39 00 00 00 00 00 00 00

在将SDV10部件改为:

05 53 44 56 39 00 00 00 00 00 00 00

工作非常好。如果有人熟悉这一点,我们将不胜感激。在

编辑2:

旧代码的长度不应该和新代码的长度一样。如果长度匹配,则没有问题。较短的变量后面可以有空格,以获得所需的字符长度。在

通过使用SSchneid建议的代码,我能够匹配精确的sdv进行替换,而不包括较长sdv的部件。在

添加涉及FieldOutput()和addData()的字段变量的标准方法不是一个好的解决方案,因为它重复了已有的具有不同名称的sdv。对于非常大的分析,它大大增加了odb的大小。除非有办法删除旧的。在

当然,我们可以通过直接从子例程将所需变量输出到一个单独的文本文件来进一步。然后通过使用该文本文件在odb中生成新的字段输出。之后可以删除文本文件。所有这些都没有请求SDV输出。在

或者可以将SDV输出请求到.fil文件,然后使用FieldOutput()和addData()将其组装回odb。但这些都是非常老套的解决方案,需要大量的磁盘写入和大量代码来解析输出文本文件。在

我会把这个问题的答案贴出来的

谢谢你的帮助!在


Tags: 文件方法代码contentfile文本文件sdvabaqus
2条回答

问题是,你要匹配所有以SDV2开头的内容。这意味着无论接下来发生什么,在一开始有SDV2的所有东西都会返回正值。

在我看来,解决匹配问题的最佳方法是使用正则表达式:

import re
import sys
with open('User.odb','rb') as f:
    content = f.read()
    content = re.sub('\\bSDV2\\b', 'works', content)
with open('User.temp.odb','wb') as fw:
    fw.write(content)

我打赌有一种方法可以不按你建议的方式去做。在

您的方法非常有创意,但是使用Abaqus Python API有一种“标准”方法来实现您的目标:

frame.FieldOutput(name='works', description='this is a vector', type=VECTOR).addData(position=INTEGRATION_POINT, instance=grout_instance, labels=elementLabels, data=elementData)

在您的代码中,我观察到两个可能的错误:

  1. 新旧名称(“SDV2”和“works”)的长度不匹配。在
  2. ODB文件的二进制数据段可能包含4个意外匹配“SDV2”的后续字节。在这种情况下,脚本会覆盖这些字节并损坏整个文件。在

编辑1

  1. 由于Abaqus没有提供任何删除现有字段的方法(正如他们所说,出于一致性原因),如果您希望使用addData方法来防止重复,则有必要创建一个新的ODB并在那里复制字段。然后可以删除旧文件。我们已经用这种方法一年了。这样做的好处是可以从不同的sdv创建向量或张量,以便更好地可视化。

  2. 要修复我之前标注的可能错误(长度不匹配和意外替换),可以使用find代替replace

你可以试试这个代码

^{pr2}$

其他代码遵循您的脚本。我假设您只需要替换文件中每个名称的一次出现。否则请使用re^{}方法。在

相关问题 更多 >