/// <summary> /// Creates the LevelSet field for the Tracker based on the Option selected /// </summary> /// <param name="DGLevelSet">the unfiltered Level-set</param> /// <param name="gridData"></param> /// <param name="Option"></param> /// <returns>The filtered Level-Set Field </returns> public static LevelSet CreateField(SinglePhaseField DGLevelSet, Foundation.Grid.Classic.GridData gridData, ContinuityProjectionOption Option) { int k = DGLevelSet.Basis.Degree + 1; switch (Option) { case ContinuityProjectionOption.SpecFEM: { var ContinuousLevelSetBasis = new SpecFemBasis(gridData, k); return(new LevelSet(ContinuousLevelSetBasis.ContainingDGBasis, "Phi")); } case ContinuityProjectionOption.ConstrainedDG: { var ContinuousLevelSetDGBasis = new Basis(gridData, k); return(new LevelSet(ContinuousLevelSetDGBasis, "Phi")); } case ContinuityProjectionOption.None: { Console.WriteLine("WARNING: No additional enforcement of the level-set continuity!"); LevelSet SmoothedLevelSet = new LevelSet(DGLevelSet.Basis, "Phi"); DGLevelSet = SmoothedLevelSet; return(SmoothedLevelSet); } default: throw new ArgumentException(); } }
/// <summary> /// Selects all cells according to their cell centers, where <paramref name="SelectionFunction"/> is true /// </summary> /// <param name="gridData"></param> /// <param name="SelectionFunc"></param> /// <returns></returns> public static CellMask GetCellMask(Foundation.Grid.Classic.GridData gridDat, Func <double[], bool> SelectionFunc) { BitArray CellArray = new BitArray(gridDat.Cells.NoOfLocalUpdatedCells); MultidimensionalArray CellCenters = gridDat.Cells.CellCenter; for (int i = 0; i < gridDat.Cells.NoOfLocalUpdatedCells; i++) { switch (gridDat.SpatialDimension) { case 1: { CellArray[i] = SelectionFunc(new double[] { CellCenters[i, 0] }); break; } case 2: { CellArray[i] = SelectionFunc(new double[] { CellCenters[i, 0], CellCenters[i, 1] }); break; } case 3: { CellArray[i] = SelectionFunc(new double[] { CellCenters[i, 0], CellCenters[i, 1], CellCenters[i, 2] }); break; } default: throw new ArgumentException(); } } return(new CellMask(gridDat, CellArray, MaskType.Logical)); }
/// <summary> /// Selects algorithm variant based on the <paramref name="Option"/> /// </summary> /// <param name="DGLevelSet">Discontinuous Field</param> /// <param name="gridData"></param> /// <param name="Option">Choice of algorithm</param> /// <param name="SmoothedLevelSet">The Continuous Field</param> public ContinuityProjection(SinglePhaseField DGLevelSet, Foundation.Grid.Classic.GridData gridData, ContinuityProjectionOption Option) { int k = DGLevelSet.Basis.Degree + 1; myOption = Option; switch (Option) { case ContinuityProjectionOption.SpecFEM: { var ContinuousLevelSetBasis = new SpecFemBasis(gridData, k); MyProjection = new ContinuityProjectionSpecFem(ContinuousLevelSetBasis); break; } case ContinuityProjectionOption.ContinuousDG: { var ContinuousLevelSetDGBasis = new Basis(gridData, k); MyProjection = new ContinuityProjectionCDG(ContinuousLevelSetDGBasis); break; } case ContinuityProjectionOption.None: { MyProjection = new NoProjection(); break; } default: throw new ArgumentException(); } }
/// <summary> /// Addition/Subtraction of DG fields on different grids /// </summary> /// <param name="A"></param> /// <param name="scaleA"></param> /// <param name="B"></param> /// <param name="scaleB"></param> /// <returns> /// <paramref name="scaleA"/>*<paramref name="A"/> + <paramref name="scaleB"/>*<paramref name="B"/> /// </returns> static public DGField ScaledSummation(this DGField A, double scaleA, DGField B, double scaleB) { if (object.ReferenceEquals(A.GridDat, B.GridDat)) { // ++++++++++++++++++++++++++++ // both fields on the same grid // ++++++++++++++++++++++++++++ DGField sum; if (A.Basis.IsSubBasis(B.Basis)) { sum = (DGField)B.Clone(); sum.Scale(scaleB); sum.AccLaidBack(1.0, A); } else if (B.Basis.IsSubBasis(A.Basis)) { sum = (DGField)A.Clone(); sum.Scale(scaleA); sum.AccLaidBack(1.0, B); } else { throw new ApplicationException("can't add the two fields, because their basis are incompatible"); } sum.Identification = "(" + scaleA + "*" + A.Identification + "+" + scaleB + "*" + B.Identification + ")"; return(sum); } else { // ++++++++++++++++++++++++++ // fields on different grids // ++++++++++++++++++++++++++ DGField fine, coarse; double aF, aC; if (A.GridDat.CellPartitioning.TotalLength > B.GridDat.CellPartitioning.TotalLength) { fine = A; coarse = B; aF = scaleA; aC = scaleB; } else { coarse = A; fine = B; aC = scaleA; aF = scaleB; } Foundation.Grid.Classic.GridData fineGridData = GridHelper.ExtractGridData(fine.GridDat); Foundation.Grid.Classic.GridData coarseGridData = GridHelper.ExtractGridData(coarse.GridDat); DGFieldComparison.ComputeFine2CoarseMap( fineGridData, coarseGridData, out var Fine2CoarseMapS); DGField injected; if (coarse is ConventionalDGField) { ConventionalDGField _injected = new SinglePhaseField( new Basis(fine.GridDat, Math.Max(coarse.Basis.Degree, fine.Basis.Degree)), coarse.Identification); DGFieldComparison.InjectDGField(Fine2CoarseMapS, _injected, coarse as ConventionalDGField); injected = _injected; } else if (coarse is XDGField) { XDGField _injected = new XDGField( new XDGBasis((fine as XDGField).Basis.Tracker, Math.Max(coarse.Basis.Degree, fine.Basis.Degree)), coarse.Identification); DGFieldComparison.InjectXDGField(Fine2CoarseMapS, _injected, coarse as XDGField); injected = _injected; } else { throw new NotSupportedException(); } return(ScaledSummation(injected, aC, fine, aF)); } }