2024-12-02 ODC库使用:Legacy ODB API ODC库使用:Legacy ODB API ODC库中还提供了legacy ODB API接口,在官方文档中未进行说明,需要通过阅读源代码才能了解其功能。ODB C/Fortran API接口说明可以参阅:odc/src/odc目录下的odccapi.cc和odccapi.h文件定义了C API;odc/src/fortran目录下的odc_c_binding.f90定义了Fortran API,实际上大部分Fortran API调用的就是C API。ODB API命令约定是以odb_为前缀的接口名称,前面介绍的ODC库一般以odc_前缀。ODB API主要包括四类:读取ODB消息: odb_read_*接口写入ODB消息: odb_write_*接口SQL语法:odb_select_*接口追加消息:odb_append_*接口ODB API设计是传统的C接口设计风格,其接口很类似NetCDF API接口设计,而最新的ODC库API是面向对象设计,以类对象构建API。对于Fortran用户,可以阅读odc/src/fortran/legacy_fortran_api_examples.f90示例程序了解如何调用ODB AP... 2024年12月02日 90 阅读 0 评论
2024-12-02 ODC库使用:指定列对应数组 ODC库使用:指定列对应数组 这应该是ODC库使用教程最后一篇文章了。不过在后面分享Fortran与C互操作(混编)时可能会以ODC库实现方式为例介绍相关内容。前面介绍的ODC编码方式是将不同类型的所有列数据通过transfer函数转换成双精度(real*8)浮点类型,同时将所有列数据组织成一个二维表格形式,放入一个二维数组中再进行解编码处理。可能很多人不习惯这种使用方式,更希望通过指定每列对应的(一维)数组buffers方式进行操作。这样做的好处是避免了显式调用transfer数据类型转换。下面介绍ODC这种使用方式。指定列数组编码查看官方实例:https://odc.readthedocs.io/en/latest/content/usage-examples/encode-custom.html首先使用add_column方法添加表格列信息! Define all column names and their types call check_call(encoder%add_column('expver', ODC_STRING), 'adding expver column') call check... 2024年12月02日 68 阅读 0 评论
2024-12-02 ODC库编程实践 ODC库编程实践 前面提到过odb-2数据格式看成是二维表格型数据,但表格中每列的数据类型可以不同。开发人员可能考虑到通用性以及读写性能,在实现时将表格数据统一处理成双精度的二维数组(也可以看成更一般的一维数组)。real(8), target :: data(ncols, nrows) rc = encoder%set_data(data, column_major)此时需要解决两个问题:二维数组在内存中的布局,即以列主元还是行主元的内存布局。如果column的类型不是双精度,那么就存在数据类型转换,对于数值类型还算简单,但字符类型如何处理?第一个问题,我们从ODC API看起。C API odc_encoder_set_data_array函数用于设置编码的输入数组。函数第二个参数是指定的输入数组,这里使用const void*类型符,通用类型指针。第三个参数是指数组(表格)的宽度,以字节为单位。第四个参数是数组的行数。最后一个参数是指列主元布局每列宽度,以字节为单位,一般为8字节,如果是行主元,传入0值。对应的Fortran API,则是类对象encoder的成员函数set_data,查看... 2024年12月02日 66 阅读 0 评论
2024-12-02 ODC库使用:数据编码 ODC库使用:数据编码 数据编码编码过程是解码过程的逆操作。编码就是将内存中数据转换成Encoder对象,然后输出到数据文件流(比如文件中)。数据编码过程除了前面介绍的顶层类对象外,主要涉及到解码对象Encoder。Encoder在编码时需要指定内存布局信息。以列主元内存布局为例:integer(8), parameter :: nrows = 1000 integer, parameter :: ncols = 6 real(8), target :: data(nrows, ncols) ! set up the data here... type(odc_encoder) :: encoder logical, parameter :: column_major = .true. integer, target :: outunit integer(8), target :: bytes_written rc = encoder%initialise() rc = encoder%add_column("column1", ODC_INTEGER) rc = encode... 2024年12月02日 80 阅读 0 评论
2024-12-02 ODC库使用建议 ODC库使用建议 odc库使用建议ODC库必须初始化在程序调用实际odc库函数前,必须调用odc_initialise_api函数。因为odc内部使用eckit库,如果odc程序未使用eckit,必须要初始化函数初始化eckit,否则程序会报错。Attempting to access a non-existent instance of Main() backtrace [1] stack has 12 addresses (/path/to/eckit/1.25.0/lib64/libeckit.so+eckit::BackTrace::dump[abi:cxx11]())0x1af (/path/to/eckit/1.25.0/lib64/libeckit.so+eckit::Main::instance())0x4d (/path/to/eckit/1.25.0/lib64/libeckit.so+eckit::ResourceBase::init())0x7e (/path/to/eckit/1.25.0/lib64/libeckit.so+eckit::FileHandle::open... 2024年12月02日 61 阅读 0 评论
2024-12-02 ODC库使用:数据解码 ODC库使用:数据解码 代码示例及API使用Fortran接口进行说明,C相关接口可查阅官方文档。数据解码解码(Decoder)过程就是从ODB-2消息流(常为文件载体)解码到计算机内存中。编码(encoder)是解码的逆过程。ODB-2数据解码在API层面涉及三个类对象(ODC库使用C++实现,使用面向对象设计),涉及到从文件操作底层到解码高层层级。Reader对象Reader对象负责ODB-2数据流的底层资源控制,比如ODB-2文件打开、关闭。type(odc_reader) :: reader !定义Reader对象 rc = reader%open_path("imaginary/path.odb") !打开ODB-2文件 ... rc = reader%close() ! 关闭odb-2文件,释放资源Frame对象Frame对象提供ODB-2消息流的连续数据的一块(chunk)切片视窗。该数据块必须拥有相同的列结构(即列的数目、名称及关联数据类型)(这就是frame的定义,即ODB-2处理数据单元是一个frame)。Frame对象在不用解码数据(data)情况下可获取元... 2024年12月02日 58 阅读 0 评论
2024-12-02 ODC库使用:ODB-2数据格式介绍 ODC库使用:ODB-2数据格式介绍 用好ODC库的前提是对ODB-2数据格式有一定了解。ODB-2是专门为气象观测数据设计的一种数据格式,具有(自描述)元数据、紧凑特点。ODB-2不是一种文件格式,更应该看作是一种消息格式。ODB-2数据流不一定存储在文件中,可以存放在内存中,甚至可以通过网格传输ODB-2数据流。ODB-2数据是(二维)表格型数据格式,可以类比excel表格来理解。frame概念在ODB-2数据格式中,引入了frame概念,可以类比excel中的sheet。ODB-2数据由一串frames构成,每个frame都是独立、自描述的,frames之间不需要拥有相同的结构,就像excel表格中每个sheet之间是独立的一样。每个frame是由元数据header和数据表组成。header部分定义columns(列)属性、编码codecs及其他元数据信息。数据部分存储了对应的数据。表格每一行(row)代表一条观测记录,行与行(即观测记录之间)是独立的。表格每一列(column)代表观测资料的一种属性,比如观测日期、站点号、观测值等等。每一个column附带着名称(name)/数据类型(type)等属性。Col... 2024年12月02日 70 阅读 0 评论