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 代码格式

cs 复制代码
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]);
                    }
                }
            }
        }
    }
}
相关推荐
xlsw_几秒前
java全栈day20--Web后端实战(Mybatis基础2)
java·开发语言·mybatis
靴子学长几秒前
基于字节大模型的论文翻译(含免费源码)
人工智能·深度学习·nlp
AI_NEW_COME1 小时前
知识库管理系统可扩展性深度测评
人工智能
Dream_Snowar1 小时前
速通Python 第三节
开发语言·python
海棠AI实验室1 小时前
AI的进阶之路:从机器学习到深度学习的演变(一)
人工智能·深度学习·机器学习
hunteritself1 小时前
AI Weekly『12月16-22日』:OpenAI公布o3,谷歌发布首个推理模型,GitHub Copilot免费版上线!
人工智能·gpt·chatgpt·github·openai·copilot
XH华1 小时前
初识C语言之二维数组(下)
c语言·算法
南宫生2 小时前
力扣-图论-17【算法学习day.67】
java·学习·算法·leetcode·图论
不想当程序猿_2 小时前
【蓝桥杯每日一题】求和——前缀和
算法·前缀和·蓝桥杯
高山我梦口香糖2 小时前
[react]searchParams转普通对象
开发语言·前端·javascript