matlab ilu函数,不完全 LU 分解

ilu

不完全 LU 分解

语法

ilu(A,setup)

[L,U] = ilu(A,setup)

[L,U,P] = ilu(A,setup)

说明

ilu 生成一个单位下三角矩阵、一个上三角矩阵和一个置换矩阵。

ilu(A,setup) 计算 A 的不完全 LU 分解。setup 是一个最多包含五个设置选项的输入结构体。这些字段必须严格按照下表所示方法命名。您可以在此结构体中包含任意数目的字段,并以任意顺序定义这些字段。忽略任何其他字段。

字段名称说明type分解的类型。type 的值包括:

'nofill'(默认) - 执行具有 0 填充级别的 ILU 分解(称为 ILU(0))。如果将 type 设置为 'nofill',则仅使用 milu 设置选项;所有其他字段都将被忽略。

'crout' - 执行 ILU 分解的 Crout 版本,称为 ILUC。如果将 type 设置为 'crout',则仅使用 droptol 和 milu 设置选项;所有其他字段都将被忽略。

'ilutp' - 执行带阈值和选择主元的 ILU 分解。

如果未指定 type,则会执行 0 填充级别的 ILU 分解。在将 type 设置为 'ilutp' 的情况下,仅会执行选择主元的分解。

droptol不完全 LU 分解的调降容差。droptol 是一个非负标量。默认值为 0,这会生成完全的 LU 分解。

U 的非零项满足

abs(U(i,j)) >= droptol*norm(A(:,j)),

但对角线元除外(无论是否满足标准,系统都保留了这些元)。在使用主元调整 L 的元之前,将根据局部调降容差检验这些元,这同样适用于 L 中的非零值

abs(L(i,j)) >= droptol*norm(A(:,j))/U(j,j).

milu修改后的不完全 LU 分解。milu 的值包括:

'row' - 生成行总和修正的不完全 LU 分解。新构成的因子列中的条目从上三角因子 U 的对角线中减去,并保留列总和。也即 A*e =

L*U*e,其中 e 是由 1 组成的向量。

'col' - 生成列总和修正的不完全 LU 分解。新构成的因子列中的条目从上三角因子 U 的对角线中减去,并保留列总和。即 e'*A =

e'*L*U。

'off'(默认值)- 不生成修正的不完全 LU 分解。

udiag如果 udiag 为 1,上三角因子的对角线上的任何零都将替换为局部调降容差。默认值为 0。

threshPivot threshold between 0(强制对角线数据透视)和 1 之间的主元阈值(默认值),该阈值始终选择数据透视表中的列的最大量值条目。

ilu(A,setup) 返回 L+U-speye(size(A)),其中 L 为单位下三角矩阵,U 为上三角矩阵。

[L,U] = ilu(A,setup) 分别在 L 和 U 中返回单位下三角矩阵和上三角矩阵。

[L,U,P] = ilu(A,setup) 返回 L 中的单位下三角矩阵、U 中的上三角矩阵和 P 中的置换矩阵。

局限性

ilu 仅适用于稀疏方阵。

示例

从一个稀疏矩阵开始,并计算 LU 分解。

A = gallery('neumann', 1600) + speye(1600);

setup.type = 'crout';

setup.milu = 'row';

setup.droptol = 0.1;

[L,U] = ilu(A,setup);

e = ones(size(A,2),1);

norm(A*e-L*U*e)

ans =

1.4251e-014

此示例显示 A 和 L*U(其中 L 和 U 由修正的 Crout ILU 给出)具有相同的行总和。

从一个稀疏矩阵开始,并计算 LU 分解。

A = gallery('neumann', 1600) + speye(1600);

setup.type = 'nofill';

nnz(A)

ans =

7840

nnz(lu(A))

ans =

126478

nnz(ilu(A,setup))

ans =

7840

此示例显示 A 具有 7840 个非零值,完全 LU 分解具有 126478 个非零值,不完全 LU 分解(采用 0 填充级别)具有 7840 个非零值,数量与 A 的数量相同。

提示

这些不完全分解可很好地用作通过 BICG(双共轭梯度)、GMRES(广义最小残差法)等迭代方法求解的线性方程组的预条件子。

参考

[1] Saad, Yousef, Iterative Methods

for Sparse Linear Systems, PWS Publishing

Company, 1996, Chapter 10 - Preconditioning

Techniques.

扩展功能

分布式数组

使用 Parallel Computing Toolbox™ 在群集的组合内存中对大型数组进行分区。

用法说明和限制:

如果在结构体数组 setup 中包含字段 type,则必须将其设置为 'nofill'。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是对称上三角稀疏矩阵非零元素的一维存储及LU分解法求解的C#代码示例: ```csharp using System; namespace SymmetricUpperTriangularSparseMatrix { public class Matrix { int n; int[] irow, jcol; double[] val; public Matrix(int n, int[] irow, int[] jcol, double[] val) { this.n = n; this.irow = irow; this.jcol = jcol; this.val = val; } public void LUDecompose(out Matrix L, out Matrix U) { int[] il = new int[n + 1]; int[] iu = new int[n + 1]; int[] jl = new int[val.Length]; int[] ju = new int[val.Length]; double[] al = new double[val.Length]; double[] au = new double[val.Length]; for (int i = 0; i < n + 1; i++) { il[i] = -1; iu[i] = -1; } for (int k = 0; k < n; k++) { il[k] = k; iu[k] = k; int ll = -1, lu = -1; for (int p = irow[k]; p < irow[k + 1]; p++) { int j = jcol[p]; if (j < k) { if (il[k] == k) il[k] = p; jl[++ll] = j; al[ll] = val[p]; } else if (j == k) { if (il[k] == k) il[k] = p; if (iu[k] == k) iu[k] = p; al[k] = val[p]; au[k] = 1.0; } else { ju[++lu] = j; au[lu] = val[p]; } } for (int p = 0; p <= ll; p++) { int i = jl[p]; double lki = al[p] / al[k]; for (int q = iu[i]; q <= irow[i + 1] - 1; q++) { int j = jcol[q]; if (j > k) break; int r = j == k ? k : il[k]; if (il[j] < 0) { jl[++ll] = j; al[ll] = -lki * val[q]; il[j] = ll; } else { al[il[j]] -= lki * val[q]; } if (il[k] < 0) { il[k] = lu + 1; iu[k + 1] = lu + 1; ju[++lu] = k; au[lu] = al[k]; } au[r] -= lki * au[q]; } } } int[] ilu = new int[n + 1]; int[] jlu = new int[val.Length]; double[] valL = new double[val.Length]; double[] valU = new double[val.Length]; for (int i = 0; i < n + 1; i++) { ilu[i] = -1; } int cntL = 0, cntU = 0; for (int i = 0; i < n; i++) { for (int p = il[i]; p <= il[i + 1] - 1; p++) { int j = jl[p]; if (j < i) { jlu[cntL] = j; valL[cntL] = al[p]; if (ilu[i] < 0) ilu[i] = cntL; cntL++; } else if (j == i) { valL[cntL] = 1.0; if (ilu[i] < 0) ilu[i] = cntL; cntL++; } else { jlu[cntU] = j; valU[cntU] = au[p]; if (ilu[i] < 0) ilu[i] = cntU; cntU++; } } for (int p = iu[i]; p <= iu[i + 1] - 1; p++) { int j = ju[p]; if (j < i) { jlu[cntL] = j; valL[cntL] = al[p]; if (ilu[i] < 0) ilu[i] = cntL; cntL++; } else if (j == i) { valL[cntL] = 1.0; if (ilu[i] < 0) ilu[i] = cntL; cntL++; } else { jlu[cntU] = j; valU[cntU] = au[p]; if (ilu[i] < 0) ilu[i] = cntU; cntU++; } } } L = new Matrix(n, ilu, jlu, valL); U = new Matrix(n, ilu, jlu, valU); } public double[] LUSolve(double[] b) { Matrix L, U; LUDecompose(out L, out U); double[] y = new double[n]; for (int i = 0; i < n; i++) { y[i] = b[i]; for (int p = L.irow[i]; p < L.irow[i + 1]; p++) { int j = L.jcol[p]; if (j < i) y[i] -= L.val[p] * y[j]; } } double[] x = new double[n]; for (int i = n - 1; i >= 0; i--) { x[i] = y[i]; for (int p = U.irow[i]; p < U.irow[i + 1]; p++) { int j = U.jcol[p]; if (j > i) x[i] -= U.val[p] * x[j]; } x[i] /= U.val[U.irow[i]]; } return x; } } class Program { static void Main(string[] args) { int n = 3; int[] irow = { 0, 1, 2, 3 }; int[] jcol = { 0, 1, 2, 1, 2, 2 }; double[] val = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 }; Matrix A = new Matrix(n, irow, jcol, val); double[] b = { 1.0, 2.0, 3.0 }; double[] x = A.LUSolve(b); Console.WriteLine("Solution:"); for (int i = 0; i < n; i++) { Console.WriteLine(x[i]); } } } } ``` 该代码中定义了一个 Matrix 类,其构造函数输入稀疏矩阵的维数、非零元素的行列下标及值。LUDecompose 方法实现了对称上三角稀疏矩阵的 LU 分解,并输出分解后的 L 和 U 矩阵。LUSolve 方法实现了使用 LU 分解求解线性方程组。最后的 Main 方法给出了一个样例,其输入的稀疏矩阵是一个 $3 \times 3$ 的矩阵,用 LU 分解求解线性方程组。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值