Skip to main content

OVF 文件解析器

项目描述

OVF 解析器库

用于强大的 OOMMF 矢量字段文件解析的简单 API

OVF 格式规范

构建状态 构建状态

Python包 PyPI 版本

图书馆覆盖率 Python 绑定覆盖率
图书馆覆盖状态 Python 绑定覆盖率状态

如何使用

有关使用示例,请查看测试文件夹:testpython/testfortran/test

除了打开文件或初始化段外,所有函数都返回状态码(通常OVF_OKOVF_INVALIDOVF_ERROR)。当返回码不是OVF_OK时,您可以查看最新消息,它应该会告诉您问题所在(const char * ovf_latest_message(struct ovf_file *)在 C API 中)。

在 C/C++ 和 Fortran 中,在编写段之前,请确保ovf_segment您传入的已初始化,即您已经调用了ovf_read_segment_headeror 或ovf_segment_create.

C/C++

打开和关闭:

  • struct ovf_file *myfile = ovf_open("myfilename.ovf")打开文件
  • myfile->found检查文件是否存在于磁盘上
  • myfile->is_ovf检查文件是否包含 OVF 标头
  • myfile->n_segments检查文件应包含的段数
  • ovf_close(myfile);关闭文件并释放资源

从文件中读取:

  • struct ovf_segment *segment = ovf_segment_create()初始化一个新段并获取指针
  • ovf_read_segment_header(myfile, index, segment)将标头读入段结构
  • 创建适当大小的浮点数据数组...
  • ovf_read_segment_data_4(myfile, index, segment, data)将段数据读入浮点数组
  • 读取前设置segment->N允许部分读取大数据段

写入和附加到文件:

  • struct ovf_segment *segment = ovf_segment_create()初始化一个新段并获取指针
  • segment->n_cells[0] = ...等设置数据维度、标题和描述等。
  • ovf_write_segment_4(myfile, segment, data, OVF_FORMAT_TEXT)写一个包含段头和数据的文件
  • ovf_append_segment_4(myfile, segment, data, OVF_FORMAT_TEXT)将段头和数据附加到文件中

Python

要安装ovf python 包,要么从源代码构建和安装,要么简单地使用

pip install ovf

ovf从 Python 中使用,例如

from ovf import ovf
import numpy as np

data = np.zeros((2, 2, 1, 3), dtype='f')
data[0,1,0,:] = [3.0, 2.0, 1.0]

with ovf.ovf_file("out.ovf") as ovf_file:

    # Write one segment
    segment = ovf.ovf_segment(n_cells=[2,2,1])
    if ovf_file.write_segment(segment, data) != -1:
        print("write_segment failed: ", ovf_file.get_latest_message())

    # Add a second segment to the same file
    data[0,1,0,:] = [4.0, 5.0, 6.0]
    if ovf_file.append_segment(segment, data) != -1:
        print("append_segment failed: ", ovf_file.get_latest_message())

Fortran

Fortran 绑定以面向对象的风格编写,以便于使用。写一个文件,例如:

type(ovf_file)      :: file
type(ovf_segment)   :: segment
integer             :: success
real(kind=4), allocatable :: array_4(:,:)
real(kind=8), allocatable :: array_8(:,:)

! Initialize segment
call segment%initialize()

! Write a file
call file%open_file("fortran/test/testfile_f.ovf")
segment%N_Cells = [ 2, 2, 1 ]
segment%N = product(segment%N_Cells)

allocate( array_4(3, segment%N) )
array_4 = 0
array_4(:,1) = [ 6.0, 7.0, 8.0 ]
array_4(:,2) = [ 5.0, 4.0, 3.0 ]

success = file%write_segment(segment, array_4, OVF_FORMAT_TEXT)
if ( success == OVF_OK) then
    write (*,*) "test write_segment succeeded."
    ! write (*,*) "n_cells = ", segment%N_Cells
    ! write (*,*) "n_total = ", segment%N
else
    write (*,*) "test write_segment did not work. Message: ", file%latest_message
    STOP 1
endif

有关如何生成现代 Fortran 绑定的更多信息,另请参阅https://github.com/MRedies/Interfacing-Fortran

如何将其嵌入到您的项目中

如果您使用的是 CMake,则只需将其克隆到子目录中即可,例如thirdparty/ovf并将其与以下内容一起使用add_subdirectory

add_subdirectory( ${PROJECT_SOURCE_DIR}/thirdparty/ovf )
set( OVF_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/thirdparty/ovf/include )
target_include_directories( myproject PRIVATE ${OVF_INCLUDE_DIRS} )
target_link_libraries( myproject PUBLIC ${OVF_LIBRARIES_STATIC} )

如果您不使用 CMake,则可能需要进行一些手动工作。

建造

在 Unix 系统上

通常:

mkdir build
cd build
cmake ..
make

在 Windows 上

一种可能:

  • 在 CMake GUI 中打开文件夹
  • 生成VS项目
  • 在 VS 中打开生成的项目并构建它

CMake 选项

以下选项是ON默认的。如果你想关闭它们,只需传递-D<OPTION>=OFF给 CMake,例如-DOVF_BUILD_FORTRAN_BINDINGS=OFF.

  • OVF_BUILD_PYTHON_BINDINGS
  • OVF_BUILD_FORTRAN_BINDINGS
  • OVF_BUILD_TEST

在 Windows 上,您还可以从 CMake GUI 设置这些。

创建并安装 Python 包

代替pip安装它,您可以例如构建所有内容,然后在本地安装包,该-e标志将允许您更改/更新包而无需重新安装它。

cd python
pip install -e .

不使用 CMake 构建

以下是如何使用 gcc 手动构建 C 库并将其与绑定链接到相应的 Fortran 可执行文件的示例。

C 库:

g++ -DFMT_HEADER_ONLY -Iinclude -fPIC -std=c++11 -c src/ovf.cpp -o ovf.cpp.o

# static
ar qc libovf_static.a ovf.cpp.o
ranlib libovf_static.a

# shared
g++ -fPIC -shared -lc++ ovf.cpp.o -o libovf_shared.so

C/C++ 测试可执行文件:

g++ -Iinclude -Itest -std=c++11 -c test/main.cpp -o main.cpp.o
g++ -Iinclude -Itest -std=c++11 -c test/simple.cpp -o simple.cpp.o

# link static lib
g++ -lc++ libovf_static.a main.cpp.o simple.cpp.o -o test_cpp_simple

# link shared lib
g++ libovf_shared.so main.cpp.o simple.cpp.o -o test_cpp_simple

Fortran 库:

gfortran -fPIC -c fortran/ovf.f90 -o ovf.f90.o

ar qc libovf_fortran.a libovf_static.a ovf.f90.o
ranlib libovf_fortran.a

Fortran 测试可执行文件

gfortran -c fortran/test/simple.f90 -o simple.f90.o
gfortran -lc++ libovf_fortran.a simple.f90.o -o test_fortran_simple

静态链接时,您还可以链接目标文件ovf.cpp.o而不是libovf_static.a.

注意:根据编译器和/或系统,您可能需要-lstdc++代替-lc++.

文件格式v2.0规范

本规范是根据 NIST 用户指南编写的 OOMMF 并已实施,但未针对 OOMMF 进行测试或验证。

注意:OVF 2.0 格式是对 OVF 1.0 格式的修改,它还支持跨三个空间维度的字段,但具有任意(但固定)维度的值。以下是 2.0 格式的完整规范。

一般的

  • OVF 文件具有 ASCII 标头和尾标,以及可能是 ASCII 或二进制的数据块。
  • 所有非数据行都以#字符开头
  • 注释以开头##并被解析器忽略。注释一直持续到行尾。
  • 没有行继续符
  • 以 a 开头#但仅包含空格的行将被忽略
  • 以 a 开头#但包含未知关键字的行是错误的

在整体头之后,文件由段块组成,每个段由段头、数据块和尾部组成。

  • 场域(即空间范围)跨越三个维度,单位通常以米或纳米表示
  • 该字段可以是任意维度N > 0(但是,该维度在每个段中是固定的)。

标题

  • OVF 2.0 文件的第一行必须是# OOMMF OVF 2.0
  • 标头还应包含段数,指定为例如# Segment count: 000001
  • 未指定段计数的零填充

细分市场

段头

  • 每个块都以# Begin: <block type>一行开始,并以相应的# End: <block type>行结束
  • 非空非注释行由关键字和值组成:
    • 关键字由从首字母#到第一个冒号 ( :) 字符的所有字符组成。忽略大小写,并删除所有空格
    • 未知关键字是错误
    • 该值由第一个冒号 ( :) 之后直到注释 ( ##) 或行尾的所有字符组成
  • 未指定关键字的顺序
  • 所有关键字都没有默认值,因此除非另有说明,否则所有关键字都是必需的

块内的所有内容都Header应该是注释或以下文件关键字行之一

  • title: 长文件名或标题
  • desc(可选):描述行,尽可能多地使用
  • meshunit:基本网格空间单元。##此行中不允许使用注释标记。示例值:nm
  • valueunits: 应该是一个 (Tcl) 值单位列表。##此行中不允许使用注释标记。示例值:"kA/m". 列表的长度应该是以下之一
    • N:每个元素表示相应维度索引的单位
    • 1:单个元素应用于所有维度索引
  • valuelabels:这应该是N值标签的 -item (Tcl) 列表,每个值维度一个。标签标识每个维度中的数量。例如,在能量密度文件中,N可能是1,valueunits 可能是"J/m3",而 valuelabels 可能是"Exchange energy density"
  • valuedim(integer):指定一个整数值,N,它是字段的维数。N >= 1
  • xmin, ymin, zmin, xmax, ymax, zmax: 六个单独的线,指定网格的边界框,单位为meshunit
  • meshtype:网格结构;之一
    • rectangular: 也需要
      • xbase, ybase, zbase: 三个单独的线,表示原点(即数据段中第一个点的位置),单位为meshunit
      • xstepsize, ystepsize, zstepsize: 三个单独的线,指定相邻网格点之间的距离,单位为meshunit
      • xnodes, ynodes, znodes(整数):三个单独的行,指定沿每个轴的节点数。
    • irregular: 也需要
      • pointcount(整数):数据样本点/位置的数量,即节点。仅适用于不规则网格

分段数据

  • 数据块开始由表格的一行标记 # Begin: data <representation>(因此由 关闭# End: data <representation>),其中<representation>一个是
    • text
    • binary 4
    • binary 8
  • 在 Data 块中,对于常规网格,每条记录都由N值组成,其中是Segment Header 中N的记录指定的值维度。valuedim对于不规则网格,每个记录由N + 3值组成,其中前三个值是节点位置的 x 、 y 和 z 分量。
  • text数据在列中是常见的约定,N以空格分隔
  • 数据排序一般是先增加 x 索引,然后是 y 索引,最后是 z 索引

对于二进制数据:

  • 二进制表示是采用小端 (LSB) 顺序的 IEEE 754 标准化浮点数。为确保字节顺序正确,并提供部分检查文件未通过非 8 位干净通道发送,第一个数据值固定1234567.0为 4 字节模式,对应于 LSB hex byte sequence 38 B4 96 49123456789012345.0对于 8-byte 模式,对应 LSB hex byte sequence40 DE 77 83 21 12 DC 42
  • 数据紧跟校验值
  • 最后一个数据值之后的第一个字符应该是换行符

这个库所做的扩展

这些扩展主要是为了帮助处理原子系统的数据。

  • 段计数用零填充到 6 位(这样可以附加段并增加计数,而无需重新写入整个文件)
  • 以 a 开头#但包含未知关键字的行将被忽略。
  • ##始终是注释,并且允许在所有关键字行中使用,包括meshunitvalueunits
  • 所有关键字都有默认值,因此不需要
  • csv也是一个有效的 ASCII 数据表示,并且对应于text类型的逗号分隔的列

该库的当前限制

  • 结构/类中变量的命名与文件格式规范不一致
  • 并非该段中的所有默认值都保证是合理的
  • valueunits并且valuelabels被写入和解析,但不检查维度或内容
  • min并且max不检查值以确保它们是合理的界限
  • irregular网格类型未得到正确支持,因为在读取或写入时未考虑位置

例子

N = 2 的不规则网格的示例 OVF 2.0 文件:

# OOMMF OVF 2.0
#
# Segment count: 1
#
# Begin: Segment
# Begin: Header
#
# Title: Long file name or title goes here
#
# Desc: Optional description line 1.
# Desc: Optional description line 2.
# Desc: ...
#
## Fundamental mesh measurement unit.  Treated as a label:
# meshunit: nm
#
# meshtype: irregular
# pointcount: 5      ## Number of nodes in mesh
#
# xmin:    0.    ## Corner points defining mesh bounding box in
# ymin:    0.    ## 'meshunit'.  Floating point values.
# zmin:    0.
# xmax:   10.
# ymax:    5.
# zmax:    1.
#
# valuedim: 2    ## Value dimension
#
## Fundamental field value units, treated as labels (i.e., unparsed).
## In general, there should be one label for each value dimension.
# valueunits:  J/m^3  A/m
# valuelabels: "Zeeman energy density"  "Anisotropy field"
#
# End: Header
#
## Each data records consists of N+3 values: the (x,y,z) node
## location, followed by the N value components.  In this example,
## N+3 = 5, the two value components are in units of J/m^3 and A/m,
## corresponding to Zeeman energy density and a magneto-crystalline
## anisotropy field, respectively.
#
# Begin: data text
0.5 0.5 0.5  500.  4e4
9.5 0.5 0.5  300.  5e3
0.5 4.5 0.5  400.  4e4
9.5 4.5 0.5  200.  5e3
5.0 2.5 0.5  350.  2.1e4
# End: data text
# End: segment

与 OVF 1.0 的比较

  • 第一行读取# OOMMF OVF 2.0规则和不规则网格。
  • 在段头块中
    • 不支持 OVF 1.0 格式的关键字valuemultiplierboundary和。ValueRangeMaxMagValueRangeMinMag
    • new 关键字valuedim是必需的。这必须指定一个N大于或等于 1 的整数值。
    • valueunits关键字替换valueunitOVF 1.0 的关键字,在 OVF 2.0 文件中不允许使用该关键字。
    • newvaluelabels关键字是必需的。
  • 在段数据块中
    • 节点排序与 OVF 1.0 格式相同。
    • 对于使用文本表示N = 3的数据块,OVF 1.0 和 OVF 2.0 文件中的数据块完全相同。另一种常见情况是N = 1,它表示标量场,例如能量密度(例如J/m3

项目详情


下载文件

下载适用于您平台的文件。如果您不确定要选择哪个,请了解有关安装包的更多信息。

源分布

ovf-0.4.3.tar.gz (492.7 kB 查看哈希

已上传 source

内置发行版

ovf-0.4.3-py2.py3-none-win_amd64.whl (10.7 kB 查看哈希

已上传 py2 py3

ovf-0.4.3-py2.py3-none-manylinux1_x86_64.whl (505.7 kB 查看哈希

已上传 py2 py3

ovf-0.4.3-py2.py3-none-macosx_10_14_x86_64.whl (90.0 kB 查看哈希

已上传 py2 py3

ovf-0.4.3-py2.py3-none-macosx_10_13_x86_64.whl (434.5 kB 查看哈希

已上传 py2 py3