/// <summary> /// /// </summary> /// <param name="field"></param> /// <param name="result"></param> /// <param name="parallel"></param> public static void GetCurl(this GridField3d <Vector3d> field, Vector3d[] result, bool parallel = false) { // implementation reference // http://www.math.harvard.edu/archive/21a_spring_09/PDF/13-05-curl-and-divergence.pdf if (parallel) { Parallel.ForEach(Partitioner.Create(0, field.CountXYZ), range => Body(range.Item1, range.Item2)); } else { Body(0, field.CountXYZ); } void Body(int from, int to) { var vals = field.Values; (var nx, var ny, var nz) = field.Count; int nxy = field.CountXY; (var dx, var dy, var dz) = (0.5 / field.Scale); (int di, int dj, int dk) = field.GetBoundaryOffsets(); (int i, int j, int k) = field.ToGridSpace(from); for (int index = from; index < to; index++, i++) { if (i == nx) { j++; i = 0; } if (j == ny) { k++; j = 0; } Vector3d tx0 = (i == 0) ? vals[index + di] : vals[index - 1]; Vector3d tx1 = (i == nx - 1) ? vals[index - di] : vals[index + 1]; Vector3d ty0 = (j == 0) ? vals[index + dj] : vals[index - nx]; Vector3d ty1 = (j == ny - 1) ? vals[index - dj] : vals[index + nx]; Vector3d tz0 = (k == 0) ? vals[index + dk] : vals[index - nxy]; Vector3d tz1 = (k == nz - 1) ? vals[index - dk] : vals[index + nxy]; result[index] = new Vector3d( (ty1.Z - ty0.Z) * dy - (tz1.Y - tz0.Y) * dz, (tz1.X - tz0.X) * dz - (tx1.Z - tx0.Z) * dx, (tx1.Y - tx0.Y) * dx - (ty1.X - ty0.X) * dy); } } }
/// <summary> /// /// </summary> /// <param name="field"></param> /// <param name="result"></param> /// <param name="parallel"></param> public static void GetLaplacian(this GridField3d <double> field, double[] result, bool parallel = false) { if (parallel) { Parallel.ForEach(Partitioner.Create(0, field.CountXYZ), range => Body(range.Item1, range.Item2)); } else { Body(0, field.CountXYZ); } void Body(int from, int to) { var vals = field.Values; (var nx, var ny, var nz) = field.Count; int nxy = field.CountXY; (var dx, var dy, var dz) = field.Scale; dx = 1.0 / (dx * dx); dy = 1.0 / (dy * dy); dz = 1.0 / (dz * dz); (int di, int dj, int dk) = field.GetBoundaryOffsets(); (int i, int j, int k) = field.ToGridSpace(from); for (int index = from; index < to; index++, i++) { if (i == nx) { j++; i = 0; } if (j == ny) { k++; j = 0; } double tx0 = (i == 0) ? vals[index + di] : vals[index - 1]; double tx1 = (i == nx - 1) ? vals[index - di] : vals[index + 1]; double ty0 = (j == 0) ? vals[index + dj] : vals[index - nx]; double ty1 = (j == ny - 1) ? vals[index - dj] : vals[index + nx]; double tz0 = (k == 0) ? vals[index + dk] : vals[index - nxy]; double tz1 = (k == nz - 1) ? vals[index - dk] : vals[index + nxy]; double t = vals[index] * 2.0; result[index] = (tx0 + tx1 - t) * dx + (ty0 + ty1 - t) * dy + (tz0 + tz1 - t) * dz; } } }
/// <summary> /// /// </summary> /// <param name="field"></param> /// <param name="result"></param> /// <param name="parallel"></param> public static void GetGradient(this GridField3d <double> field, Vector3d[] result, bool parallel = false) { if (parallel) { Parallel.ForEach(Partitioner.Create(0, field.CountXYZ), range => Body(range.Item1, range.Item2)); } else { Body(0, field.CountXYZ); } void Body(int from, int to) { var vals = field.Values; (var nx, var ny, var nz) = field.Count; int nxy = field.CountXY; (var dx, var dy, var dz) = (0.5 / field.Scale); (int di, int dj, int dk) = field.GetBoundaryOffsets(); (int i, int j, int k) = field.ToGridSpace(from); for (int index = from; index < to; index++, i++) { if (i == nx) { j++; i = 0; } if (j == ny) { k++; j = 0; } double tx0 = (i == 0) ? vals[index + di] : vals[index - 1]; double tx1 = (i == nx - 1) ? vals[index - di] : vals[index + 1]; double ty0 = (j == 0) ? vals[index + dj] : vals[index - nx]; double ty1 = (j == ny - 1) ? vals[index - dj] : vals[index + nx]; double tz0 = (k == 0) ? vals[index + dk] : vals[index - nxy]; double tz1 = (k == nz - 1) ? vals[index - dk] : vals[index + nxy]; result[index] = new Vector3d((tx1 - tx0) * dx, (ty1 - ty0) * dy, (tz1 - tz0) * dz); } } }