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
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
//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
{
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]);
}
}
}
}
}
}
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 rho { get; set; } = new List();
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(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 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]);
}
}
}
}
}
}