Matlab:将 ID 与数据集(例如结构)相关联?

Matlab: associating an ID with a dataset (e.g. struct)?

我正在为 Matlab 中的高阶有限元仿真算法开发某个功能,我想知道实现某项任务的好方法是什么。我相信我面临着一个有点普遍的问题,但在做了一些挖掘之后,我并没有真正找到一个好的解决方案。

基本上,我有一长串 ID(对应于我的网格上的某些节点),其中每个 ID 都与小数据集相关联。然后当我 运行 我的求解器时,我需要访问与这些节点关联的数据并更新数据(多次)。

因此,例如,假设这是我的这些特定节点的列表:

nodelist = [3 27 38] %(so these are my node ID's) 

然后对于每个节点,我有以下关联的数据集

a (scalar)
b (5x5 double matrix)
c (10x1 double vector)

(a total of 36 double values associated with each node ID)

实际上,我当然会有一个长得多的节点 ID 列表和一个更大的与每个节点关联的数据集(但仍然只有双标量、矩阵和向量(没有字符、字符串等)) .

方法一

所以我想出的一种方法就是将所有内容都存储在二维双矩阵中,然后在需要时进行一些相对复杂的索引以访问我的数据。对于上面的示例,我的二维矩阵的大小为

size(2Dmat) = [length(nodelist), 36]

假设我想访问节点 ID 27 的 b(3,3),我将访问 2Dmat(2,14)。

原则上,这是可行的,但由于这种复杂的索引,代码不是很干净和可读(更不用说,当我更改数据集设置方式时,我需要重新调整整个索引代码)。

方法二

另一种方法是对节点列表中的每个节点使用某种结构:

a = 4.4;
b = rand(5,5);
c = rand(10,1);
s = struct('a',a,'b',b,'c',c)

然后我可以通过 s.b(3,3) 等访问数据。但我只是不知道如何将结构与节点 ID 相关联?

方法 3

我能想到的最后一件事是建立某种 SQL 数据库,但这似乎有点矫枉过正。此外,我需要我的代码尽可能快,因为我需要多次访问与这些选定节点关联的数据集中的这些字段,而且我想对数据库进行一些查询会减慢速度。

请注意,最终我会将代码从 Matlab 转换为 C/C++,因此我更愿意实现一些不严重依赖某些 Matlab 特定功能的东西。

那么,关于如何以干净的方式实现此功能有什么想法吗?我希望我的问题有道理并提前致谢!

方法 2 是最干净的,并且很容易转换为 C++。对于每个节点,您都有一个结构 s,然后:

data(nodeID) = s;

就是所谓的结构数组。你索引为

data(id).b(3,3) = 0.0;

这假设 ID 是连续的,或者它们的值没有很大的差距。但这始终可以确保,如果需要,很容易重新编号节点 ID。


在 C++ 中,你有一个结构向量:

struct Bla{
   double a;
   double b[3][3];
   double c[10];
};

std::vector<Bla> data(N);

或者在 C:

Bla* data = malloc(sizeof(Bla)*N);

(完成后不要忘记 free(data))。

然后,在 C 或 C++ 中,您可以这样访问元素:

data[id].b[2][2] = 0.0;

除了索引在 C++ 中从 0 开始,在 MATLAB 中从 1 开始之外,翻译很明显。


请注意,此方法在 MATLAB 中比方法 1 具有更大的内存开销,但在 C 或 C++ 中则不然。

方法 3 是个坏主意,它只会减慢您的代码速度而没有任何好处。

我认为最干净的解决方案,给定一组不连续的节点 ID,方法 2 使用 map container where your node ID is the key (i.e. index) into the map. This can be implemented in MATLAB using a containers.Map object, and in C++ using the std::map 容器。例如,以下是在 MATLAB 中创建节点映射并将值添加到节点映射的方法:

>> nodeMap = containers.Map('KeyType', 'double', 'ValueType', 'any');
>> nodelist = [3 27 38];
>> nodeMap(nodelist(1)) = struct('a', 4.4, 'b', rand(5, 5), 'c', rand(10, 1));
>> nodeMap(3)

ans = 

  struct with fields:

    a: 4.400000000000000
    b: [5×5 double]
    c: [10×1 double]

>> nodeMap(3).b(3,3)

ans =

   0.646313010111265

在 C++ 中,您需要为要存储在地图中的数据类型定义结构或 class(例如 Node)。这是一个示例(... 表示传递给 Node 构造函数的参数):

#include <map>

class Node {...};   // Define Node class
typedef std::map<int, Node> NodeMap;  // Using int for key type

int main()
{
  NodeMap map1;

  map1[3] = Node(...);  // Initialize and assign Node object
  map1.emplace(27, std::forward_as_tuple<...>);  // Create Node object in-place
}