/// <summary> /// extract the Fields from the solution, Resample them equally spaced and ready to use in an fft /// </summary> private void Resample(int iterIndex, double[] currentSol, MultigridOperator Mgop, string component) { if (Mgop.GridData.SpatialDimension == 2 && Mgop.LevelIndex == 0) { MultidimensionalArray SamplePoints; GridData GD = (GridData)Mgop.Mapping.AggGrid.AncestorGrid; BoundingBox BB = GD.GlobalBoundingBox; double xDist = BB.Max[0] - BB.Min[0]; double yDist = BB.Max[1] - BB.Min[1]; double aspectRatio = xDist / yDist; MGViz viz = new MGViz(Mgop); DGField[] Fields = viz.ProlongateToDg(currentSol, "Error"); for (int p = 0; p < Fields.Length; p++) { var field = Fields[p]; int DOF = field.DOFLocal; double N = Math.Sqrt(DOF); int Nx = (int)Math.Round(Math.Sqrt(aspectRatio) * N); int Ny = (int)Math.Round(1 / Math.Sqrt(aspectRatio) * N); SamplePoints = MultidimensionalArray.Create(Ny, Nx); for (int i = 0; i < Nx; i++) { MultidimensionalArray points = MultidimensionalArray.Create(Ny, 2); for (int k = 0; k < Ny; k++) { points[k, 0] = BB.Min[0] + (i + 1) * xDist / (Nx + 1); points[k, 1] = BB.Min[1] + (k + 1) * yDist / (Ny + 1); } List <DGField> fields = new List <DGField>(); fields.Add(field); FieldEvaluation FE = new FieldEvaluation(GD); MultidimensionalArray Result = MultidimensionalArray.Create(Ny, 1); FE.Evaluate(1.0, fields, points, 1.0, Result); SamplePoints.ExtractSubArrayShallow(-1, i).Acc(1.0, Result.ExtractSubArrayShallow(-1, 0)); } SamplePoints.SaveToTextFile("ResampleFFT_lvl" + Mgop.LevelIndex + "_" + iterIndex + "_" + component + "_" + field.Identification + ".txt"); } } }
/// <summary> /// computes the L2-error of the interface points onto the LevelSet-DGfield /// </summary> /// <param name="LevelSet"></param> /// <param name="interP"></param> public double InterfaceProjectionError(SinglePhaseField LevelSet, MultidimensionalArray interP) { GridData grdat = (GridData)LevelSet.GridDat; FieldEvaluation fEval = new FieldEvaluation(grdat); MultidimensionalArray PhiAtSamplePoints = MultidimensionalArray.Create(interP.Lengths[0], 1); DGField[] DGLevSet = new DGField[] { LevelSet }; int outP = fEval.Evaluate(1, DGLevSet, interP, 0, PhiAtSamplePoints); if (outP != 0) { throw new Exception("points outside the grid for fieldevaluation"); } return(PhiAtSamplePoints.L2Norm()); }
/// <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> /// /// </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> /// Reconstructs a <see cref="BoSSS.Foundation.XDG.LevelSet"/> from a given set of points on a given DG field /// </summary> /// <param name="field">The DG field to work with</param> /// <param name="points"> <see cref="MultidimensionalArray"/> /// Lengths --> [0]: numOfPoints, [1]: 2 /// [1] --> [0]: x, [1]: y /// </param> public static SinglePhaseField ReconstructLevelSetField(SinglePhaseField field, MultidimensionalArray points) { // Init IGridData gridData = field.GridDat; // Evaluate gradient SinglePhaseField gradientX = new SinglePhaseField(field.Basis, "gradientX"); SinglePhaseField gradientY = new SinglePhaseField(field.Basis, "gradientY"); gradientX.DerivativeByFlux(1.0, field, d: 0); gradientY.DerivativeByFlux(1.0, field, d: 1); //gradientX = PatchRecovery(gradientX); //gradientY = PatchRecovery(gradientY); FieldEvaluation ev = new FieldEvaluation((GridData)gridData); MultidimensionalArray GradVals = MultidimensionalArray.Create(points.GetLength(0), 2); ev.Evaluate(1.0, new DGField[] { gradientX, gradientY }, points, 0.0, GradVals); // Level set reconstruction Console.WriteLine("Reconstruction of field levelSet started..."); int count = 0; Func <double[], double> func = delegate(double[] X) { double minDistSigned = double.MaxValue; int iMin = int.MaxValue; double closestPointOnInterfaceX = double.MaxValue; double closestPointOnInterfaceY = double.MaxValue; double x = X[0]; double y = X[1]; for (int i = 0; i < points.Lengths[0]; i++) { double currentPointX = points[i, 0]; double currentPointY = points[i, 1]; double deltaX = x - currentPointX; double deltaY = y - currentPointY; double dist = Math.Sqrt(deltaX * deltaX + deltaY * deltaY); if (dist <= minDistSigned) { iMin = i; minDistSigned = dist; closestPointOnInterfaceX = currentPointX; closestPointOnInterfaceY = currentPointY; } } //// Compute global cell index of quadrature node //gridData.LocatePoint(X, out long GlobalId, out long GlobalIndex, out bool IsInside, out bool OnThisProcess); //// Compute local node set //NodeSet nodeSet = GetLocalNodeSet(gridData, X, (int)GlobalIndex); //// Evaluate gradient //// Get local cell index of quadrature node //int j0Grd = gridData.CellPartitioning.i0; //int j0 = (int)(GlobalIndex - j0Grd); //int Len = 1; //MultidimensionalArray resultGradX = MultidimensionalArray.Create(1, 1); //MultidimensionalArray resultGradY = MultidimensionalArray.Create(1, 1); //gradientX.Evaluate(j0, Len, nodeSet, resultGradX); //gradientY.Evaluate(j0, Len, nodeSet, resultGradY); int sign = Math.Sign((x - closestPointOnInterfaceX) * GradVals[iMin, 0] + (y - closestPointOnInterfaceY) * GradVals[iMin, 1]); minDistSigned *= sign; //Console.WriteLine(String.Format("Quadrature point #{0}: ({1}, {2}), interface point: ({3}, {4})", count, X[0], X[1], closestPointOnInterfaceX, closestPointOnInterfaceY)); count++; return(minDistSigned); }; // DG level set field SinglePhaseField DGLevelSet = new SinglePhaseField(field.Basis, "levelSet_recon"); DGLevelSet.ProjectField(func.Vectorize()); Console.WriteLine("finished"); return(DGLevelSet); }