我正在设计一个有限元库的过程。对于给定的问题,所使用的有限元网格可以具有不同尺寸的元素(例如四面体和三角形),并且可以组合相同尺寸的不同元素(例如四面体和六面体)。因此,我需要一个存储有限元素信息的数据结构。最基本的信息是元素的连通性(定义元素的节点ID)。例如,我需要以某种方式存储该三角形元素4连接到节点5,6和10.设计复杂的数据结构的依赖关系
我的第一个尝试是创建一个索引是维度(0,1,2或3)的列表和即存储字典。这些字典有字符串键(标识符),值是numpy数组(每行代表一个元素的连通性)。我需要这样做,因为根据字符串标识符,给定尺寸的numpy数组具有不同的形状。
这是类:
import os
from collections import OrderedDict
import numpy.ma as ma
flatten = lambda l: [item for sublist in l for item in sublist]
class ElementData(list):
def __init__(self, *args, **kwargs):
self.reset()
super(ElementData, self).__init__(*args, **kwargs)
def __iter__(self):
for k, v in self[self.idx].items():
for i, e in enumerate(v):
yield (k,i,e) if not ma.is_masked(e) else (k,i, None)
self.reset()
def __call__(self, idx):
self.idx = idx-1
return self
def __getitem__(self, index):
if index >= len(self):
self.expand(index)
return super(ElementData, self).__getitem__(index)
def __setitem__(self, index, value):
if index >= len(self):
self.expand(index)
list.__setitem__(self, index, value)
def __str__(self):
return "Element dimensions present: {}\n".format([i for i in range(len(self)) if self[i]]) + super(ElementData, self).__str__()
def keys(self):
return flatten([list(self[i].keys()) for i in range(len(self))])
def reset(self):
self.idx = -1
self.d = -1
def expand(self, index):
self.d = max(index, self.d)
for i in range(index + 1 - len(self)):
self.append(OrderedDict())
def strip(self, value=None):
if not callable(value):
saved_value, value = value, lambda k,v: saved_value
return ElementData([OrderedDict({k:value(k, v) for k,v in i.items()}) for i in super(ElementData, self).__iter__()])
def numElements(self, d):
def elementsOfDimension(d):
# loop over etypes
nelems = 0
for v in self[d].values():
nelems += v.shape[0] if not isinstance(v, ma.MaskedArray) else v.shape[0] - v.mask.any(axis=1).sum()
return nelems
# compute the number of all elements
if d == -1:
nelems = 0
for i in range(self.d+1):
nelems += elementsOfDimension(i)
return nelems
else: # of specific dimension only
return elementsOfDimension(d)
类工作得很好,它让我无缝循环通过特定维度的所有项目。但是,还有其他数据与单独存储的每个元素相关联,例如其材料。因此,我决定使用相同的数据结构来引用其他属性。为此,我使用该类的strip
函数,将整个结构返回给我,而不使用numpy数组。
问题是我原来的数据结构是动态的,如果我改变它,我不得不修改所有依赖它的其他结构。我真的认为我在设计这门课的时候走错了方向。也许有更简单的方法来解决这个问题?我想在numpy数组旁边存储额外的信息(例如元组),但我不知道这是否好。设计软件时所做的选择可能会让我们的生活过得更悲惨,现在我开始意识到这一点。
UPDATE
使用上述类,一个示例可以是如下:其中,所述数据结构已经被用来存储0(节点)的元素,1(行)
Element dimensions present: [0, 1, 2]
[OrderedDict([('n1', array([[0],
[1],
[3]]))]), OrderedDict([('l2', array([[1, 2]]))]), OrderedDict([('q4', array([[0, 1, 5, 4],
[5, 1, 2, 6],
[6, 2, 3, 7],
[7, 3, 0, 4],
[4, 5, 6, 7]]))])]
和2(四边形)尺寸。
可能有助于理解你为什么最初设计了这样的数据结构。你解决什么问题? – plalx
我正在创建一个有限元素库。这些numpy数组中的每一行都是元素连接(定义元素的节点ID)。对于一个给定的问题,所使用的有限元网格可以具有不同尺寸的元素(例如四面体和三角形),并且可以组合相同维度的不同元素(适用于例如四面体和六面体)。但是,该第一数据结构仅处理元素的连接性,每个元素也被分配一个材料属性(为此我需要另一个数据结构来存储材料),其他数据也是一样的 – aaragon
请提供一些数据给你的问题,显示**变化**,一个它与给定的'class'一起工作,其中一个不适合我的第一次尝试失败,因为缺少'ma.MaskedArray',它出现在哪里。 – stovfl