有限元和稀疏矩阵

news2024/11/24 20:52:23

对于大规模的有限元计算,系统的整体刚度矩阵是非常耗费内存的,以百万自由度为例,刚度矩阵K的大小为100万x100万,元素大小为双精度double,占用8 byte,那么K占用的内存为100万x100万x8 byte = 8000G,这无疑是一个天量内存,好在刚度矩阵一般是稀疏矩阵,我们可以充分利用稀疏矩阵的特性来降低空间复杂度

稀疏矩阵的优势

存储效率

  • 稀疏矩阵存储方式只记录非零元素及其位置,大大减少了内存消耗。例如,使用压缩稀疏行(CSR)或压缩稀疏列(CSC)格式,可以有效地存储和操作大型稀疏矩阵。

计算效率

  • 稀疏矩阵运算,如矩阵乘法、求解线性系统等,仅对非零元素进行操作,减少了计算量。使用稀疏矩阵求解器(如迭代法)可以显著提高求解大型线性系统的效率。

稀疏矩阵的常用存储格式

稀疏矩阵有很多存储格式,这些格式的核心思想是只存储非零元素,

coo_matrix

coo_matrix(coordinate list matrix)是最简单的稀疏矩阵存储方式,采用三元组(row, col, data)的形式来存储矩阵中非零元素的信息。在实际使用中,一般coo_matrix用来创建矩阵,因为coo_matrix无法对矩阵的元素进行增删改操作;创建成功之后可以转化成其他格式的稀疏矩阵(如csr_matrix、csc_matrix)进行转置、矩阵乘法等操作。
image.png
coo_matrix的优点:
· 有利于稀疏格式之间的快速转换(tobsr()、tocsr()、to_csc()、to_dia()、to_dok()、to_lil())
· 允许又重复项(格式转换的时候自动相加)
· 能与CSR / CSC格式的快速转换
coo_matrix的缺点:
· 不能直接进行算术运算

csr_matrix

上面的coo格式是否还能优化呢,我们注意到,每行都有很多元素,如下面数组,行索引row indices为[1,1,2,4,4,4,6]这里面其实是很多重复元素的,我们可以将其压缩,只需要记录重复元素的个数就可以。
csr_matrix,全称Compressed Sparse Row matrix,即按行压缩的稀疏矩阵存储方式,由三个一维数组indptr, indices, data组成。indptr存储之前行中非零值的累积计数,indices是按行顺序存储每行中数据的列号,与data中的元素一一对应。这种格式要求矩阵元按行顺序存储,每一行中的元素可以乱序存储。indptr存储的其实是每行元素个数数组的前缀和数组,这样我们就很容易知道每行有多少个元素,对于Data中的第i个数,我们可以根据indptr很容易得到他属于哪一行,然后配合列指标indices,就可以将Data和原来的行列对应起来。
image.png

csc_matrix

csc_matrix和csr_matrix正好相反,即按列压缩的稀疏矩阵存储方式,同样由三个一维数组indptr, indices, data组成,如下图所示:
image.png

lil_matrix

lil_matrix,即List of Lists format,又称为Row-based linked list sparse matrix。它使用两个嵌套列表存储稀疏矩阵:data保存每行中的非零元素的值,rows保存每行非零元素所在的列号(列号是顺序排序的)。这种格式很适合逐个添加元素,并且能快速获取行相关的数据。其初始化方式同coo_matrix初始化的前三种方式:通过密集矩阵构建、通过其他矩阵转化以及构建一个一定shape的空矩阵。
image.png

dok_matrix

dok_matrix,即Dictionary Of Keys based sparse matrix,是一种类似于coo matrix但又基于字典的稀疏矩阵存储方式,key由非零元素的的坐标值tuple(row, column)组成,value则代表数据值。dok matrix非常适合于增量构建稀疏矩阵,并一旦构建,就可以快速地转换为coo_matrix。

dia_matrix

dia_matrix,全称Sparse matrix with DIAgonal storage,是一种对角线的存储方式。如下图中,将稀疏矩阵使用offsets和data两个矩阵来表示。offsets表示data中每一行数据在原始稀疏矩阵中的对角线位置k(k>0, 对角线往右上角移动;k<0, 对角线往左下方移动;k=0,主对角线)。该格式的稀疏矩阵可用于算术运算:它们支持加法,减法,乘法,除法和矩阵幂。
image.png

有限元法中的稀疏矩阵

有限元刚度矩阵为何是稀疏的

局部性原理

  • 在有限元法中,整体结构或域被划分成许多小的、互不相交的有限单元。每个有限单元仅与其相邻单元通过共享节点(顶点)相互作用。因此,刚度矩阵的每一行和每一列对应的节点只与其相邻的节点相互作用。远离该节点的节点不会直接影响它,从而导致矩阵中大部分元素为零。

节点的有限连接

  • 每个节点只与少数几个相邻节点相连。这意味着每个节点对应的刚度矩阵行(或列)只有少数几个非零元素,对应这些相邻节点的贡献。这种局部相互作用导致了刚度矩阵的稀疏性。



上年图片实例来自:[Graphical Representation of Sparse Matrices - MATLAB & Simulink Example (mathworks.com)]

刚度矩阵带宽估计

假设我们有一个三维问题,它的离散化通常会产生一个对称稀疏矩阵 A A A。在这个矩阵中,只有靠近主对角线的元素是非零的。矩阵 A A A 的半带宽 B W BW BW 定义为:
B W = max ⁡ i , j { ∣ i − j ∣   ∣   a i j ≠ 0 } BW = \max_{i,j} \{ |i - j| \ | \ a_{ij} \neq 0 \} BW=maxi,j{ij  aij=0}
即矩阵中所有非零元素的行索引和列索引之差的最大值,也是非零元素到所在行的对角元素之间距离的最大值。
image.png

三维问题的带宽估计

对于三维问题,通常会在网格上离散化,例如 n × n × n n \times n \times n n×n×n 的网格。假设我们使用有限差分法离散化,得到的稀疏矩阵 A A A 的非零元素主要分布在主对角线附近。
对于三维问题,我们可以设想每个点与其在 x x x y y y z z z 方向上的相邻点相连。每个点在三维网格中的索引可以表示为 ( i , j , k ) (i, j, k) (i,j,k),其中 i , j , k i, j, k i,j,k 是点在 x x x y y y z z z 方向上的坐标。将这些坐标展平到一个一维数组中,点 ( i , j , k ) (i, j, k) (i,j,k) 的索引可以表示为:
i d x = i + j ⋅ n + k ⋅ n 2 idx = i + j \cdot n + k \cdot n^2 idx=i+jn+kn2
在这种情况下,如果我们考虑点 ( i , j , k ) (i, j, k) (i,j,k) 与其相邻点的关系,其非零元素的索引差值为:
∣ i d x − i d x neighbor ∣ |idx - idx_{\text{neighbor}}| idxidxneighbor
索引差值最大为 n 2 n^2 n2,因此带宽 BH为 n 2 n^2 n2

SkyLine存储格式

有限元的刚度矩阵,一般情况下,不仅稀疏,而且对称,对称意味着数据可以只存一半,有限元中有一种常用的稀疏矩阵存储格式SkyLine存储格式

  • 一个数组A用于存储所有列从对角线到最后一个非零元素
  • 一个索引数组,存储每一个对角线元素在value中的索引

A(i,j) i<= j 的值如何计算? 先找到 j列有几个非零值 num_val = index[j+1] - index[j]
如果 j-i < num_val ,则 为0 ,否则在A数组的索引为index[j] - (j-i)

Skyline存储格式可以看做是CSC的特例,由于非零元素对称的分布在对角元素附近,所以只需要存储每列有多少个元素,而每个元素的行索引,可以直接根据离对角元素的距离计算出,而不用单独的行索引数组。
image.png
i n d e x = [ 1 、 2 、 4 、 6 、 10 、 12 、 16 、 18 、 22 ] index = [1 、 2 、 4 、 6 、10 、 12 、 16、 18、 22] index=[12461012161822]

如何在组装前知道稀疏矩阵的结构?需要遍历单元,找到每一个单元对应的自由度里面的最小的非零行,例如单元对应的刚度举证项为k[i,j], 则第j列的 第i个值非0.

有限元刚度阵带宽优化

由上面可知,稀疏矩阵的带宽由单元自由度最大差值决定,而单元自由度一般根据节点编号进行编号,因而我们可以通过优化节点编号的方式来降低刚度矩阵的带宽,这是一个经典的图论问题,节点可以看做是图上的节点,节点之间的连接可以看作是图的边,现在要求两个相连的节点的最大差值最小。

网格的图表示法

在有限元分析中的矩阵一般都是稀疏的,即刚度矩阵中非零元的数目要远小于零元素的数目,如果将结点和结点的连接关系抽象为一张图,那么刚度矩阵本质上就是这张图的邻接矩阵表示。如果元素 K i j > 0 K_{ij} >0 Kij>0, 说明自由度i和j是相邻顶点, K i j K_{ij} Kij的值可以看做是边的权重。
image.png
用一个二维数组A存放图G各顶点间的相邻关系,称这个二维数组为图G的邻接矩阵(Adjacency Matrix)。图G与它的邻接矩阵A呈一、一对应关系。设图G的邻接矩阵为 A = a i j A=a_{ij} A=aij,图中某两顶点 v i v_i vi v j v_j vj相邻,则对应于矩阵A中元素 a i j = 1 a_{ij}=1 aij=1,否则 a i j = 0 a_{ij}=0 aij=0。如果矩阵A是对称矩阵,则图G是一个无向图。此时矩阵的带宽可以表示为:
B H = max ⁡ { ∣ f ( ν 1 ) − f ( ν 2 ) ∣ : { v 1 , v 2 } ∈ E ( G ) } BH=\max\left\{\left|f(\nu_{1})-f(\nu_{2})\right|:\{v_{1},v_{2}\}\in E(G)\right\} BH=max{f(ν1)f(ν2):{v1,v2}E(G)}

CM和RCM重排算法

CM算法最初由Cuthill和Mckee在1969年首先提出,用于稀疏矩阵的重排序以减小矩阵带宽。George完善改进了CM算法得到RCM(Reverse Cuthill-Mckee)算法。RCM算法和CM算法基本相同,只不过把CM排序数组逆序排列。

网格图的BFG层级结构

对于网格结构组成的图,选择一个给定顶点 V V V为根顶点 r r r,从根顶点出发,进行BFS遍历,将每层记录为 L 1 , L 2 … … L m L_1,L_2……L_m L1L2……Lm,形成图_G_的层级结构 L L L,各层中顶点的数目被定义为该层的宽 W i W_i Wi,层级结构 L L L总的宽度 W ( L ) = m a x W i W(L)= max { W_i} W(L)=maxWi。我们可以知道, L m − 1 L_{m-1} Lm1 L m L_{m} Lm层之间相互连接的节点最大编号差不大于 L m − 1 L_{m-1} Lm1 L m L_{m} Lm层节点数之和。如果按照层级顺序由根顶点始按从小到大顺序对各个顶点依次分配新节点编号,那么由此构造的新矩阵带宽 B H BH BH与层级结构的宽度 W ( L ) W(L) W(L)有如下关系:
B H < = 2 W ( L ) BH <= 2W(L) BH<=2W(L)
降低矩阵的带宽和轮廓的问题可被转化为降低以矩阵所生成的层级结构 L L L的宽度问题。

RCM算法

RCM算法基于无向图的BFS算法,以生成最长层次结构为目标,具体实现方法:

  • (1)生成矩阵_A_的无向图_G_(A),找出_G_中度最小的顶点,并分别以这些顶点为根顶点生成各自的层级结构,找出各层级结构中宽度最小的层级结构。
  • (2)按层的递增顺序分配新的编号:
    • 根顶点分配为1
    • 由第二层开始,将每一层中顶点的各个顶点按照度从小到大排列并分配编号
    • 重复(2)中的步骤,直至所有顶点均被分配到新的编号,按照新的编号生成CM排序数组。
  • (3)对于步骤2中生成的各个CM排序数组,计算新得到的矩阵的带宽,保留带宽最小的CM排序数组;
  • (4)将CM排序数组反转,得到RCM排序数组。

下图为前文机翼结构网格邻接矩阵在经过RCM重排序后的优化效果,可以看到,优化效果比较显著。
image.pngimage.png

有限元刚度矩阵内存规模估计

有了前面的知识,现在我们可以对有限元刚度矩阵的内存规模进行大致的估计了,对于一个具有 N N N个自由度规模的问题,刚度矩阵的大小为 N 2 N^2 N2, 如果 采用重排序优化,可以大大减小稀疏矩阵带宽,我们考虑一个100万自由度问题,内存占用约为100万8BH(Byte) = 8 * BH(M),假设x,y,x三个方向网格数量比较均匀,则三个方向自由度为100100100,BH约等于10000,则内存占用约为80G, 如果进一步能够降低BH到100, 则内存占用为0.8G,我们可以参考下图中的数据,对于传热问题,每百万自由度占用的内存约为1.25G。对于不同类型的物理场问题,相同规模自由度占用的内存差异较大。

image.png
image.png
上图引自:[ 求解大型 COMSOL 模型需要多少内存? | COMSOL 博客]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1986352.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【模版进阶】

模版进阶 小杨 一、非类型模版参数 模板参数分为类型形参与非类型形参。 类型形参即&#xff1a;出现在模板参数列表中&#xff0c;跟在class或者typename之类的参数类型名称。 非类型形参&#xff0c;就是用一个常量作为类(函数)模板的一个参数&#xff0c;在类(函数)模板中可…

mysql数据库触发器同步数据

首先检查数据源库是否支持触发器&#xff0c;show ENGINES&#xff0c;如果FEDERATED是NO&#xff0c;表示未开启&#xff0c;如需开启&#xff0c;再mysql配置文件中&#xff0c;添加federated配置到mysqld下面。 一、同服务器不同库触发器同步&#xff0c;这里只举例插入数据…

【用Java学习数据结构系列】探索Java集合框架的无尽秘密pro

看到这句话的时候证明&#xff1a;此刻你我都在努力 加油陌生人 个人主页&#xff1a;Gu Gu Study专栏&#xff1a;用Java学习数据结构系列 喜欢的一句话&#xff1a; 常常会回顾努力的自己&#xff0c;所以要为自己的努力留下足迹 喜欢的话可以点个赞谢谢了。 作者&#xff…

修改SpringBoot启动图标banner

方式一: 将图标文件命名为banner放在resources目录下 文本文件banner 图片banner 方式二&#xff1a;通过配置文件指定图标路径 指定文本图标&#xff1a;spring.banner.locationclasspath:相对于resources下的位置 ("classpath:"可以省略) 指定图片作为图标: sprin…

C语言——扫雷游戏

扫雷游戏通常是一个由方格组成的区域内进行的&#xff0c;其中随机分布着一定数量的地雷 。玩家的目标是通过点击方格来标记出所有地雷的位置&#xff0c;同时避免自己点到地雷而导致游戏失败。游戏开始时&#xff0c;玩家通常只能看到一部分方格&#xff0c;而其余的方格则需要…

消息框:tkinter.messagebox

文章目录 一、tkinter 简介二、tkinter 基础&#xff08;部件 布局管理器&#xff09;三、项目实战3.1、主循环&#xff1a;root.mainloop()3.2、手动摧毁窗口&#xff1a;root.destroy()3.3、布局管理器&#xff1a;pack3.4、布局管理器&#xff1a;grid3.5、布局管理器&…

【ML】transform 之 decoder 及其实现细节

【ML】transform 之 decoder 及其实现细节 1. decoder2. encoder 和decoder 之间是如何处理和传递讯息的&#xff1f;self-attention3. 查询&#xff08;Query&#xff09;、键&#xff08;Key&#xff09;、值&#xff08;Value&#xff09;是三个核心概念及其具体含义和计算方…

轻松应对大量订单:快递批量查询软件大揭秘

在日常生活和工作中&#xff0c;我们经常会遇到需要查询多个快递单号物流信息的情况&#xff0c;无论是电商卖家需要跟踪大量订单&#xff0c;还是消费者想要及时了解自己包裹的运输状态&#xff0c;手动逐一查询都显得既繁琐又低效。今天&#xff0c;我就向大家推荐一款效果非…

如何使用Alist:多网盘管理神器!一站式挂载、集成管理,支持WebDav

在日常生活中&#xff0c;我们或多或少会使用不同的网盘存储和处理各类文件&#xff0c;这往往导致我们的文件管理繁琐且效率低下。 Alist支持将多种不同的网盘服务集成到一个统一的界面中&#xff0c;让你能够轻松地挂载和管理所有文件。 通过Alist&#xff0c;你可以在一个界…

阿里发布“神笔马良版Sora”:寥寥数笔,动画自成

AI视频生成赛道风起云涌&#xff0c;国内外新颖的文生、图生视频产品层出不穷。在各大厂商的“内卷”之下&#xff0c;当下的视频生成模型各方面已经接近“以假乱真”的效果。例如&#xff0c;OpenAI 的 Sora 和国内的 Vidu、可灵等模型&#xff0c;通过利用 Diffusion Transfo…

structuredClone():JavaScript中深拷贝对象的最简单方法

前端岗位内推来了 深拷贝是传递或存储数据时的一项常规编程任务。 浅拷贝&#xff1a;只复制对象的第一层深拷贝&#xff1a;复制对象的所有层级 const obj { name: Tari, friends: [{ name: Messi }] };const shallowCopy { ...obj };const deepCopy dCopy(obj);console.lo…

C++——多态经典案例(二)制作饮品

案例&#xff1a;制作饮品的步骤是差不多一样的&#xff0c;假设都有四步&#xff0c;打开包装Open、煮水Boil、放杯子里面PutInCup、放佐料PutSomething、喝Drink 利用多态&#xff0c;制作茶和咖啡等饮品 分析&#xff1a;定义一个抽象类&#xff0c;纯虚函数包括Open、Boil…

C++(1):构造函数,复制函数和析构函数

引用 ref这里是对i起了一个别名 引用和指针区别区别1.引用直接绑定2.引用必须初始化 auyo a 10;自动匹配a的类型&#xff0c;但是初始化必须给值 内联函数放头文件 不传参形参有默认值 默认形参b有b后面的都必须有默认 函数重载&#xff1a;同名不同参&#xff08;返回值不能作…

浅学 Pytorch

&#xff08;一&#xff09;Dataset Dataset 是一个抽象类&#xff0c;用于表示数据集。它封装了数据的加载和预处理逻辑&#xff0c;使得数据的读取和处理更加灵活和易于管理。在PyTorch中&#xff0c;torch.utils.data.Dataset 是一个基类&#xff0c;用户可以继承并实现自己…

软件渗透测试详细介绍,专业软件测评机构分享

随着信息技术的飞速发展&#xff0c;软件应用已成为我们生活和工作中不可或缺的一部分。然而&#xff0c;与此&#xff0c;信息安全问题也日益凸显&#xff0c;网络攻击的频繁发生让企业和用户面临前所未有的风险。为了更好地保护软件产品的安全性&#xff0c;渗透测试应运而生…

Mysql执行计划(上)

1、执行计划的概念 执行计划是什么&#xff1a;使用EXPLAIN关键字可以模拟优化器执行SQL查询语句&#xff0c;从而知道MySQL是如何处理你的SQL语句的。 作用&#xff1a;分析你的查询语句或是表结构的性能瓶颈 语法&#xff1a;Explain SQL语句 执行计划输出内容介绍&#…

记录一次网关无响应的排查

1. 使用jstack pid > thread.txt 打印进 thread.txt 文件里 去观察线程的状态。 我发现&#xff0c;一个线程在经过 rateliter的prefilter后, 先是调用 consume方法&#xff0c;获取到锁。 接着在执行 jedis的 evalsha命令时 一直卡在socket.read()的状态。 发现jedis官…

【iOS】OC关键字总结及底层原理(上)

目录 线程安全相关的关键字atomic&nonatomic 作用域相关的关键字static、extern、const&auto 读写权限相关和指定方法名的关键字内存管理相关的关键字&#xff08;或方法&#xff09;1. 引用计数的存储SideTableretain方法源码分析release方法源码分析dealloc方法源码分…

无缝融入,即刻智能[4]:MaxKB知识库问答系统[进一步深度开发调试,完成基于API对话,基于ollama大模型本地部署等]

无缝融入,即刻智能[4]:MaxKB知识库问答系统[进一步深度开发调试,完成基于API对话,基于ollama大模型本地部署等] 1.简介 MaxKB(Max Knowledge Base)是一款基于 LLM 大语言模型的开源知识库问答系统, 1.1 产品优势 开箱即用:支持直接上传文档、自动爬取在线文档,支持文本…

计算机网络 6.3Internet组成6.4Internet地址

第三节 Internet组成 一、基本结构及特点 1.Internet结构类型&#xff1a;分层网络互联群体。 2.主要构成&#xff1a;①主干网&#xff1b;②中间层网&#xff1b;③底层网。 3.结构特点&#xff1a; ①对用户隐藏网间连接的底层节点。 ②不指定网络互联的拓扑结构。 ③…