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); }