public void Build_FVM13(ref int xDim, ref int yDim, ref int zDim, bool PML)
                {
                    double rt2 = Math.Sqrt(2);
                    double rt3 = Math.Sqrt(3);

                    dx = Rm.Sound_speed(0) / fmax * .1;

                    Bounds = new AABB(Rm.Min() - new Point(.05 * dx, .05 * dx, .05 * dx), Rm.Max() + new Point(.05 * dx, .05 * dx, .05 * dx));

                    int no_of_Layers = 0;
                    double max_Layer = 0;

                    if (PML)
                    {
                        no_of_Layers = 10;
                        max_Layer = 0.5;
                    }

                    double x_length = Bounds.X_Length() + (no_of_Layers * 2 + 1) * dx;
                    double y_length = Bounds.Y_Length() + (no_of_Layers * 2 + 1) * dx;
                    double z_length = Bounds.Z_Length() + (no_of_Layers * 2 + 1) * dx;

                    //estimated distance between nodes
                    xDim = (int)Math.Ceiling(x_length / dx);                                //set number of nodes in x direction
                    dx = x_length / xDim;                                                   //refined distance between nodes
                    yDim = (int)Math.Ceiling(y_length / dx);                                //set number of nodes in y direction
                    dy = y_length / yDim;
                    zDim = (int)Math.Ceiling(z_length / dx);                                //set number of nodes in z direction
                    dz = z_length / zDim;

                    //dt = dx / (Math.Sqrt(1.0 / 3.0) * (Rm.Sound_speed(0)));                           //set time step small enough to satisfy courrant condition
                    dt = dx / (Rm.Sound_speed(0));                           //set time step small enough to satisfy courrant condition
                    //dt = dx / (Math.Sqrt(.75) * (Rm.Sound_speed));                           //set time step small enough to satisfy courrant condition
                    dxrt2 = dx * rt2;
                    dxrt3 = dx * rt3;

                    Dir = new Vector[13]{
                        //new Vector(-1,double.Epsilon,double.Epsilon),
                        //new Vector(double.Epsilon,-1,double.Epsilon),
                        //new Vector(double.Epsilon,double.Epsilon,-1),

                        //new Vector(-1/rt2,-1/rt2,double.Epsilon),
                        //new Vector(1/rt2, -1/rt2,double.Epsilon),
                        //new Vector(-1/rt2, double.Epsilon, 1/rt2),
                        //new Vector(double.Epsilon, -1/rt2, 1/rt2),
                        //new Vector(1/rt2, double.Epsilon, 1/rt2),
                        //new Vector(double.Epsilon, 1/rt2, 1/rt2),

                        //new Vector(-1/rt2,-1/rt2,1/rt2),
                        //new Vector(1/rt2,-1/rt2,1/rt2),
                        //new Vector(1/rt2,1/rt2,1/rt2),
                        //new Vector(-1/rt2,1/rt2,1/rt2)
                        new Vector(-1, 0, 0),
                        new Vector(0, -1, 0),
                        new Vector(0, 0, -1),

                        new Vector(-1/rt2,-1/rt2,double.Epsilon),
                        new Vector(1/rt2, -1/rt2,double.Epsilon),
                        new Vector(-1/rt2, double.Epsilon, 1/rt2),
                        new Vector(double.Epsilon, -1/rt2, 1/rt2),
                        new Vector(1/rt2, double.Epsilon, 1/rt2),
                        new Vector(double.Epsilon, 1/rt2, 1/rt2),

                        new Vector(-dx, -dy/rt2, dz/rt2),
                        new Vector(dx, -dy/rt2, dz/rt2),
                        new Vector(dx, dy/rt2, dz/rt2),
                        new Vector(-dx, dy/rt2, dz/rt2)

                    };

                    foreach (Vector V in Dir) V.Normalize();

                    xDim = (int)Math.Ceiling((double)xDim * rt2 / 2);

                    PFrame = new Node[xDim][][];// yDim, zDim];                               //pressure scalar field initialisation

                    List<Bound_Node_RDD> Bound = new List<Bound_Node_RDD>();

                    //dx = dx/rt2;
                    Point MinPt = Bounds.Min_PT - new Point(dx * no_of_Layers, dy * no_of_Layers, dz * no_of_Layers);

                    //System.Threading.Tasks.Parallel.For(0, xDim, (x) =>
                    for (int x = 0; x < PFrame.Length; x++)
                    {
                        int mod = x % 2;
                        PFrame[x] = new Node[(int)(Math.Floor((double)yDim / 2) + yDim % 2 * mod)][];
                        Random Rnd = new Random(x);
                        for (int y = 0; y < PFrame[x].Length; y++)
                        {
                            PFrame[x][y] = new Node[(int)(Math.Floor((double)zDim / 2) + yDim % 2 * mod)];
                            for (int z = 0; z < PFrame[x][y].Length; z++)
                            {
                                List<double> abs;
                                List<Bound_Node.Boundary> BDir;
                                Point Loc = new Point(MinPt.x + 2 * (((double)x - 0.5) * dx / rt2), MinPt.y + 2 * (((double)y + (0.5 - 0.5 * mod)) * dy), MinPt.z + 2 * (((double)z + (0.5 - 0.5 * mod)) * dz));
                                if (!Intersect_13Pt(Loc, SD.frequency, out BDir, out abs, ref Rnd))
                                {
                                    PFrame[x][y][z] = new RDD_Node(Loc);//, rho0, dt, dx, Rm.Sound_speed, new int[] { x, y, z });
                                }
                                else
                                {
                                    PFrame[x][y][z] =
                                        new Bound_Node_RDD(Loc, rho0, dt, dx, Rm.Sound_speed(0), new int[] { x, y, z }, abs, BDir);
                                    Bound.Add(PFrame[x][y][z] as Bound_Node_RDD);
                                }
                            }
                        }
                    }//);

                    Node.Attenuation = Math.Sqrt(Math.Pow(10, -.1 * Rm.AttenuationPureTone(PFrame[0][0][0].Pt, SD.frequency) * dt));

                    bool failed = false;
                    //Make Mesh Templates:
                    Build_Mesh_Sections();
                    for (int x = 0; x < PFrame.Length; x++)
                    //System.Threading.Tasks.Parallel.For(0, xDim, (x) =>
                    {
                        for (int y = 0; y < PFrame[x].Length; y++)
                        {
                            for (int z = 0; z < PFrame[x][y].Length; z++)
                            {
                                PFrame[x][y][z].Link_Nodes(ref PFrame, x, y, z);
                            }
                        }
                    }//);

                    yDim = PFrame[0].Length;
                    zDim = PFrame[0][0].Length;

                    foreach (Bound_Node_RDD b in Bound) b.Complete_Boundary();
                    if (failed) return;

                    //Set up PML...
                    Layers = new Acoustic_Compact_FDTD.PML(no_of_Layers, max_Layer, PFrame);

                    //Connect Sources and Receivers...
                    SD.Connect_Grid(PFrame, Bounds, dx, dy, dz, tmax, dt, no_of_Layers);
                    Mic.Connect_Grid(PFrame, Bounds, dx, tmax, dt, no_of_Layers);
                }
                public void Build_Interp(ref int xDim, ref int yDim, ref int zDim)
                {
                    dx = Rm.Sound_speed(0) / fmax * .1;

                    Bounds = new AABB(Rm.Min() - new Point(.05 * dx, .05 * dx, .05 * dx), Rm.Max() + new Point(.05 * dx, .05 * dx, .05 * dx));
                    double x_length = Bounds.X_Length();
                    double y_length = Bounds.Y_Length();
                    double z_length = Bounds.Z_Length();

                    //estimated distance between nodes
                    xDim = (int)Math.Ceiling(x_length / dx);                                //set number of nodes in x direction
                    dx = x_length / xDim;                                                       //refined distance between nodes
                    yDim = (int)Math.Ceiling(y_length / dx);                                //set number of nodes in y direction
                    double dy = y_length / yDim;
                    zDim = (int)Math.Ceiling(z_length / dx);                              //set number of nodes in z direction
                    double dz = z_length / zDim;

                    dt = dx / (Math.Sqrt(1.0 / 3.0) * (Rm.Sound_speed(0)));                           //set time step small enough to satisfy courrant condition
                    dt = dx / (Rm.Sound_speed(0));                           //set time step small enough to satisfy courrant condition
                    //dt = dx / (Math.Sqrt(.75) * (Rm.Sound_speed));                           //set time step small enough to satisfy courrant condition
                    double rt2 = Math.Sqrt(2);
                    double rt3 = Math.Sqrt(3);
                    dxrt2 = dx * rt2;
                    dxrt3 = dx * rt3;

                    Dir = new Vector[13]{
                        new Vector(-1,double.Epsilon,double.Epsilon),
                        new Vector(double.Epsilon,-1,double.Epsilon),
                        new Vector(double.Epsilon,double.Epsilon,-1),

                        new Vector(-1/rt2,-1/rt2,double.Epsilon),
                        new Vector(1/rt2, -1/rt2,double.Epsilon),

                        new Vector(-1/rt2, double.Epsilon, 1/rt2),
                        new Vector(double.Epsilon, -1/rt2, 1/rt2),
                        new Vector(1/rt2, double.Epsilon, 1/rt2),
                        new Vector(double.Epsilon, 1/rt2, 1/rt2),

                        new Vector(-1/rt3,-1/rt3,1/rt3),
                        new Vector(1/rt3,-1/rt3,1/rt3),
                        new Vector(1/rt3,1/rt3,1/rt3),
                        new Vector(-1/rt3,1/rt3,1/rt3)
                    };

                    foreach (Vector V in Dir) V.Normalize();

                    PFrame = new P_Node[xDim][][];// yDim, zDim];                               //pressure scalar field initialisation

                    //System.Threading.Tasks.Parallel.For(0, xDim, (x) =>
                    for (int x = 0; x < xDim; x++)
                    {
                        PFrame[x] = new P_Node[yDim][];
                        Random Rnd = new Random(x);
                        for (int y = 0; y < yDim; y++)
                        {
                            PFrame[x][y] = new P_Node[zDim];
                            for (int z = 0; z < zDim; z++)
                            {
                                List<double[]> abs;
                                List<Bound_Node.Boundary> BDir;
                                Point Loc = new Point(Bounds.Min_PT.x + (((double)x + 0.5) * dx), Bounds.Min_PT.y + (((double)y + 0.5) * dy), Bounds.Min_PT.z + (((double)z + 0.5) * dz));
                                if (!Intersect_26Pt(Loc, out BDir, out abs, ref Rnd))
                                {
                                    PFrame[x][y][z] = new P_Node(Loc);//, rho0, dt, dx, Rm.Sound_speed, new int[] { x, y, z });
                                }
                                else
                                {
                                    PFrame[x][y][z] =
                                        new Bound_Node_IWB(Loc, rho0, dt, dx, Rm.Sound_speed(0), new int[] { x, y, z }, abs, BDir);
                                }
                            }
                        }
                    }//);

                    bool failed = false;
                    //Make Mesh Templates:
                    Build_Mesh_Sections();
                    for (int x = 0; x < xDim; x++)
                    //System.Threading.Tasks.Parallel.For(0, xDim, (x) =>
                    {
                        for (int y = 0; y < yDim; y++)
                        {
                            for (int z = 0; z < zDim; z++)
                            {
                                try
                                {
                                    PFrame[x][y][z].Link_Nodes(ref PFrame, x, y, z);
                                }
                                catch
                                {
                                    //Display faulty voxels in a display conduit here...
                                    UI.CellConduit.Instance.Add(PFrame[x][y][z], x, y, z, dx, Utilities.PachTools.HPttoRPt(Bounds.Min_PT));
                                    failed = true;
                                }
                            }
                        }
                    }//);

                    if (failed) return;

                    SD.Connect_Grid(PFrame, Bounds, dx, dy, dz, tmax, dt, 0);
                    Mic.Connect_Grid(PFrame, Bounds, dx, tmax, dt, 0);
                }