using System; using System.Collections.Generic; namespace Science.Mathematics.PartialDifferentialEquation { /// /// LinearEllipticEquationTwoDimension /// C_xxU_xx+C_xU_x+C_yyU_yy+C_yU_y+C_zzU_zz+C_zU_z /// +C_xyU_xy+C_xzU_xz+C_yzU_yz+C_propU=C_source /// public class LinearEllipticEquation3D { public delegate double Coefficient(double x, double y, double z); public LinearEllipticEquation3D() { } private double delta, rj; public double MeshSize { get{return delta;} set{delta=value;} } public double JacobiRadius { get{return rj;} set{rj=value;} } private Domain3D dtd; public Domain3D Domain { set{dtd=value;} } private Coefficient cxx, cx, cyy, cy, czz, cz, cxy, cxz, cyz, cprop, csource; public Coefficient CoefficientOfSecondDerivativeOfX { set{cxx=value;} } public Coefficient CoefficientOfFirstDerivativeOfX { set{cx=value;} } public Coefficient CoefficientOfSecondDerivativeOfY { set{cyy=value;} } public Coefficient CoefficientOfFirstDerivativeOfY { set{cy=value;} } public Coefficient CoefficientOfSecondDerivativeOfZ { set { czz = value; } } public Coefficient CoefficientOfFirstDerivativeOfZ { set { cz = value; } } public Coefficient CoefficientOfDerivativeOfXandY { set{cxy=value;} } public Coefficient CoefficientOfDerivativeOfXandZ { set { cxz = value; } } public Coefficient CoefficientOfDerivativeOfYandZ { set { cyz = value; } } public Coefficient CoefficientOfProportional { set{cprop=value;} } public Coefficient CoefficientOfSourceTerm { set{csource=value;} } private List al = new List(); public void SetBoundaryValue(double xFrom, double yFrom, double zFrom, double xTo, double yTo, double zTo, double boundaryValue) { al.Add(xFrom); al.Add(yFrom); al.Add(zFrom); al.Add(xTo); al.Add(yTo); al.Add(zTo); al.Add(boundaryValue); } private bool[,,] isItInDomain; private double[,,] bv; public void Solve() { double x, y, z; int nbv = al.Count / 7; double xf = dtd.LowerBoundOfX; double xt = dtd.UpperBoundOfX; double yf = dtd.LowerBoundOfY; double yt = dtd.UpperBoundOfY; double zf = dtd.LowerBoundOfZ; double zt = dtd.UpperBoundOfZ; int jx = (int)((xt - xf) / delta) + 1; int jy = (int)((yt - yf) / delta) + 1; int jz = (int)((zt - zf) / delta) + 1; double[, ,] axp = new double[jx, jy, jz]; double[, ,] axm = new double[jx, jy, jz]; double[, ,] ayp = new double[jx, jy, jz]; double[, ,] aym = new double[jx, jy, jz]; double[, ,] azp = new double[jx, jy, jz]; double[, ,] azm = new double[jx, jy, jz]; double[, ,] axy = new double[jx, jy, jz]; double[, ,] axz = new double[jx, jy, jz]; double[, ,] ayz = new double[jx, jy, jz]; double[, ,] aprop = new double[jx, jy, jz]; double[, ,] asource = new double[jx, jy, jz]; isItInDomain = new bool[jx,jy,jz]; bv = new double[jx,jy,jz]; solution = new double[jx,jy,jz]; for(int k = 0; k < jx; k++) { x = xf + k*delta; for(int m = 0; m < jy; m++) { y = yf + m*delta; for (int n = 0; n < jz; n++) { z = zf + n*delta; axp[k, m, n] = cxx(x, y, z) + cx(x, y, z) * delta / 2.0; axm[k, m, n] = cxx(x, y, z) - cx(x, y, z) * delta / 2.0; ayp[k, m, n] = cyy(x, y, z) + cy(x, y, z) * delta / 2.0; aym[k, m, n] = cyy(x, y, z) - cy(x, y, z) * delta / 2.0; azp[k, m, n] = czz(x, y, z) + cz(x, y, z) * delta / 2.0; azm[k, m, n] = czz(x, y, z) - cz(x, y, z) * delta / 2.0; aprop[k, m, n] = - 2.0 * cxx(x, y, z) - 2.0 * cyy(x, y, z) - 2.0 * czz(x, y, z) + cprop(x, y, z) * delta * delta; asource[k, m, n] = csource(x, y, z) * delta * delta; axy[k, m, n] = cxy(x, y, z) / 4.0; axz[k, m, n] = cxz(x, y, z) / 4.0; ayz[k, m, n] = cyz(x, y, z) / 4.0; isItInDomain[k, m, n] = dtd.Check(x, y, z); if (!isItInDomain[k, m, n]) { for (int kk = 0; kk < nbv; kk++) { if (Convert.ToDouble(al[7 * kk]) < x && x < Convert.ToDouble(al[7 * kk + 3]) && Convert.ToDouble(al[7 * kk + 1]) < y && y < Convert.ToDouble(al[7 * kk + 4]) && Convert.ToDouble(al[7 * kk + 2]) < z && z < Convert.ToDouble(al[7 * kk + 5])) bv[k, m, n] = Convert.ToDouble(al[7 * kk + 6]); } } } } } for (int k = 0; k < jx; k++) { for (int m = 0; m < jy; m++) { for (int n = 0; n < jz; n++) { solution[k, m, n] = bv[k, m, n]; } } } sor(axp,axm,ayp,aym,azp,azm,aprop,asource,axy,axz,ayz,solution, rj); } private double[, ,] solution; public double[, ,] Solution { get { return solution; } } // numerical recipes private int MAXITS = 1000; private double EPS = 1.0e-5; private void sor(double[,,]axp,double[,,]axm,double[,,]ayp,double[,,]aym, double[,,]azp,double[,,]azm,double[,,]aprop,double[,,]asource, double[, ,] axy, double[, ,] axz, double[, ,] ayz, double[, ,] u, double rjac) { int jmax = u.GetLength(0); int ipass,j,jsw,l,lsw,n,m; double anorm = 0.0, omega=1.0, resid; for (n = 1; n <= MAXITS; n++) { anorm = 0.0; jsw = 1; for (ipass = 1; ipass <= 2; ipass++) { lsw = jsw; for (j = 1; j < jmax - 1; j++) { for (m = 1; m < jmax - 1; m++) { for (l = lsw; l < jmax - 1; l += 2) { if (isItInDomain[j, m, l]) { resid = axp[j, m, l] * u[j + 1, m, l] + axm[j, m, l] * u[j - 1, m, l] + ayp[j, m, l] * u[j, m + 1, l] + aym[j, m, l] * u[j, m - 1, l] + azp[j, m, l] * u[j, m, l + 1] + azm[j, m, l] * u[j, m, l - 1] + aprop[j, m, l] * u[j, m, l] - asource[j, m, l] + axy[j, m, l] * (u[j + 1, m + 1, l] + u[j - 1, m - 1, l] - u[j + 1, m - 1, l] - u[j - 1, m + 1, l]) + axz[j, m, l] * (u[j + 1, m, l + 1] + u[j - 1, m, l - 1] - u[j + 1, m, l - 1] - u[j - 1, m, l + 1]) + ayz[j, m, l] * (u[j, m + 1, l + 1] + u[j, m - 1, l - 1] - u[j, m + 1, l - 1] - u[j, m - 1, l + 1]); anorm += Math.Abs(resid); u[j, m, l] += omega * resid / 6.0; } else u[j, m, l] = bv[j, m, l]; } lsw = 3 - lsw; } } jsw=3-jsw; omega=(n == 1 && ipass == 1 ? 1.0/(1.0-0.5*rjac*rjac) : 1.0/(1.0-0.25*rjac*rjac*omega)); } if (anorm < EPS) return; } try { throw new Science.Error(); } catch (Science.Error er) { er.Write("MAXITS exceeded"); } } } }