public static double SecondDerivative(SinglePhaseField field, int localCellIndex, NodeSet nodeSet) { // Evaluate gradient int length = 1; int noOfNodes = 1; int D = 2; MultidimensionalArray gradient = MultidimensionalArray.Create(length, noOfNodes, D); field.EvaluateGradient(localCellIndex, 1, nodeSet, gradient, ResultCellindexOffset: 0, ResultPreScale: 1.0); // Evalaute Hessian matrix MultidimensionalArray hessian = MultidimensionalArray.Create(length, noOfNodes, D, D); field.EvaluateHessian(localCellIndex, 1, nodeSet, hessian); // Compute second derivative along curve double g_alpha_alpha = 2 * ((hessian[0, 0, 0, 0] * gradient[0, 0, 0] + hessian[0, 0, 0, 1] * gradient[0, 0, 1]) * gradient[0, 0, 0] + (hessian[0, 0, 1, 0] * gradient[0, 0, 0] + hessian[0, 0, 1, 1] * gradient[0, 0, 1]) * gradient[0, 0, 1]); if (g_alpha_alpha == 0.0 || g_alpha_alpha.IsNaN()) { throw new NotSupportedException("Second derivative is zero"); } return(g_alpha_alpha); }
public static double[] NormalizedGradient(SinglePhaseField field, int localCellIndex, NodeSet nodeSet) { // Evaluate gradient int length = 1; int noOfNodes = 1; int D = 2; MultidimensionalArray gradient = MultidimensionalArray.Create(length, noOfNodes, D); field.EvaluateGradient(localCellIndex, 1, nodeSet, gradient, ResultCellindexOffset: 0, ResultPreScale: 1.0); // Normalize gradient double[] tmp = gradient.ExtractSubArrayShallow(0, 0, -1).To1DArray(); tmp.Normalize(); return(tmp); }
/// <summary> /// Evaluates the divergence of the modified integrand /// \f$ /// \nabla \cdot \vec{g} = \nabla \cdot (g \frac{\nabla \Phi}{|\nabla \Phi|}) /// \f$ /// which can be expanded to /// \f$ /// \nabla \cdot \vec{g} = \nabla g \frac{\nabla \Phi}{|\nabla \Phi|} + g ( /// \frac{\Delta \Phi}{|\nabla \Phi|} /// - \frac{\nabla \Phi}{|\nabla \Phi|} \frac{H(\Phi)}{|\nabla \Phi|} \frac{\nabla \Phi}{|\nabla \Phi|}) /// \f$ /// using the chain rule. HEre, \f$ H(\Phi)\f$ /// denotes the Hessian of the level set (i.e., the second derivatives) /// </summary> /// <param name="j0"> /// <see cref="LevelSetIntegrator.EvaluateDivergenceOfIntegrand"/> /// </param> /// <param name="Length"> /// <see cref="LevelSetIntegrator.EvaluateDivergenceOfIntegrand"/> /// </param> /// <param name="EvalResult"> /// <see cref="LevelSetIntegrator.EvaluateDivergenceOfIntegrand"/> /// </param> public override void EvaluateDivergenceOfIntegrand(NodeSet nodes, int j0, int Length, MultidimensionalArray EvalResult) { using (new FuncTrace()) { int D = base.m_LevSetTrk.GridDat.SpatialDimension; // spatial dimension int noOfNodes = EvalResult.GetLength(1); // number of nodes if (m_WeighFunctionBuffer.GetLength(0) != Length || m_WeighFunctionBuffer.GetLength(1) != noOfNodes) { m_IntegrandBuffer.Allocate(Length, noOfNodes); m_IntegrandGradientBuffer.Allocate(Length, noOfNodes, D); m_WeighFunctionBuffer.Allocate(Length, noOfNodes); m_LevelSetGradientBuffer.Allocate(Length, noOfNodes, D); m_LevelSetHessianBuffer.Allocate(Length, noOfNodes, D, D); } m_Field.Evaluate(j0, Length, nodes, m_IntegrandBuffer); m_Field.EvaluateGradient(j0, Length, nodes, m_IntegrandGradientBuffer, 0, 0.0); m_levSet.EvaluateGradient(j0, Length, nodes, m_LevelSetGradientBuffer); m_levSet.EvaluateHessian(j0, Length, nodes, m_LevelSetHessianBuffer); EvaluateWeightFunction(nodes, j0, Length, m_WeighFunctionBuffer); double[] Buf = new double[D]; for (int i = 0; i < Length; i++) { for (int j = 0; j < noOfNodes; j++) { if (m_WeighFunctionBuffer[i, j] == 0.0) { continue; } double AbsGradPhi = 0.0; for (int d = 0; d < D; d++) { double GradPhi_d = m_LevelSetGradientBuffer[i, j, d]; AbsGradPhi += GradPhi_d * GradPhi_d; } AbsGradPhi = Math.Sqrt(AbsGradPhi); if (AbsGradPhi < 1e-11) { // Assume zero since gradient is nearly zero continue; } double ooAbsGradPhi = 1.0 / AbsGradPhi; double term1 = 0.0; for (int d = 0; d < D; d++) { term1 += m_IntegrandGradientBuffer[i, j, d] * m_LevelSetGradientBuffer[i, j, d]; } term1 *= ooAbsGradPhi; double term2 = 0; for (int d = 0; d < D; d++) { term2 += m_LevelSetHessianBuffer[i, j, d, d]; } term2 *= ooAbsGradPhi; double term3 = 0; { for (int d1 = 0; d1 < D; d1++) { double a = 0; for (int d2 = 0; d2 < D; d2++) { a += m_LevelSetHessianBuffer[i, j, d1, d2] * m_LevelSetGradientBuffer[i, j, d2]; } Buf[d1] = a; } for (int d = 0; d < D; d++) { term3 += Buf[d] * m_LevelSetGradientBuffer[i, j, d]; } term3 *= (ooAbsGradPhi * ooAbsGradPhi * ooAbsGradPhi); } EvalResult[i, j, 0] = term1 + m_IntegrandBuffer[i, j] * (term2 - term3); } } } }