protected override void ComputeValues(NodeSet NS, int j0, int Len, MultidimensionalArray output) { MultidimensionalArray Phi = m_owner.GetLevSetValues(NS, j0, Len); MultidimensionalArray GradPhi = m_owner.GetLevelSetReferenceGradients(NS, j0, Len); MultidimensionalArray HessPhi = m_owner.GetLevelSetReferenceHessian(NS, j0, Len); MultidimensionalArray ooNormGrad = new MultidimensionalArray(2); MultidimensionalArray Laplace = new MultidimensionalArray(2); MultidimensionalArray Q = new MultidimensionalArray(3); int K = output.GetLength(1); int D = GradPhi.GetLength(2); Debug.Assert(D == this.m_owner.m_owner.GridDat.SpatialDimension); ooNormGrad.Allocate(Len, K); Laplace.Allocate(Len, K); Q.Allocate(Len, K, D); // compute the monstrous formula // ----------------------------- // norm of Gradient: for (int d = 0; d < D; d++) { var GradPhi_d = GradPhi.ExtractSubArrayShallow(-1, -1, d); ooNormGrad.Multiply(1.0, GradPhi_d, GradPhi_d, 1.0, "ik", "ik", "ik"); } ooNormGrad.ApplyAll(x => 1.0 / Math.Sqrt(x)); // laplacian of phi: for (int d = 0; d < D; d++) { var HessPhi_d_d = HessPhi.ExtractSubArrayShallow(-1, -1, d, d); Laplace.Acc(1.0, HessPhi_d_d); } // result = Laplacian(phi)/|Grad phi| output.Multiply(1.0, Laplace, ooNormGrad, 0.0, "ik", "ik", "ik"); // result = Grad(1/|Grad(phi)|) for (int d1 = 0; d1 < D; d1++) { var Qd = Q.ExtractSubArrayShallow(-1, -1, d1); for (int d2 = 0; d2 < D; d2++) { var Grad_d2 = GradPhi.ExtractSubArrayShallow(-1, -1, d2); var Hess_d2_d1 = HessPhi.ExtractSubArrayShallow(-1, -1, d2, d1); Qd.Multiply(-1.0, Grad_d2, Hess_d2_d1, 1.0, "ik", "ik", "ik"); } } ooNormGrad.ApplyAll(x => x * x * x); output.Multiply(1.0, GradPhi, Q, ooNormGrad, 1.0, "ik", "ikd", "ikd", "ik"); }
/// <summary> /// Change-of-basis, in cell 0 /// </summary> /// <param name="jCell"></param> /// <param name="pl"></param> public MultidimensionalArray GetChangeofBasisMatrix(int jCell, PolynomialList pl) { var m_Context = this.GridDat; int N = this.Length; int M = pl.Count; int J = this.GridDat.iLogicalCells.NoOfLocalUpdatedCells; if (jCell < 0 || jCell >= J) { throw new ArgumentOutOfRangeException("cell index out of range"); } MultidimensionalArray Mtx = MultidimensionalArray.Create(N, M); var cellMask = new CellMask(m_Context, new[] { new Chunk() { i0 = jCell, Len = 1 } }, MaskType.Geometrical); // we project the basis function from 'jCell1' onto 'jCell0' CellQuadrature.GetQuadrature(new int[2] { N, M }, m_Context, (new CellQuadratureScheme(true, cellMask)).Compile(m_Context, this.Degree + pl.MaxAbsoluteDegree), // integrate over target cell delegate(int i0, int Length, QuadRule QR, MultidimensionalArray _EvalResult) { NodeSet nodes_Cell0 = QR.Nodes; Debug.Assert(Length == 1); //NodesGlobal.Allocate(1, nodes_Cell0.GetLength(0), nodes_Cell0.GetLength(1)); //m_Context.TransformLocal2Global(nodes_Cell0, jCell0, 1, NodesGlobal, 0); //var nodes_Cell1 = new NodeSet(GridDat.iGeomCells.GetRefElement(jCell1), nodes_Cell0.GetLength(0), nodes_Cell0.GetLength(1)); //m_Context.TransformGlobal2Local(NodesGlobal.ExtractSubArrayShallow(0, -1, -1), nodes_Cell1, jCell1, null); //nodes_Cell1.LockForever(); var phi_0 = this.CellEval(nodes_Cell0, jCell, 1).ExtractSubArrayShallow(0, -1, -1); MultidimensionalArray R = MultidimensionalArray.Create(QR.NoOfNodes, pl.Count); pl.Evaluate(nodes_Cell0, R); var EvalResult = _EvalResult.ExtractSubArrayShallow(0, -1, -1, -1); EvalResult.Multiply(1.0, R, phi_0, 0.0, "knm", "km", "kn"); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { Debug.Assert(Length == 1); var res = ResultsOfIntegration.ExtractSubArrayShallow(0, -1, -1); Mtx.Clear(); Mtx.Acc(1.0, res); }).Execute(); return(Mtx); }
/// <summary> /// Transforms the given <paramref name="origTarget"/> into some /// serializable format. /// </summary> /// <param name="origTarget"></param> /// <returns></returns> public static object GetTarget(object origTarget) { if (origTarget is IMutableMatrixEx) { // Hack: Type is not serializable, so use full matrix instead origTarget = origTarget.As <IMutableMatrixEx>().ToFullMatrixOnProc0(); } else if (origTarget is NodeSet) { NodeSet nodeSet = origTarget.Cast <NodeSet>(); MultidimensionalArray temp = MultidimensionalArray.Create(nodeSet.Lengths); temp.Acc(1.0, nodeSet); origTarget = temp; } return(origTarget); }
/// <summary> /// curvature computation according to Bonnet's formula /// Copy-Paste from <see cref="LevelSet.EvaluatetotalCurvature"/>, since there is no analytic formula for the curvature of an ellipse /// </summary> public void EvaluateTotalCurvature(int j0, int Len, NodeSet NodeSet, MultidimensionalArray result) { // (siehe FK, persoenliche Notizen, 08mar13) // checks // ------ int K = NodeSet.NoOfNodes; if (result.Dimension != 2) { throw new ArgumentException(); } if (result.GetLength(0) != Len) { throw new ArgumentException(); } if (result.GetLength(1) != K) { throw new ArgumentException(); } int D = NodeSet.SpatialDimension; //Debug.Assert(D == this.GridDat.SpatialDimension); // buffers: // -------- //MultidimensionalArray Phi = new MultidimensionalArray(2); MultidimensionalArray GradPhi = new MultidimensionalArray(3); MultidimensionalArray HessPhi = new MultidimensionalArray(4); MultidimensionalArray ooNormGrad = new MultidimensionalArray(2); MultidimensionalArray Laplace = new MultidimensionalArray(2); MultidimensionalArray Q = new MultidimensionalArray(3); //Phi.Allocate(Len, K); GradPhi.Allocate(Len, K, D); HessPhi.Allocate(Len, K, D, D); ooNormGrad.Allocate(Len, K); Laplace.Allocate(Len, K); Q.Allocate(Len, K, D); // derivatives // ----------- // evaluate gradient this.EvaluateGradient(j0, Len, NodeSet, GradPhi); // evaluate Hessian this.EvaluateHessian(j0, Len, NodeSet, HessPhi); // compute the monstrous formula // ----------------------------- // norm of Gradient: for (int d = 0; d < D; d++) { var GradPhi_d = GradPhi.ExtractSubArrayShallow(-1, -1, d); ooNormGrad.Multiply(1.0, GradPhi_d, GradPhi_d, 1.0, "ik", "ik", "ik"); } ooNormGrad.ApplyAll(x => 1.0 / Math.Sqrt(x)); // laplacian of phi: for (int d = 0; d < D; d++) { var HessPhi_d_d = HessPhi.ExtractSubArrayShallow(-1, -1, d, d); Laplace.Acc(1.0, HessPhi_d_d); } // result = Laplacian(phi)/|Grad phi| result.Multiply(1.0, Laplace, ooNormGrad, 0.0, "ik", "ik", "ik"); // result += Grad(1/|Grad(phi)|) for (int d1 = 0; d1 < D; d1++) { var Qd = Q.ExtractSubArrayShallow(-1, -1, d1); for (int d2 = 0; d2 < D; d2++) { var Grad_d2 = GradPhi.ExtractSubArrayShallow(-1, -1, d2); var Hess_d2_d1 = HessPhi.ExtractSubArrayShallow(-1, -1, d2, d1); Qd.Multiply(-1.0, Grad_d2, Hess_d2_d1, 1.0, "ik", "ik", "ik"); } } ooNormGrad.ApplyAll(x => x * x * x); result.Multiply(1.0, GradPhi, Q, ooNormGrad, 1.0, "ik", "ikd", "ikd", "ik"); }
/// <summary> /// Computation of mean curvature according to Bonnet's formula. /// </summary> /// <param name="scale"></param> /// <param name="Output"> /// output. /// </param> /// <param name="quadScheme"></param> /// <param name="UseCenDiffUpTo"> /// Either 0, 1, or 2: /// If 0, all derivatives are computed locally (broken derivative); /// if 1, the first order derivatives are computed by central /// differences, while the second order ones are computed locally, /// based on the first order ones; /// if 2, all derivatives are computed by central differences. /// </param> /// <param name="_1stDerivDegree"> /// Relative DG polynomial degree for the 1st order derivatives, i.e. /// degree is <paramref name="_1stDerivDegree"/>+<em>p</em>, where /// <em>p</em> is the degree of this field. /// Only active if <paramref name="UseCenDiffUpTo"/> is greater than 0. /// </param> /// <param name="_2ndDerivDegree"> /// Relative DG polynomial degree for the 2nd order derivatives, i.e. /// degree is <paramref name="_2ndDerivDegree"/>+<em>p</em>, where /// <em>p</em> is the degree of this field. Only active if /// <paramref name="UseCenDiffUpTo"/> is greater than 1. /// </param> /// <remarks> /// using central differences causes memory allocation: <em>D</em> /// fields for <paramref name="UseCenDiffUpTo"/>=1, and /// <em>D</em>*(<em>D</em>+1) for <paramref name="UseCenDiffUpTo"/>=2, /// where <em>D</em> notates the spatial dimension. /// </remarks> public void ProjectTotalcurvature2( double scale, SinglePhaseField Output, int UseCenDiffUpTo, int _1stDerivDegree = 0, int _2ndDerivDegree = 0, CellQuadratureScheme quadScheme = null) { using (new FuncTrace()) { if (UseCenDiffUpTo < 0 || UseCenDiffUpTo > 2) { throw new ArgumentOutOfRangeException(); } //int M = Output.Basis.Length; //int N = this.Basis.Length; int D = this.GridDat.SpatialDimension; //var NSC = m_context.NSC; SubGrid sgrd = null; SpatialOperator.SubGridBoundaryModes bndMode = SpatialOperator.SubGridBoundaryModes.InnerEdge; if (UseCenDiffUpTo >= 1 && quadScheme != null && quadScheme.Domain != null) { sgrd = new SubGrid(quadScheme.Domain); bndMode = SpatialOperator.SubGridBoundaryModes.OpenBoundary; } // compute 1st order derivatives by central differences, if desired // ================================================================ Basis B2 = new Basis(this.GridDat, this.Basis.Degree + _1stDerivDegree); SinglePhaseField[] GradientVector = null; if (UseCenDiffUpTo >= 1) { GradientVector = new SinglePhaseField[D]; for (int d = 0; d < D; d++) { GradientVector[d] = new SinglePhaseField(B2); GradientVector[d].DerivativeByFlux(1.0, this, d, sgrd, bndMode); } } // compute 2nd order derivatives by central differences, if desired // =============================================================== Basis B3 = new Basis(this.GridDat, this.Basis.Degree + _2ndDerivDegree); SinglePhaseField[,] HessianTensor = null; if (UseCenDiffUpTo >= 2) { HessianTensor = new SinglePhaseField[D, D]; for (int d1 = 0; d1 < D; d1++) { for (int d2 = 0; d2 < D; d2++) { HessianTensor[d1, d2] = new SinglePhaseField(B3); HessianTensor[d1, d2].DerivativeByFlux(1.0, GradientVector[d1], d2, sgrd, bndMode); } } } // compute and project // =================== // buffers: MultidimensionalArray Phi = new MultidimensionalArray(2); MultidimensionalArray GradPhi = new MultidimensionalArray(3); MultidimensionalArray HessPhi = new MultidimensionalArray(4); MultidimensionalArray ooNormGrad = new MultidimensionalArray(2); MultidimensionalArray Laplace = new MultidimensionalArray(2); MultidimensionalArray Q = new MultidimensionalArray(3); // evaluate/project: //double Erracc = 0; Output.ProjectField(scale, (ScalarFunctionEx) delegate(int j0, int Len, NodeSet NodeSet, MultidimensionalArray result) { // ScalarFunction2 Debug.Assert(result.Dimension == 2); Debug.Assert(Len == result.GetLength(0)); int K = result.GetLength(1); // number of nodes // alloc buffers // ------------- if (Phi.GetLength(0) != Len || Phi.GetLength(1) != K) { Phi.Allocate(Len, K); GradPhi.Allocate(Len, K, D); HessPhi.Allocate(Len, K, D, D); ooNormGrad.Allocate(Len, K); Laplace.Allocate(Len, K); Q.Allocate(Len, K, D); } else { Phi.Clear(); GradPhi.Clear(); HessPhi.Clear(); ooNormGrad.Clear(); Laplace.Clear(); Q.Clear(); } // evaluate Gradient and Hessian // ----------------------------- if (UseCenDiffUpTo >= 1) { for (int d = 0; d < D; d++) { GradientVector[d].Evaluate(j0, Len, NodeSet, GradPhi.ExtractSubArrayShallow(-1, -1, d)); } } else { this.EvaluateGradient(j0, Len, NodeSet, GradPhi); } if (UseCenDiffUpTo == 2) { for (int d1 = 0; d1 < D; d1++) { for (int d2 = 0; d2 < D; d2++) { HessianTensor[d1, d2].Evaluate(j0, Len, NodeSet, HessPhi.ExtractSubArrayShallow(-1, -1, d1, d2)); } } } else if (UseCenDiffUpTo == 1) { for (int d = 0; d < D; d++) { var GradientVector_d = GradientVector[d]; GradientVector_d.EvaluateGradient(j0, Len, NodeSet, HessPhi.ExtractSubArrayShallow(-1, -1, d, -1), 0, 0.0); } } else if (UseCenDiffUpTo == 0) { this.EvaluateHessian(j0, Len, NodeSet, HessPhi); } else { Debug.Assert(false); } // compute the monstrous formula // ----------------------------- // norm of Gradient: for (int d = 0; d < D; d++) { var GradPhi_d = GradPhi.ExtractSubArrayShallow(-1, -1, d); ooNormGrad.Multiply(1.0, GradPhi_d, GradPhi_d, 1.0, "ik", "ik", "ik"); } ooNormGrad.ApplyAll(x => 1.0 / Math.Sqrt(x)); // laplacian of phi: for (int d = 0; d < D; d++) { var HessPhi_d_d = HessPhi.ExtractSubArrayShallow(-1, -1, d, d); Laplace.Acc(1.0, HessPhi_d_d); } // result = Laplacian(phi)/|Grad phi| result.Multiply(1.0, Laplace, ooNormGrad, 0.0, "ik", "ik", "ik"); // result = Grad(1/|Grad(phi)|) for (int d1 = 0; d1 < D; d1++) { var Qd = Q.ExtractSubArrayShallow(-1, -1, d1); for (int d2 = 0; d2 < D; d2++) { var Grad_d2 = GradPhi.ExtractSubArrayShallow(-1, -1, d2); var Hess_d2_d1 = HessPhi.ExtractSubArrayShallow(-1, -1, d2, d1); Qd.Multiply(-1.0, Grad_d2, Hess_d2_d1, 1.0, "ik", "ik", "ik"); } } ooNormGrad.ApplyAll(x => x * x * x); result.Multiply(1.0, GradPhi, Q, ooNormGrad, 1.0, "ik", "ikd", "ikd", "ik"); //for (int i = 0; i < Len; i++) { // for (int k = 0; k < K; k++) { // double acc = 0; // for (int d = 0; d < D; d++) { // acc += GradPhi[i,k,d]*Q[i,k,d]*ooNormGrad[i,k]; // } // Erracc += (acc - result[i,k]).Abs(); // } //} }, quadScheme.SaveCompile(this.GridDat, (Output.Basis.Degree + this.m_Basis.Degree * (this.m_Basis.Degree - 1) * D) * 2) ); } }
/// <summary> /// /// </summary> /// <param name="dt"></param> /// <param name="velocity"></param> /// <returns></returns> public override double[] ComputeChangerate(double dt, ConventionalDGField[] velocity, double[] current_FLSprop) { GridData grdat = (GridData)velocity[0].GridDat; FieldEvaluation fEval = new FieldEvaluation(grdat); MultidimensionalArray VelocityAtSamplePoints = MultidimensionalArray.Create(current_interfaceP.Lengths); int outP = fEval.Evaluate(1, velocity, current_interfaceP, 0, VelocityAtSamplePoints); if (outP != 0) { throw new Exception("points outside the grid for fieldevaluation"); } // change rate for the material points is the velocity at the points if (FourierEvolve == Fourier_Evolution.MaterialPoints) { double[] velAtP = new double[2 * numFp]; for (int sp = 0; sp < numFp; sp++) { velAtP[sp * 2] = VelocityAtSamplePoints[sp, 0]; velAtP[sp * 2 + 1] = VelocityAtSamplePoints[sp, 1]; } return(velAtP); } // compute an infinitesimal change of sample points at the Fourier points/ change of Fourier modes MultidimensionalArray interfaceP_evo = current_interfaceP.CloneAs(); double dt_infin = dt * 1e-3; interfaceP_evo.Acc(dt_infin, VelocityAtSamplePoints); RearrangeOntoPeriodicDomain(interfaceP_evo); double[] samplP_change = current_samplP.CloneAs(); InterpolateOntoFourierPoints(interfaceP_evo, samplP_change); if (FourierEvolve == Fourier_Evolution.FourierPoints) { samplP_change.AccV(-1.0, current_samplP); samplP_change.ScaleV(1.0 / dt_infin); return(samplP_change); } else if (FourierEvolve == Fourier_Evolution.FourierModes) { Complex[] samplP_complex = new Complex[numFp]; for (int sp = 0; sp < numFp; sp++) { samplP_complex[sp] = (Complex)samplP_change[sp]; } //Complex[] DFT_change = DFT.NaiveForward(samplP_complex, FourierOptions.Matlab); Complex[] DFT_change = samplP_complex; samplP_complex = null; Fourier.Forward(DFT_change, FourierOptions.Matlab); double[] DFT_change_double = new double[2 * numFp]; for (int sp = 0; sp < numFp; sp++) { DFT_change_double[sp * 2] = (DFT_change[sp].Real - DFT_coeff[sp].Real) / dt_infin; DFT_change_double[sp * 2 + 1] = (DFT_change[sp].Imaginary - DFT_coeff[sp].Imaginary) / dt_infin; } return(DFT_change_double); } else { throw new ArgumentException(); } }
/// <summary> /// Compares the cell surface and the boundary integral. /// </summary> public static void TestSealing(IGridData gdat) { int J = gdat.iLogicalCells.NoOfLocalUpdatedCells; int[,] E2Clog = gdat.iGeomEdges.LogicalCellIndices; // // compute cell surface via edge integrals // MultidimensionalArray CellSurf1 = MultidimensionalArray.Create(J); EdgeQuadrature.GetQuadrature(new int[] { 1 }, gdat, new EdgeQuadratureScheme().Compile(gdat, 2), delegate(int i0, int Length, QuadRule rule, MultidimensionalArray EvalResult) { // evaluate EvalResult.SetAll(1.0); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // save results for (int i = 0; i < Length; i++) { int iEdge = i + i0; int jCellIn = E2Clog[iEdge, 0]; int jCellOt = E2Clog[iEdge, 1]; CellSurf1[jCellIn] += ResultsOfIntegration[i, 0]; if (jCellOt >= 0 && jCellOt < J) { CellSurf1[jCellOt] += ResultsOfIntegration[i, 0]; } } }).Execute(); // // compute cell surface via cell boundary integrals // var cbqs = new CellBoundaryQuadratureScheme(false, null); foreach (var Kref in gdat.iGeomCells.RefElements) { cbqs.AddFactory(new StandardCellBoundaryQuadRuleFactory(Kref)); } MultidimensionalArray CellSurf2 = MultidimensionalArray.Create(J); CellBoundaryQuadrature <CellBoundaryQuadRule> .GetQuadrature(new int[] { 1 }, gdat, cbqs.Compile(gdat, 2), delegate(int i0, int Length, CellBoundaryQuadRule rule, MultidimensionalArray EvalResult) { // evaluate EvalResult.SetAll(1.0); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { // save results int NoOfFaces = ResultsOfIntegration.GetLength(1); for (int i = 0; i < Length; i++) { int jCell = i + i0; for (int iFace = 0; iFace < NoOfFaces; iFace++) { CellSurf2[jCell] += ResultsOfIntegration[i, iFace, 0]; } } }, cs : CoordinateSystem.Physical).Execute(); // // compare // MultidimensionalArray Err = CellSurf1.CloneAs(); Err.Acc(-1.0, CellSurf2); double ErrNorm = Err.L2Norm(); double TotSurf = CellSurf1.L2Norm(); Console.WriteLine("Area Check " + Err.L2Norm()); Assert.LessOrEqual(ErrNorm / TotSurf, 1.0e-8); //for (int j = 0; j < J; j++) { // if (Err[j].Abs() >= 1.0e-6) { // Console.WriteLine("Mismatch between edge area and cell surface area in cell {0}, GlobalId {1}, No. of neighbors {3}, {2:0.####E-00}", j, gdat.CurrentGlobalIdPermutation.Values[j], Err[j], gdat.Cells.CellNeighbours[j].Length); // schas.SetMeanValue(j, 1); // } //} }
/// <summary> /// /// </summary> /// <param name="velocity"></param> /// <returns></returns> public override double[] ComputeChangerate(double dt, ConventionalDGField[] velocity, double[] current_FLSprop) { setMaterialInterfacePoints(current_FLSprop); GridData grdat = (GridData)(velocity[0].GridDat); FieldEvaluation fEval = new FieldEvaluation(grdat); // Movement of the material interface points MultidimensionalArray VelocityAtSamplePointsXY = MultidimensionalArray.Create(current_interfaceP.Lengths); int outP = fEval.Evaluate(1, velocity, current_interfaceP, 0, VelocityAtSamplePointsXY); if (outP != 0) { throw new Exception("points outside the grid for fieldevaluation"); } int numIp = current_interfaceP.Lengths[0]; // change rate for the material points is the velocity at the points if (FourierEvolve == Fourier_Evolution.MaterialPoints) { double[] velAtP = new double[2 * numIp]; for (int sp = 0; sp < numIp; sp++) { velAtP[sp * 2] = VelocityAtSamplePointsXY[sp, 0]; velAtP[(sp * 2) + 1] = VelocityAtSamplePointsXY[sp, 1]; } return(velAtP); } // compute an infinitesimal change of sample points at the Fourier points/ change of Fourier modes MultidimensionalArray interfaceP_evo = current_interfaceP.CloneAs(); double dt_infin = dt * 1e-3; interfaceP_evo.Acc(dt_infin, VelocityAtSamplePointsXY); // Movement of the center point MultidimensionalArray center_evo = center.CloneAs(); MultidimensionalArray VelocityAtCenter = center.CloneAs(); switch (CenterMove) { case CenterMovement.None: { VelocityAtCenter.Clear(); break; } case CenterMovement.Reconstructed: { center_evo = GetGeometricCenter(interfaceP_evo); //Console.WriteLine("center_evo = ({0}, {1}) / center = ({2}, {3})", center_evo[0, 0], center_evo[0, 1], center[0, 0], center[0, 1]); MultidimensionalArray center_change = center_evo.CloneAs(); center_change.Acc(-1.0, center); center_change.Scale(1.0 / dt_infin); VelocityAtCenter[0, 0] = center_change[0, 0]; VelocityAtCenter[0, 1] = center_change[0, 1]; break; } case CenterMovement.VelocityAtCenter: { outP = fEval.Evaluate(1, velocity, center, 0, VelocityAtCenter); if (outP != 0) { throw new Exception("center point outside the grid for fieldevaluation"); } center_evo.Acc(dt_infin, VelocityAtCenter); break; } } //Console.WriteLine("Velocity at Center point = ({0}, {1})", VelocityAtCenter[0, 0], VelocityAtCenter[0, 1]); // transform to polar coordiantes MultidimensionalArray interP_evo_polar = interfaceP_polar.CloneAs(); for (int sp = 0; sp < numIp; sp++) { double x_c = interfaceP_evo[sp, 0] - center_evo[0, 0]; double y_c = interfaceP_evo[sp, 1] - center_evo[0, 1]; double theta = Math.Atan2(y_c, x_c); if (theta < 0) { theta = Math.PI * 2 + theta; } ; interP_evo_polar[sp, 0] = theta; interP_evo_polar[sp, 1] = Math.Sqrt(x_c.Pow2() + y_c.Pow2()); } RearrangeOntoPeriodicDomain(interP_evo_polar); double[] samplP_change = current_samplP.CloneAs(); InterpolateOntoFourierPoints(interP_evo_polar, samplP_change); if (FourierEvolve == Fourier_Evolution.FourierPoints) { samplP_change.AccV(-1.0, current_samplP); samplP_change.ScaleV(1.0 / dt_infin); double[] FPchange = new double[numFp + 2]; FPchange[0] = VelocityAtCenter[0, 0]; FPchange[1] = VelocityAtCenter[0, 1]; for (int p = 0; p < numFp; p++) { FPchange[p + 2] = samplP_change[p]; } return(FPchange); } else if (FourierEvolve == Fourier_Evolution.FourierModes) { Complex[] samplP_complex = new Complex[numFp]; for (int sp = 0; sp < numFp; sp++) { samplP_complex[sp] = (Complex)samplP_change[sp]; } //Complex[] DFTchange = DFT.NaiveForward(samplP_complex, FourierOptions.Matlab); Complex[] DFTchange = samplP_complex; samplP_complex = null; Fourier.Forward(DFTchange, FourierOptions.Matlab); double[] DFTchange_double = new double[2 * numFp + 2]; DFTchange_double[0] = VelocityAtCenter[0, 0]; DFTchange_double[1] = VelocityAtCenter[0, 1]; for (int sp = 0; sp < numFp; sp++) { DFTchange_double[2 + (sp * 2)] = (DFTchange[sp].Real - DFT_coeff[sp].Real) / dt_infin; DFTchange_double[2 + (sp * 2) + 1] = (DFTchange[sp].Imaginary - DFT_coeff[sp].Imaginary) / dt_infin; } return(DFTchange_double); } else { throw new ArgumentException(); } }
/// <summary> /// % /// </summary> /// <param name="output"></param> /// <param name="input">input DG field; unchanged on </param> public void Perform(SinglePhaseField output, SinglePhaseField input) { if (!output.Basis.Equals(this.m_bOutput)) { throw new ArgumentException("output basis mismatch"); } if (!input.Basis.Equals(this.m_bInput)) { throw new ArgumentException("output basis mismatch"); } var GridDat = this.m_bOutput.GridDat; int N = m_bOutput.Length; int Nin = m_bInput.Length; int J = GridDat.iLogicalCells.NoOfLocalUpdatedCells; diagnosis = new double[N * J]; double[] RHS = new double[N]; double[] f2 = new double[N]; double[] g1 = new double[N]; MultidimensionalArray Trf = MultidimensionalArray.Create(N, N); input.MPIExchange(); for (int jCell = 0; jCell < J; jCell++) { Debug.Assert((this.AggregateBasisTrafo[jCell] != null) == (this.Stencils[jCell] != null)); //FullMatrix invMassM = this.InvMassMatrix[jCell]; MultidimensionalArray ExPolMtx = this.AggregateBasisTrafo[jCell]; if (ExPolMtx != null) { int[] Stencil_jCells = this.Stencils[jCell]; int K = Stencil_jCells.Length; Debug.Assert(Stencil_jCells[0] == jCell); var coordIn = input.Coordinates; //for(int n = Math.Min(Nin, N) - 1; n >= 0; n--) { // RHS[n] = coordIn[jCell, n]; //} RHS.ClearEntries(); g1.ClearEntries(); var oldCoords = input.Coordinates.GetRow(jCell); for (int k = 0; k < K; k++) { int jNeigh = Stencil_jCells[k]; for (int n = Math.Min(input.Basis.Length, N) - 1; n >= 0; n--) { f2[n] = input.Coordinates[jNeigh, n]; } if (Nlim != null && Nlim[jNeigh] > 0) { for (int n = Nlim[jNeigh]; n < RHS.Length; n++) { f2[n] = 0; } } for (int l = 0; l < N; l++) { double acc = 0; for (int i = 0; i < N; i++) { acc += ExPolMtx[k, i, l] * f2[i]; } RHS[l] += acc; } } if (Nlim != null && Nlim[jCell] > 0) { for (int n = Nlim[jCell]; n < RHS.Length; n++) { RHS[n] = 0; } } for (int l = 0; l < N; l++) { diagnosis[jCell * N + l] = RHS[l]; } //invMassM.gemv(1.0, RHS, 0.0, g1); Trf.Clear(); Trf.Acc(1.0, ExPolMtx.ExtractSubArrayShallow(0, -1, -1)); //Trf.Solve(FulCoords, AggCoords); Trf.gemv(1.0, RHS, 0.0, g1); if (Nlim != null && Nlim[jCell] > 0) { for (int n = Nlim[jCell]; n < RHS.Length; n++) { g1[n] = 0; } } if (Nlim == null) { output.Coordinates.SetRow(jCell, g1); } else { if ((Nlim[jCell] <= 0 && this.notchangeunlim)) { output.Coordinates.SetRow(jCell, oldCoords); } else { output.Coordinates.SetRow(jCell, g1); } } } } output.MPIExchange(); }
/// <summary> /// /// </summary> /// <param name="CellPairs"> /// 1st index: list of cells <br/> /// 2nd index: in {0, 1} /// </param> /// <param name="M"> /// 1st index: corresponds with 1st index of <paramref name="CellPairs"/><br/> /// 2nd index: matrix row index <br/> /// 3rd index: matrix column index /// </param> /// <param name="Minv">the inverse of <paramref name="M"/></param> /// <remarks> /// Let \f$ K_j \f$ and \f$ K_i \f$ be two different cells with a linear-affine /// transformation to the reference element. /// Here, \f$ j \f$=<paramref name="CellPairs"/>[a,0] and \f$ i \f$=<paramref name="CellPairs"/>[a,1]. /// The DG-basis in these cells can uniquely be represented as /// \f[ /// \phi_{j n} (\vec{x}) = p_n (\vec{x}) \vec{1}_{K_j} (\vec{x}) /// \textrm{ and } /// \phi_{i m} (\vec{x}) = q_m (\vec{x}) \vec{1}_{K_i} (\vec{x}) /// \f] /// where \f$ \vec{1}_X \f$ denotes the characteristic function for set \f$ X \f$ /// and \f$ p_n\f$ and \f$ p_m\f$ are polynomials. /// Then, for the output \f$ M \f$ =<paramref name="M"/>[a,-,-] fulfills /// \f[ /// \phi_{j n} + \sum_{m} M_{m n} \phi_{i m} /// = /// p_n \vec{1}_{K_j \cup K_i} /// \f] /// </remarks> public void GetExtrapolationMatrices(int[,] CellPairs, MultidimensionalArray M, MultidimensionalArray Minv = null) { var m_Context = this.GridDat; int N = this.Length; int Esub = CellPairs.GetLength(0); int JE = this.GridDat.iLogicalCells.Count; int J = this.GridDat.iLogicalCells.NoOfLocalUpdatedCells; if (CellPairs.GetLength(1) != 2) { throw new ArgumentOutOfRangeException("second dimension is expected to be 2!"); } if (M.Dimension != 3) { throw new ArgumentException(); } if (M.GetLength(0) != Esub) { throw new ArgumentException(); } if (M.GetLength(1) != N || M.GetLength(2) != N) { throw new ArgumentException(); } if (Minv != null) { if (Minv.GetLength(0) != Esub) { throw new ArgumentException(); } if (Minv.GetLength(1) != N || Minv.GetLength(2) != N) { throw new ArgumentException(); } } MultidimensionalArray NodesGlobal = new MultidimensionalArray(3); MultidimensionalArray Minv_tmp = MultidimensionalArray.Create(N, N); MultidimensionalArray M_tmp = MultidimensionalArray.Create(N, N); for (int esub = 0; esub < Esub; esub++) // loop over the cell pairs... { int jCell0 = CellPairs[esub, 0]; int jCell1 = CellPairs[esub, 1]; if (jCell0 < 0 || jCell0 >= JE) { throw new ArgumentOutOfRangeException("Cell index out of range."); } if (jCell1 < 0 || jCell1 >= JE) { throw new ArgumentOutOfRangeException("Cell index out of range."); } bool swap; if (jCell0 >= J) { //if(true) { swap = true; int a = jCell0; jCell0 = jCell1; jCell1 = a; } else { swap = false; } if (!m_Context.iGeomCells.IsCellAffineLinear(jCell0)) { throw new NotSupportedException("Currently not supported for curved cells."); } if (!m_Context.iGeomCells.IsCellAffineLinear(jCell1)) { throw new NotSupportedException("Currently not supported for curved cells."); } Debug.Assert(jCell0 < J); var cellMask = new CellMask(m_Context, new[] { new Chunk() { i0 = jCell0, Len = 1 } }, MaskType.Geometrical); // we project the basis function from 'jCell1' onto 'jCell0' CellQuadrature.GetQuadrature(new int[2] { N, N }, m_Context, (new CellQuadratureScheme(true, cellMask)).Compile(m_Context, this.Degree * 2), // integrate over target cell delegate(int i0, int Length, QuadRule QR, MultidimensionalArray _EvalResult) { NodeSet nodes_Cell0 = QR.Nodes; Debug.Assert(Length == 1); NodesGlobal.Allocate(1, nodes_Cell0.GetLength(0), nodes_Cell0.GetLength(1)); m_Context.TransformLocal2Global(nodes_Cell0, jCell0, 1, NodesGlobal, 0); var nodes_Cell1 = new NodeSet(GridDat.iGeomCells.GetRefElement(jCell1), nodes_Cell0.GetLength(0), nodes_Cell0.GetLength(1)); m_Context.TransformGlobal2Local(NodesGlobal.ExtractSubArrayShallow(0, -1, -1), nodes_Cell1, jCell1, null); nodes_Cell1.LockForever(); var phi_0 = this.CellEval(nodes_Cell0, jCell0, 1).ExtractSubArrayShallow(0, -1, -1); var phi_1 = this.CellEval(nodes_Cell1, jCell1, 1).ExtractSubArrayShallow(0, -1, -1); var EvalResult = _EvalResult.ExtractSubArrayShallow(0, -1, -1, -1); EvalResult.Multiply(1.0, phi_1, phi_0, 0.0, "kmn", "kn", "km"); }, /*_SaveIntegrationResults:*/ delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { Debug.Assert(Length == 1); var res = ResultsOfIntegration.ExtractSubArrayShallow(0, -1, -1); Minv_tmp.Clear(); Minv_tmp.Acc(1.0, res); }).Execute(); // compute the inverse Minv_tmp.InvertTo(M_tmp); // store if (!swap) { M.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, M_tmp); if (Minv != null) { Minv.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, Minv_tmp); } } else { M.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, Minv_tmp); if (Minv != null) { Minv.ExtractSubArrayShallow(esub, -1, -1).AccMatrix(1.0, M_tmp); } } } }
static private void EvalComponent <T>(LevSetIntParams _inParams, int gamma, EquationComponentArgMapping <T> bf, MultidimensionalArray[][] argsPerComp, MultidimensionalArray[,] argsSum, int componentIdx, MultidimensionalArray ParamFieldValuesPos, MultidimensionalArray ParamFieldValuesNeg, int DELTA, Stopwatch timer, IDictionary <SpeciesId, MultidimensionalArray> LengthScales, CallComponent <T> ComponentFunc) where T : ILevelSetComponent { timer.Start(); for (int i = 0; i < bf.m_AllComponentsOfMyType.Length; i++) // loop over equation components { var comp = bf.m_AllComponentsOfMyType[i]; LengthScales.TryGetValue(comp.NegativeSpecies, out _inParams.NegCellLengthScale); LengthScales.TryGetValue(comp.PositiveSpecies, out _inParams.PosCellLengthScale); argsPerComp[gamma][i].Clear(); int NoOfArgs = bf.NoOfArguments[i]; Debug.Assert(NoOfArgs == comp.ArgumentOrdering.Count); int NoOfParams = bf.NoOfParameters[i]; Debug.Assert(NoOfParams == ((comp.ParameterOrdering != null) ? comp.ParameterOrdering.Count : 0)); // map parameters _inParams.ParamsPos = new MultidimensionalArray[NoOfParams]; _inParams.ParamsNeg = new MultidimensionalArray[NoOfParams]; for (int c = 0; c < NoOfParams; c++) { int targ = bf.AllToSub[i, c + NoOfArgs] - DELTA; Debug.Assert(targ >= 0); _inParams.ParamsPos[c] = ParamFieldValuesPos.ExtractSubArrayShallow(targ, -1, -1); _inParams.ParamsNeg[c] = ParamFieldValuesNeg.ExtractSubArrayShallow(targ, -1, -1); } // evaluate equation components ComponentFunc(comp, gamma, i, _inParams); #if DEBUG argsPerComp[gamma][i].CheckForNanOrInf(); #endif // sum up bilinear forms: { MultidimensionalArray Summand = argsPerComp[gamma][i]; if (componentIdx >= 0) { for (int c = 0; c < NoOfArgs; c++) // loop over arguments of equation component { int targ = bf.AllToSub[i, c]; int[] selSum = new int[Summand.Dimension]; selSum.SetAll(-1); selSum[componentIdx] = c; MultidimensionalArray Accu = argsSum[gamma, targ]; //int[] selAccu = new int[Accu.Dimension]; //selAccu.SetAll(-1); //selAccu[componentIdx] = targ; #if DEBUG Summand.ExtractSubArrayShallow(selSum).CheckForNanOrInf(); #endif Accu.Acc(1.0, Summand.ExtractSubArrayShallow(selSum)); } } else { // affin #if DEBUG Summand.CheckForNanOrInf(); #endif MultidimensionalArray Accu = argsSum[gamma, 0]; Accu.Acc(1.0, Summand); } } } timer.Stop(); }
static internal void InvertMassMatrixBlocks( out Dictionary <SpeciesId, MassMatrixBlockContainer> MassMatrixBlocksInv, Dictionary <SpeciesId, MassMatrixBlockContainer> MassMatrixBlocks, int N) { using (new FuncTrace()) { MassMatrixBlocksInv = new Dictionary <SpeciesId, MassMatrixBlockContainer>(); foreach (var Species in MassMatrixBlocks.Keys) { var mblk = MassMatrixBlocks[Species].MassMatrixBlocks; //var mblkB4agg = MassMatrixBlocks[Species].MassMatrixBlocks_B4Agglom; var invmblk = MultidimensionalArray.Create(mblk.GetLength(0), N, N); MassMatrixBlocksInv.Add(Species, new MassMatrixBlockContainer() { MassMatrixBlocks = invmblk, //jCell2jSub = MassMatrixBlocks[Species].jCell2jSub, jSub2jCell = MassMatrixBlocks[Species].jSub2jCell, IntegrationDomain = MassMatrixBlocks[Species].IntegrationDomain }); int B = mblk.GetLength(0); Debug.Assert(mblk.GetLength(2) >= N); MultidimensionalArray blk = MultidimensionalArray.Create(N, N); MultidimensionalArray inv_Blk = MultidimensionalArray.Create(N, N); // loop over all cut cells (mass matrix blocks)... for (int b = 0; b < B; b++) { MultidimensionalArray _blk; //if ((aggSw == true) || (mblkB4agg[b] == null)) { _blk = mblk.ExtractSubArrayShallow(new int[] { b, 0, 0 }, new int[] { b - 1, N - 1, N - 1 }); //} else { // Debug.Assert(aggSw == false); // Debug.Assert(mblkB4agg[b] != null); // _blk = mblkB4agg[b].ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { N - 1, N - 1 }); //} blk.Set(_blk); if (blk.ContainsNanOrInf(true, true)) { throw new ArithmeticException("NAN/INF in mass matrix."); } if (blk.InfNorm() == 0.0) { // a zero-block invmblk.ExtractSubArrayShallow(b, -1, -1).Clear(); } else { //blk.Invert(inv_Blk); try { inv_Blk.Clear(); inv_Blk.Acc(1.0, blk); inv_Blk.InvertSymmetrical(); #if DEBUG for (int n = 0; n < N; n++) { for (int m = 0; m < N; m++) { Debug.Assert(inv_Blk[n, m] == inv_Blk[m, n]); } } #endif } catch (ArithmeticException) { Console.WriteLine("WARNING: indefinite mass matrix."); blk.InvertTo(inv_Blk); #if DEBUG for (int n = 0; n < N; n++) { for (int m = 0; m < N; m++) { Debug.Assert(Math.Abs(inv_Blk[n, m] - inv_Blk[m, n]) / (Math.Abs(inv_Blk[n, m]) + Math.Abs(inv_Blk[m, n])) <= 1.0e-9); } } #endif } if (blk.ContainsNanOrInf(true, true)) { throw new ArithmeticException("NAN/INF in inverse mass matrix."); } invmblk.SetSubMatrix(inv_Blk, b, -1, -1); } /* * bool Choleski_failed = false; * bool Symmelim_failed = false; * try { * blk.Initialize(_blk); * blk.InvertSymmetrical(); * } catch (ArithmeticException) { * Choleski_failed = true; * } * try { * blk.Initialize(_blk); * FullMatrix.TiredRoutine(blk); * } catch (ArithmeticException) { * Symmelim_failed = true; * } * * if (Choleski_failed || Symmelim_failed) { * Console.WriteLine("Mass matrix defect ({0},{1}): species {2}, jsub = {3};", Choleski_failed, Symmelim_failed, LsTrk.GetSpeciesName(Species), b); * * int J = LsTrk.Ctx.Grid.NoOfUpdateCells; * if (MassErrors == null) { * MassErrors = new Dictionary<SpeciesId, System.Collections.BitArray>(); * } * if (!MassErrors.ContainsKey(Species)) { * MassErrors.Add(Species, new System.Collections.BitArray(J)); * } * var _MassErrors = MassErrors[Species]; * * int[] globalIdx = cutted.SubgridIndex2LocalCellIndex; * int jCell = globalIdx[b]; * * _MassErrors[jCell] = true; * * } * //*/ } } } }
private DoubleEdgeQuadRule CombineQr(DoubleEdgeQuadRule qrEdge, CellBoundaryQuadRule givenRule, int iFace, int jCell) { int D = grd.SpatialDimension; var volSplx = m_cellBndQF.Simplex; int coD = grd.Grid.GridSimplex.EdgeSimplex.SpatialDimension; // extract edge rule // ----------------- int i0 = 0, iE = 0; for (int i = 0; i < iFace; i++) { i0 += givenRule.NumbersOfNodesPerEdge[i]; } iE = i0 + givenRule.NumbersOfNodesPerEdge[iFace] - 1; if (iE < i0) { // rule is empty (measure is zero). if (qrEdge == null) { DoubleEdgeQuadRule ret = new DoubleEdgeQuadRule(); ret.OrderOfPrecision = int.MaxValue - 1; ret.Nodes = MultidimensionalArray.Create(1, Math.Max(1, D - 1)); ret.Weights = MultidimensionalArray.Create(1); // this is an empty rule, since the weight is zero! ret.Median = 1; // (rules with zero nodes may cause problems at various places.) return(ret); } else { Debug.Assert(qrEdge.Median == qrEdge.NoOfNodes); return(qrEdge); } } MultidimensionalArray NodesVol = givenRule.Nodes.ExtractSubArrayShallow(new int[] { i0, 0 }, new int[] { iE, D - 1 }); MultidimensionalArray Weigts = givenRule.Weights.ExtractSubArrayShallow(new int[] { i0 }, new int[] { iE }).CloneAs(); MultidimensionalArray Nodes = MultidimensionalArray.Create(iE - i0 + 1, coD); volSplx.VolumeToEdgeCoordinates(iFace, NodesVol, Nodes); //Debug.Assert((Weigts.Sum() - grd.Grid.GridSimplex.EdgeSimplex.Volume).Abs() < 1.0e-6, "i've forgotten the gramian"); // combine // ------- if (qrEdge == null) { // no rule defined yet - just set the one we have got // ++++++++++++++++++++++++++++++++++++++++++++++++++ qrEdge = new DoubleEdgeQuadRule(); qrEdge.Weights = Weigts; qrEdge.Nodes = Nodes; qrEdge.Median = qrEdge.NoOfNodes; qrEdge.OrderOfPrecision = givenRule.OrderOfPrecision; } else { // take the mean of already defined and new rule // +++++++++++++++++++++++++++++++++++++++++++++ int L1 = qrEdge.Nodes.GetLength(0); int L2 = Nodes.GetLength(0); Debug.Assert(coD == qrEdge.Nodes.GetLength(1)); MultidimensionalArray newNodes = MultidimensionalArray.Create(L1 + L2, coD); newNodes.Set(qrEdge.Nodes, new int[] { 0, 0 }, new int[] { L1 - 1, coD - 1 }); newNodes.Set(Nodes, new int[] { L1, 0 }, new int[] { L1 + L2 - 1, coD - 1 }); MultidimensionalArray newWeights = MultidimensionalArray.Create(L1 + L2); newWeights.Acc(1.0, qrEdge.Weights, new int[] { 0 }, new int[] { L1 - 1 }); newWeights.Acc(1.0, Weigts, new int[] { L1 }, new int[] { L1 + L2 - 1 }); double oldSum = qrEdge.Weights.Sum(); double newSum = Weigts.Sum(); WeightInbalance += Math.Abs(oldSum - newSum); qrEdge.Nodes = newNodes; qrEdge.Weights = newWeights; qrEdge.Median = L1; qrEdge.OrderOfPrecision = Math.Min(qrEdge.OrderOfPrecision, givenRule.OrderOfPrecision); } // return // ------ return(qrEdge); }