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]);
                    }
                }
            }
        }
    }
}
相关推荐
昨日之日200627 分钟前
Moonshine - 新型开源ASR(语音识别)模型,体积小,速度快,比OpenAI Whisper快五倍 本地一键整合包下载
人工智能·whisper·语音识别
浮生如梦_29 分钟前
Halcon基于laws纹理特征的SVM分类
图像处理·人工智能·算法·支持向量机·计算机视觉·分类·视觉检测
深度学习lover30 分钟前
<项目代码>YOLOv8 苹果腐烂识别<目标检测>
人工智能·python·yolo·目标检测·计算机视觉·苹果腐烂识别
△曉風殘月〆32 分钟前
WPF MVVM入门系列教程(二、依赖属性)
c#·wpf·mvvm
XiaoLeisj1 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
热爱跑步的恒川1 小时前
【论文复现】基于图卷积网络的轻量化推荐模型
网络·人工智能·开源·aigc·ai编程
励志成为嵌入式工程师2 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
逐·風2 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
捕鲸叉3 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer3 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法