// triangle-winding-number second-order approximation // t is triangle, p is 'center' of cluster of dipoles, q is evaluation point static double triwn_order2(ref Triangle3d t, ref Vector3d p, ref Vector3d xn, ref double xA, ref Vector3d q) { Vector3d dpq = (p - q); double len = dpq.Length; double len3 = len * len * len; // first-order approximation - integrated_normal_area * \grad(G) double order1 = (xA / MathUtil.FourPI) * xn.Dot(dpq / len3); // second-order hessian \grad^2(G) Matrix3d xqxq = new Matrix3d(ref dpq, ref dpq); xqxq *= 3.0 / (MathUtil.FourPI * len3 * len * len); double diag = 1 / (MathUtil.FourPI * len3); Matrix3d hessian = new Matrix3d(diag, diag, diag) - xqxq; // second-order LHS - integrated second-order area matrix (formula 26) Vector3d centroid = new Vector3d( (t.V0.x + t.V1.x + t.V2.x) / 3.0, (t.V0.y + t.V1.y + t.V2.y) / 3.0, (t.V0.z + t.V1.z + t.V2.z) / 3.0); Vector3d dcp = centroid - p; Matrix3d o2_lhs = new Matrix3d(ref dcp, ref xn); double order2 = xA * o2_lhs.InnerProduct(ref hessian); return(order1 + order2); }
// point-winding-number second-order approximation // x is dipole point, p is 'center' of cluster of dipoles, q is evaluation point static double pointwn_order2(ref Vector3d x, ref Vector3d p, ref Vector3d xn, ref double xA, ref Vector3d q) { Vector3d dpq = (p - q); Vector3d dxp = (x - p); double len = dpq.Length; double len3 = len * len * len; // first-order approximation - area*normal*\grad(G) double order1 = (xA / MathUtil.FourPI) * xn.Dot(dpq / len3); // second-order hessian \grad^2(G) Matrix3d xqxq = new Matrix3d(ref dpq, ref dpq); xqxq *= 3.0 / (MathUtil.FourPI * len3 * len * len); double diag = 1 / (MathUtil.FourPI * len3); Matrix3d hessian = new Matrix3d(diag, diag, diag) - xqxq; // second-order LHS area * \outer(x-p, normal) Matrix3d o2_lhs = new Matrix3d(ref dxp, ref xn); double order2 = xA * o2_lhs.InnerProduct(ref hessian); return(order1 + order2); }