【问题标题】:Replacing State variable names in odb with python用python替换odb中的状态变量名
【发布时间】:2016-04-25 20:02:30
【问题描述】:

在 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

工作得很好。如果有人对此熟悉,将不胜感激。

EDIT2:

我的代码不起作用,因为新变量的长度应该与旧变量完全相同。如果长度匹配,则没有问题。较短的变量后面可以有空格以获得所需的字符长度。

通过使用 SSchneid 建议的代码,我能够匹配准确的 SDV 进行替换,不包括较长的部分。

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

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

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

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

感谢您的帮助!

【问题讨论】:

  • 在您的代码中,b'SDV2'b'works' 的长度不同。我认为这行不通。
  • 是的,这是正确的。长度必须匹配才能正常工作。虽然我通过查看编码模式并尝试手动复制它来增加长度是不成功的。

标签: python string binary abaqus


【解决方案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

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

【讨论】:

  • 如果我理解正确,“标准”方式会创建新的字段变量。我已经有 36 个 SDV,如果我创建新的,这个数字会翻倍。我不能删除旧的,所以我的 odb 的文件大小会增加很多。特别是对于大型分析。目前我只是用我在问题中发布的代码替换我的 SDV 的名称。我只需要确保新变量的长度与旧变量的长度完全相同。这样我就被限制在只有 4 个符号,什么是不够的。但是非常快速和简单。虽然将新变量名正确编码到 odb 中会很好。
  • 感谢您的澄清,没有考虑将所有内容复制到新的 ODB。现在使用 addData 方法很有意义!如果 newn 的长度比 oldn 长,您提供的代码仍然会破坏 odb。无论如何,我将尝试使用 addData 方法,因为我可以使用创建张量和向量的能力!
【解决方案2】:

问题是,您匹配以 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)

我敢打赌,有一种方法可以按照你建议的方式做到这一点。

【讨论】:

  • 是的,确实,你的方式完全取代了我想要的。但是,Abaqus 查看器仍然给出错误消息。这非常奇怪,因为如果我手动执行它就可以了。与在Notepad++中编辑相比,python中的读写保存有什么不同?
  • 对我来说,虽然我绝对不是专家,但这听起来像是一个编码问题,但由于我没有使用 Abaqus 查看器的经验,这只是一个猜测。
  • 显然,它必须与初始字符串具有相同的长度。否则它将无法正常工作。如果我的新字符串较短,我可以用空格替换其他字符。如果我的新字符串更长,现在我无能为力。尽管 abaqus 对某些变量使用更长的名称。 Notepad++ 方法有效,因为我尝试用 'works' 替换 'SDV10' 并且两者具有相同数量的字符。我想知道关于字符长度的信息存储在哪里。
猜你喜欢
  • 1970-01-01
  • 2022-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-09
  • 2021-06-30
  • 2021-09-28
  • 2022-01-11
相关资源
最近更新 更多