• 検索結果がありません。

ター さ た一般化最小残差法 (GMRES : Generalized Minimum Residual) 使用し 線形方程式 Ax

= b

ます

梗概

#include <imsl.h>

float *imsl_f_lin_sol_gen_min_residual (int n, void amultp (float *p, float *z), float *b, ..., 0) double型 関数 imsl_d_lin_sol_gen_min_residual

必須 引数

int n 。入力) 行列 行数

void amultp (float *p, float *z)

z = Ap 計算す 提供 関数

float *b 。入力)

右辺 含 長さ n ベク

戻 値

線形方程式 Ax = b x インタ 領域 解放す imsl_free 使用します 解

が得 い場合 NULL が返さ ます

プ ン引数 梗概

#include <imsl.h>

float *imsl_f_lin_sol_gen_min_residual (int n, void amultp (), float *b, IMSL_RETURN_USER, float x[],

IMSL_MAX_ITER, int *maxit, IMSL_REL_ERR, float tolerance, IMSL_PRECOND, void precond(),

IMSL_MAX_KRYLOV_SUBSPACE_DIM, int kdmax, IMSL_HOUSEHOLDER_REORTHOG,

IMSL_FCN_W_DATA, void amultp (), void *data, IMSL_PRECOND_W_DATA, void precond(), void *data, 0)

プ ン引数

IMSL_RETURN_USER, float x[] 。出力)

x 含 長さ n ー 割 当 配列 IMSL_MAX_ITER, int *maxit 。入力/出力)

整数へ インタ 最初に 許さ GMRES 反復 最大数に設定さ ます 終了時 に 使用さ た反復数が返さ ます

フ : maxit = 1000

IMSL_REL_ERR, float tolerance 。入力)

こ ア

||b Ax ||

2 ||b||2 満たす x 計算します

ここ = tolerance す

フ : tolerance = sqrt(imsl_f_machine(4))

IMSL_PRECOND, void precond (float *r, float *z) 。入力)

z = M -1 r 設定す 提供 関数 ここ M 前処理行列 す

IMSL_MAX_KRYLOV_SUBSPACE_DIM, int kdmax 。入力)

Krylov 部分空間 最大 次元 す す わ ター さ 前に許さ 最大

GMRES 反復数 す

フ : kdmax = imsl_i_min(n, 20)

IMSL_HOUSEHOLDER_REORTHOG,

Gram-Schmidt プロ く Householder変換によ 直交化 実行します

IMSL_FCN_W_DATA, void amultp (float *p, float *z, void *data), void *data (入力)

z = Ap 計算す 提供 関数 によ 供給さ ータへ インタも

受け data ー 提供 関数に渡さ ータへ インタ す 詳細 イン

ロダク ン ー 定義関数に ータ 受け渡す方法 参照し 下さい IMSL_PRECOND_W_DATA, void precond (float *r, float *z, void *data), void *data (入力)

z = M -1r 提供 関数 ここ M 前処理行列 す こ また ー

によ 提供さ ータへ インタも受け data ー 定義関数に渡さ ータへ インタ す 詳細 イン ロダク ン ー 提供 関数に ータ 受け渡す方法 参照し 下さい

説明

imsl_f_lin_sol_gen_min_residual GMRES 使用し 線形方程式 Ax = b ます

コー H.F. Walker によ FORTRAN ーチン GMRES に基 ます こ 方法 Saad Schultz

(1986年) また Walker (1988年)に詳細が説明さ います

GMRES 法 近似解 x0 初期残差 r0

= b - Ax

0 ター ます 反復 m 修正 zm 次 Krylov

部分空間 決定さ ます:

m

(  )  span(  , A  ,..., A

m1

 )

ν

= r

0 次 最小二乗問題 解 す:

(zk

min

m(r0))

bA ( x

0

z )

2

反復 m xm = x0

+ z

m

Householder変換によ 直交化 Gram-Schmidt法よ 必要 しませ が 計算量 多い す

し しWalker (1988年) 特に残差 減少が限界に達す に Householder法 方がよ 安定し い

こ 報告し います

例題 1

例 し 次 行列 考えます

















6 0 0 0 2 1

3 1 5 0 0 1

0 1 10 0 0 2

0 0 0 15 0 0

0 0 1 3 10 0

0 0 0 0 0 10 A

Ax = (10, 7, 45, 33, 34, 31)T ように xT= (1, 2, 3, 4, 5, 6) にします 関数 imsl_f_mat_mul_rect_coordinate 用い 積 Ax ます

#include <imsl.h>

void amultp (float*, float*);

int main() {

float b[] = {10.0, 7.0, 45.0, 33.0, -34.0, 31.0};

int n = 6;

float *x;

x = imsl_f_lin_sol_gen_min_residual (n, amultp, b, 0);

imsl_f_write_matrix ("Solution, x, to Ax = b", 1, n, x, 0);

}

void amultp (float *p, float *z) {

Imsl_f_sparse_elem a[] = {0, 0, 10.0, 1, 1, 10.0, 1, 2, -3.0, 1, 3, -1.0, 2, 2, 15.0, 3, 0, -2.0, 3, 3, 10.0, 3, 4, -1.0, 4, 0, -1.0, 4, 3, -5.0, 4, 4, 1.0, 4, 5, -3.0, 5, 0, -1.0, 5, 1, -2.0, 5, 5, 6.0};

int n = 6;

int nz = 15;

imsl_f_mat_mul_rect_coordinate ("A*x", IMSL_A_MATRIX, n, n, nz, a, IMSL_X_VECTOR, n, p,

IMSL_RETURN_USER_VECTOR, z, 0);

}

出力

Solution, x, to Ax = b

1 2 3 4 5 6

1 2 3 4 5 6

例題 2

こ 例題 最初 例題 同 方程式 解 ます 今回 前処理行列 使います 前処理行列

A 対角項 します

#include <imsl.h>

#include <stdio.h>

void amultp (float*, float*);

void precond (float*, float*);

int main() {

float b[] = {10.0, 7.0, 45.0, 33.0, -34.0, 31.0};

int n = 6;

float *x;

int maxit = 1000;

x = imsl_f_lin_sol_gen_min_residual (n, amultp, b, IMSL_MAX_ITER, &maxit,

IMSL_PRECOND, precond, 0);

imsl_f_write_matrix ("Solution, x, to Ax = b", 1, n, x, 0);

printf ("\nNumber of iterations taken = %d\n", maxit);

}

/* Set z = Ap */

void amultp (float *p, float *z) {

static Imsl_f_sparse_elem a[] =

{0, 0, 10.0, 1, 1, 10.0, 1, 2, -3.0, 1, 3, -1.0, 2, 2, 15.0, 3, 0, -2.0, 3, 3, 10.0, 3, 4, -1.0, 4, 0, -1.0, 4, 3, -5.0, 4, 4, 1.0, 4, 5, -3.0, 5, 0, -1.0, 5, 1, -2.0, 5, 5, 6.0};

int n = 6;

int nz = 15;

imsl_f_mat_mul_rect_coordinate ("A*x", IMSL_A_MATRIX, n, n, nz, a,

IMSL_X_VECTOR, n, p,

IMSL_RETURN_USER_VECTOR, z, 0);

}

/* Solve Mz = r */

void precond (float *r, float *z) {

static float diagonal_inverse[] =

{0.1, 0.1, 1.0/15.0, 0.1, 1.0, 1.0/6.0};

int n = 6;

int i;

for (i=0; i<n; i++)

z[i] = diagonal_inverse[i]*r[i];

}

出力

Solution, x, to Ax = b

1 2 3 4 5 6

1 2 3 4 5 6

Number of iterations taken = 5

重大 ー

IMSL_STOP_USER_FCN ー 定義関数 計算 停 が要求さ た ー フ グ= "#"