微分方程,Mgfas的计算方法与源程序"/>
C#,数值计算——偏微分方程,Mgfas的计算方法与源程序
1 文本格式
using System;
using System.Collections.Generic;
namespace Legalsoft.Truffer
{
public class Mgfas
{
public int n { get; set; }
public int ng { get; set; }
public double[,] uj;
public double[,] uj1 { get; set; }
public List<double[,]> rho { get; set; } = new List<double[,]>();
public Mgfas(double[,] u, int maxcyc)
{
this.n = u.GetLength(0);
this.ng = 0;
int nn = n;
while ((nn >>= 1) != 0)
{
ng++;
}
if ((n - 1) != (1 << ng))
{
throw new Exception("n-1 must be a power of 2 in mgfas.");
}
nn = n;
int ngrid = ng - 1;
rho = new List<double[,]>(ng);
//rho.resize(ng);
rho[ngrid] = new double[nn, nn];
rho[ngrid] = u;
while (nn > 3)
{
nn = nn / 2 + 1;
rho[--ngrid] = new double[nn, nn];
//rstrct(ref rho[ngrid], rho[ngrid + 1]);
double[,] tmp = rho[ngrid];
rstrct( tmp, rho[ngrid + 1]);
//rho[ngrid] = new double[,](tmp);
rho[ngrid] = Globals.CopyFrom(tmp);
}
nn = 3;
uj = new double[nn, nn];
slvsm2( uj, rho[0]);
for (int j = 1; j < ng; j++)
{
nn = 2 * nn - 1;
uj1 = uj;
uj = new double[nn, nn];
double[,] temp = new double[nn, nn];
interp( uj, uj1);
uj1 = null;
for (int jcycle = 0; jcycle < maxcyc; jcycle++)
{
double trerr = 1.0;
mg(j, uj, temp, rho, ref trerr);
lop( temp, uj);
matsub(temp, rho[j], temp);
double res = anorm2(temp);
if (res < trerr)
{
break;
}
}
}
u = uj;
}
public void matadd(double[,] a, double[,] b, double[,] c)
{
int n = a.GetLength(0);
for (int j = 0; j < n; j++)
{
for (int i = 0; i < n; i++)
{
c[i, j] = a[i, j] + b[i, j];
}
}
}
public void matsub(double[,] a, double[,] b, double[,] c)
{
int n = a.GetLength(0);
for (int j = 0; j < n; j++)
{
for (int i = 0; i < n; i++)
{
c[i, j] = a[i, j] - b[i, j];
}
}
}
public void slvsm2(double[,] u, double[,] rhs)
{
double h = 0.5;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
u[i, j] = 0.0;
}
}
double fact = 2.0 / (h * h);
double disc = Math.Sqrt(fact * fact + rhs[1, 1]);
u[1, 1] = -rhs[1, 1] / (fact + disc);
}
public void relax2(double[,] u, double[,] rhs)
{
int n = u.GetLength(0);
int jsw = 1;
double h = 1.0 / (n - 1);
double h2i = 1.0 / (h * h);
double foh2 = -4.0 * h2i;
for (int ipass = 0; ipass < 2; ipass++, jsw = 3 - jsw)
{
int isw = jsw;
for (int j = 1; j < n - 1; j++, isw = 3 - isw)
{
for (int i = isw; i < n - 1; i += 2)
{
double res = h2i * (u[i + 1, j] + u[i - 1, j] + u[i, j + 1] + u[i, j - 1] - 4.0 * u[i, j]) + u[i, j] * u[i, j] - rhs[i, j];
u[i, j] -= res / (foh2 + 2.0 * u[i, j]);
}
}
}
}
public void rstrct(double[,] uc, double[,] uf)
{
int nc = uc.GetLength(0);
int ncc = 2 * nc - 2;
for (int jf = 2, jc = 1; jc < nc - 1; jc++, jf += 2)
{
for (int iif = 2, ic = 1; ic < nc - 1; ic++, iif += 2)
{
uc[ic, jc] = 0.5 * uf[iif, jf] + 0.125 * (uf[iif + 1, jf] + uf[iif - 1, jf] + uf[iif, jf + 1] + uf[iif, jf - 1]);
}
}
for (int jc = 0, ic = 0; ic < nc; ic++, jc += 2)
{
uc[ic, 0] = uf[jc, 0];
uc[ic, nc - 1] = uf[jc, ncc];
}
for (int jc = 0, ic = 0; ic < nc; ic++, jc += 2)
{
uc[0, ic] = uf[0, jc];
uc[nc - 1, ic] = uf[ncc, jc];
}
}
public void lop(double[,] xout, double[,] u)
{
int n = u.GetLength(0);
double h = 1.0 / (n - 1);
double h2i = 1.0 / (h * h);
for (int j = 1; j < n - 1; j++)
{
for (int i = 1; i < n - 1; i++)
{
xout[i, j] = h2i * (u[i + 1, j] + u[i - 1, j] + u[i, j + 1] + u[i, j - 1] - 4.0 * u[i, j]) + u[i, j] * u[i, j];
}
}
for (int i = 0; i < n; i++)
{
xout[i, 0] = xout[i, n - 1] = xout[0, i] = xout[n - 1, i] = 0.0;
}
}
public void interp(double[,] uf, double[,] uc)
{
int nf = uf.GetLength(0);
int nc = nf / 2 + 1;
for (int jc = 0; jc < nc; jc++)
{
for (int ic = 0; ic < nc; ic++)
{
uf[2 * ic, 2 * jc] = uc[ic, jc];
}
}
for (int jf = 0; jf < nf; jf += 2)
{
for (int iif = 1; iif < nf - 1; iif += 2)
{
uf[iif, jf] = 0.5 * (uf[iif + 1, jf] + uf[iif - 1, jf]);
}
}
for (int jf = 1; jf < nf - 1; jf += 2)
{
for (int iif = 0; iif < nf; iif++)
{
uf[iif, jf] = 0.5 * (uf[iif, jf + 1] + uf[iif, jf - 1]);
}
}
}
public double anorm2(double[,] a)
{
double sum = 0.0;
int n = a.GetLength(0);
for (int j = 0; j < n; j++)
{
for (int i = 0; i < n; i++)
{
sum += a[i, j] * a[i, j];
}
}
return Math.Sqrt(sum) / n;
}
public void mg(int j, double[,] u, double[,] rhs, List<double[,]> rho, ref double trerr)
{
const int NPRE = 1;
const int NPOST = 1;
const double ALPHA = 0.33;
double dum = -1.0;
int nf = u.GetLength(0);
int nc = (nf + 1) / 2;
double[,] temp = new double[nf, nf];
if (j == 0)
{
matadd(rhs, rho[j], temp);
slvsm2( u, temp);
}
else
{
double[,] v = new double[nc, nc];
double[,] ut = new double[nc, nc];
double[,] tau = new double[nc, nc];
double[,] tempc = new double[nc, nc];
for (int jpre = 0; jpre < NPRE; jpre++)
{
if (trerr < 0.0)
{
matadd(rhs, rho[j], temp);
relax2( u, temp);
}
else
{
relax2( u, rho[j]);
}
}
rstrct( ut, u);
v = Globals.CopyFrom(ut);
lop( tau, ut);
lop( temp, u);
if (trerr < 0.0)
{
matsub(temp, rhs, temp);
}
rstrct( tempc, temp);
matsub(tau, tempc, tau);
if (trerr > 0.0)
{
trerr = ALPHA * anorm2(tau);
}
mg(j - 1, v, tau, rho, ref dum);
matsub(v, ut, tempc);
interp( temp, tempc);
matadd(u, temp, u);
for (int jpost = 0; jpost < NPOST; jpost++)
{
if (trerr < 0.0)
{
matadd(rhs, rho[j], temp);
relax2( u, temp);
}
else
{
relax2( u, rho[j]);
}
}
}
}
}
}
2 代码格式
using System;
using System.Collections.Generic;namespace Legalsoft.Truffer
{public class Mgfas{public int n { get; set; }public int ng { get; set; }public double[,] uj;public double[,] uj1 { get; set; }public List<double[,]> rho { get; set; } = new List<double[,]>();public Mgfas(double[,] u, int maxcyc){this.n = u.GetLength(0);this.ng = 0;int nn = n;while ((nn >>= 1) != 0){ng++;}if ((n - 1) != (1 << ng)){throw new Exception("n-1 must be a power of 2 in mgfas.");}nn = n;int ngrid = ng - 1;rho = new List<double[,]>(ng);//rho.resize(ng);rho[ngrid] = new double[nn, nn];rho[ngrid] = u;while (nn > 3){nn = nn / 2 + 1;rho[--ngrid] = new double[nn, nn];//rstrct(ref rho[ngrid], rho[ngrid + 1]);double[,] tmp = rho[ngrid];rstrct( tmp, rho[ngrid + 1]);//rho[ngrid] = new double[,](tmp);rho[ngrid] = Globals.CopyFrom(tmp);}nn = 3;uj = new double[nn, nn];slvsm2( uj, rho[0]);for (int j = 1; j < ng; j++){nn = 2 * nn - 1;uj1 = uj;uj = new double[nn, nn];double[,] temp = new double[nn, nn];interp( uj, uj1);uj1 = null;for (int jcycle = 0; jcycle < maxcyc; jcycle++){double trerr = 1.0;mg(j, uj, temp, rho, ref trerr);lop( temp, uj);matsub(temp, rho[j], temp);double res = anorm2(temp);if (res < trerr){break;}}}u = uj;}public void matadd(double[,] a, double[,] b, double[,] c){int n = a.GetLength(0);for (int j = 0; j < n; j++){for (int i = 0; i < n; i++){c[i, j] = a[i, j] + b[i, j];}}}public void matsub(double[,] a, double[,] b, double[,] c){int n = a.GetLength(0);for (int j = 0; j < n; j++){for (int i = 0; i < n; i++){c[i, j] = a[i, j] - b[i, j];}}}public void slvsm2(double[,] u, double[,] rhs){double h = 0.5;for (int i = 0; i < 3; i++){for (int j = 0; j < 3; j++){u[i, j] = 0.0;}}double fact = 2.0 / (h * h);double disc = Math.Sqrt(fact * fact + rhs[1, 1]);u[1, 1] = -rhs[1, 1] / (fact + disc);}public void relax2(double[,] u, double[,] rhs){int n = u.GetLength(0);int jsw = 1;double h = 1.0 / (n - 1);double h2i = 1.0 / (h * h);double foh2 = -4.0 * h2i;for (int ipass = 0; ipass < 2; ipass++, jsw = 3 - jsw){int isw = jsw;for (int j = 1; j < n - 1; j++, isw = 3 - isw){for (int i = isw; i < n - 1; i += 2){double res = h2i * (u[i + 1, j] + u[i - 1, j] + u[i, j + 1] + u[i, j - 1] - 4.0 * u[i, j]) + u[i, j] * u[i, j] - rhs[i, j];u[i, j] -= res / (foh2 + 2.0 * u[i, j]);}}}}public void rstrct(double[,] uc, double[,] uf){int nc = uc.GetLength(0);int ncc = 2 * nc - 2;for (int jf = 2, jc = 1; jc < nc - 1; jc++, jf += 2){for (int iif = 2, ic = 1; ic < nc - 1; ic++, iif += 2){uc[ic, jc] = 0.5 * uf[iif, jf] + 0.125 * (uf[iif + 1, jf] + uf[iif - 1, jf] + uf[iif, jf + 1] + uf[iif, jf - 1]);}}for (int jc = 0, ic = 0; ic < nc; ic++, jc += 2){uc[ic, 0] = uf[jc, 0];uc[ic, nc - 1] = uf[jc, ncc];}for (int jc = 0, ic = 0; ic < nc; ic++, jc += 2){uc[0, ic] = uf[0, jc];uc[nc - 1, ic] = uf[ncc, jc];}}public void lop(double[,] xout, double[,] u){int n = u.GetLength(0);double h = 1.0 / (n - 1);double h2i = 1.0 / (h * h);for (int j = 1; j < n - 1; j++){for (int i = 1; i < n - 1; i++){xout[i, j] = h2i * (u[i + 1, j] + u[i - 1, j] + u[i, j + 1] + u[i, j - 1] - 4.0 * u[i, j]) + u[i, j] * u[i, j];}}for (int i = 0; i < n; i++){xout[i, 0] = xout[i, n - 1] = xout[0, i] = xout[n - 1, i] = 0.0;}}public void interp(double[,] uf, double[,] uc){int nf = uf.GetLength(0);int nc = nf / 2 + 1;for (int jc = 0; jc < nc; jc++){for (int ic = 0; ic < nc; ic++){uf[2 * ic, 2 * jc] = uc[ic, jc];}}for (int jf = 0; jf < nf; jf += 2){for (int iif = 1; iif < nf - 1; iif += 2){uf[iif, jf] = 0.5 * (uf[iif + 1, jf] + uf[iif - 1, jf]);}}for (int jf = 1; jf < nf - 1; jf += 2){for (int iif = 0; iif < nf; iif++){uf[iif, jf] = 0.5 * (uf[iif, jf + 1] + uf[iif, jf - 1]);}}}public double anorm2(double[,] a){double sum = 0.0;int n = a.GetLength(0);for (int j = 0; j < n; j++){for (int i = 0; i < n; i++){sum += a[i, j] * a[i, j];}}return Math.Sqrt(sum) / n;}public void mg(int j, double[,] u, double[,] rhs, List<double[,]> rho, ref double trerr){const int NPRE = 1;const int NPOST = 1;const double ALPHA = 0.33;double dum = -1.0;int nf = u.GetLength(0);int nc = (nf + 1) / 2;double[,] temp = new double[nf, nf];if (j == 0){matadd(rhs, rho[j], temp);slvsm2( u, temp);}else{double[,] v = new double[nc, nc];double[,] ut = new double[nc, nc];double[,] tau = new double[nc, nc];double[,] tempc = new double[nc, nc];for (int jpre = 0; jpre < NPRE; jpre++){if (trerr < 0.0){matadd(rhs, rho[j], temp);relax2( u, temp);}else{relax2( u, rho[j]);}}rstrct( ut, u);v = Globals.CopyFrom(ut);lop( tau, ut);lop( temp, u);if (trerr < 0.0){matsub(temp, rhs, temp);}rstrct( tempc, temp);matsub(tau, tempc, tau);if (trerr > 0.0){trerr = ALPHA * anorm2(tau);}mg(j - 1, v, tau, rho, ref dum);matsub(v, ut, tempc);interp( temp, tempc);matadd(u, temp, u);for (int jpost = 0; jpost < NPOST; jpost++){if (trerr < 0.0){matadd(rhs, rho[j], temp);relax2( u, temp);}else{relax2( u, rho[j]);}}}}}
}
更多推荐
C#,数值计算——偏微分方程,Mgfas的计算方法与源程序
发布评论