我正在为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列表以及与每个节点相关联的数据集(但仍然只有双标量,矩阵和向量(没有字符,字符串等))。
方法1
因此,我准备的一种方法是将所有内容存储在2D双矩阵中,然后在需要时执行一些相对复杂的索引以访问我的数据。对于上面的示例,我的2D矩阵的大小为
size(2Dmat) = [length(nodelist), 36]
说我想访问节点ID 27的b(3,3),我访问2Dmat(2,14)。
从原理上讲,这是可行的,但是由于这种复杂的索引编制,代码不是很干净和可读性(更不用说,当我改变数据集的设置方式时,我需要重新调整完整的索引代码)。
方法2
另一种方法是对节点列表中的每个节点使用某种结构:
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特定功能的东西。
那么,关于如何以干净的方式实现此功能的任何想法?希望我的问题有道理,并预先感谢!
答案 0 :(得分:2)
方法2是最简洁的方法,可以轻松转换为C ++。对于每个节点,您都有一个结构s
,然后:
data(nodeID) = s;
是所谓的struct数组。您索引为
data(id).b(3,3) = 0.0;
这假定ID是连续的,或者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是个坏主意,只会减慢您的代码速度而没有任何好处。
答案 1 :(得分:2)
我认为,给定一组不连续的节点ID,最干净的解决方案是使用map container的方法2,其中您的节点ID是映射中的键(即索引)。这可以在MATLAB中使用containers.Map
对象来实现,而在C ++中可以使用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 ++中,您需要为要存储在地图中的数据类型定义结构或类(例如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
}