1

在 Abaqus 中,我有自己的材料描述 (VUMAT)。此 VUMAT 生成名为 SDV1、SDV2 等的状态变量。这些变量与 abaqus 中的其他输出数据一起存储在二进制 .odb 文件中。因为我有大量这样的变量,所以我想给它们起有意义的名称,例如 S1、S2、E1、E2 等,因此当在 Abaqus 查看器中查看 .odb 时,会清楚哪个变量是哪个变量。

现在,abaqus 提供了 python 接口来读取和写入该 .odb 文件。但据我所知,我找不到重命名这些变量的方法。当我尝试更改它们时,我得到只读错误。

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

但我想自动化这个过程。因此,我编写了一个 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 查看器中打开新的 .odb 时,我收到以下消息:

***错误:Abaqus 数据库文件已损坏。如果此文件是使用 FTP 或同等功能从另一台机器传输的,请确保使用二进制模式而不是 ASCII 模式复制文件。

此外,目前,此代码还替换了 SDV20,如何避免这种情况并仅替换 SDV2 而不是 SDV20、SDV21 等的部分?

我错过了什么?我正在使用python 2.7。

编辑:

如果在 HEX 编辑器中打开 ODB,可以看到以下模式: 对于 SDV9,后跟 SDV10:

04 53 44 56 39 00 00 00 05 53 44 56 31 30 00 00 00 00 00 00  

可以观察到编码以字符数开头。04 表示 SDV9,05 表示 SDV10,后跟 NULL 值。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 进行替换,不包括较长的部分。

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

当然,我们可以通过直接从子例程将所需变量输出到单独的文本文件来走得更远。然后通过使用该文本文件在 odb 中生成新的字段输出。之后可以删除文本文件。而这一切都不需要 SDV 输出。

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

我没有回答这个问题,直到发布完整的解决方案或者我自己弄清楚(在这种情况下,我将发布一个答案野兔)

谢谢您的帮助!

4

2 回答 2

1

问题是,您匹配以 SDV2 开头的所有内容。这意味着无论后面发生什么,所有开头都有 SDV2 的东西都会返回正值。

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

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)

我敢打赌,有一种方法可以做到这一点,而无需按照您提出的方式进行。

于 2016-04-22T10:14:53.787 回答
1

您的方法非常有创意,但是有一种“标准”方法可以使用 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 文件的二进制数据部分可能包含意外匹配“SDV2”的 4 个后续字节。在这种情况下,您的脚本会覆盖这些字节并破坏整个文件。

编辑1

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

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

你可以试试这段代码

content = bytearray(content)
old2new={b'SDV2':b'work'} # add more renaming patterns as you need
for oldn, newn in old2new.items():
  i = content.find(oldn) 
  # or using regex pattern:
  # re.search(oldn, content).start()
  content[i:i+len(newn)] = newn

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

于 2016-04-23T02:05:48.667 回答