//static void Main(string[] args) { // BoSSS.Solution.Application._Main(args, false, null, () => new VortexRock4()); //} protected override IGrid CreateOrLoadGrid() { int NumOfCells = 4; double[] xnodes1 = GenericBlas.Linspace(-10, -5, NumOfCells + 1); double[] xnodes2 = GenericBlas.Linspace(-5, 5, 4 * NumOfCells + 1); double[] xnodes3 = GenericBlas.Linspace(5, 10, NumOfCells + 1); double[] xComplete = new double[xnodes1.Length + xnodes2.Length + xnodes3.Length - 2]; for (int i = 0; i < xnodes1.Length; i++) { xComplete[i] = xnodes1[i]; } for (int i = 1; i < xnodes2.Length; i++) { xComplete[i + xnodes1.Length - 1] = xnodes2[i]; } for (int i = 1; i < xnodes3.Length; i++) { xComplete[i + xnodes1.Length + xnodes2.Length - 2] = xnodes3[i]; } GridCommons grd = Grid2D.Cartesian2DGrid(xComplete, xComplete, CellType.Square_Linear, true, true); grd.Description = "2D cartesian grid 10x10 cells"; return(grd); }
void RegisterTagNamesTo(GridCommons grid) { foreach (KeyValuePair <byte, string> tagName in boundary.EdgeTagNames) { grid.EdgeTagNames.Add(tagName); } }
/// <summary> /// Test using subsonicInlet at the inlet and /// supersonicInlet (Dirichlet) at the outlet /// </summary> /// <returns></returns> public static CNSControl[] EulerSubsonicInlet1D() { CNSControl[] templates = GetTemplates(); foreach (CNSControl c in templates) { int divisions = (int)c.Paramstudy_CaseIdentification.Single(t => t.Item1 == "divisions").Item2; int noOfCells = (2 << divisions) * 8; c.GridFunc = delegate { GridCommons grid = Grid1D.LineGrid( GenericBlas.Linspace(0.0, Math.PI / 2.0 + 0.0, noOfCells + 1)); grid.EdgeTagNames.Add(1, "supersonicInlet"); grid.EdgeTagNames.Add(2, "subsonicInlet"); grid.DefineEdgeTags((Vector x) => Math.Abs(x[0]) < 1e-14 ? (byte)2 : (byte)1); return(grid); }; c.ProjectName += "_subsonicInlet2"; c.AddBoundaryValue("subsonicInlet", CompressibleVariables.Density, exactDensity); c.AddBoundaryValue("subsonicInlet", CNSVariables.Velocity[0], exactVelocity); c.AddBoundaryValue("supersonicInlet", CompressibleVariables.Density, exactDensity); c.AddBoundaryValue("supersonicInlet", CNSVariables.Velocity[0], exactVelocity); c.AddBoundaryValue("supersonicInlet", CNSVariables.Pressure, exactPressure); } return(templates); }
/// <summary> /// plot a 2D grid /// </summary> public static void Plot2DGrid(this GridCommons grd, params int[] Cells) { using (var gp = new Gnuplot()) { Console.WriteLine("Plotting 2D grid with gnuplot..."); if (grd.SpatialDimension != 2) { throw new NotSupportedException("works only for 2D grid"); } int J = grd.Cells.Length; if (Cells == null) { Cells = J.ForLoop(j => j); } foreach (int j in Cells) { var Cell_j = grd.Cells[j]; //var Kref = grd.RefElements.Single(KK => KK.SupportedCellTypes.Contains(Cell_j.Type)); //var Vtx = Kref.Vertices; //var _Vtx = Kref.GetSubDivTree(3).GlobalVertice; //var Vtx = MultidimensionalArray.Create(_Vtx.GetLength(0), _Vtx.GetLength(1)); //Vtx.SetA2d(_Vtx); //Vtx.Scale(1); var Vtx_glob = Cell_j.TransformationParams; double[] xNodes = Vtx_glob.ExtractSubArrayShallow(-1, 0).To1DArray(); double[] yNodes = Vtx_glob.ExtractSubArrayShallow(-1, 1).To1DArray(); double xC = xNodes.Sum() / xNodes.Length; double yC = yNodes.Sum() / yNodes.Length; for (int k = 0; k < xNodes.Length; k++) { double dx = xNodes[k] - xC; dx *= 0.95; xNodes[k] = xC + dx; double dy = yNodes[k] - yC; dy *= 0.95; yNodes[k] = yC + dy; } double hy = yNodes.Max() - yNodes.Min(); gp.PlotXY(xNodes, yNodes, title: null, format: (new PlotFormat(Style: Styles.LinesPoints, lineColor: ((LineColors)j)))); gp.Cmd("set label \"{0}\" at {2},{3} font \"Arial,5\"", j.ToString(), Cell_j.GlobalID, xC.ToStringDot(), (yC + hy * 0.21).ToStringDot()); gp.Cmd("set label \"[{1}]\" at {2},{3} font \"Arial,5\"", j.ToString(), Cell_j.GlobalID, xC.ToStringDot(), (yC - hy * 0.21).ToStringDot()); } gp.Execute(); Console.WriteLine("Press any key to continue..."); Console.ReadKey(); } }
/// <summary> /// Test using SubsonicPressureInlet at the inlet and /// SubsonicOutlet at the outlet. That is, this test case /// uses physically correct boundary conditions /// </summary> /// <returns></returns> public static CNSControl[] EulerSubsonicPressureInletAndOutletTest1D() { CNSControl[] templates = GetTemplates(); foreach (CNSControl c in templates) { int divisions = (int)c.Paramstudy_CaseIdentification.Single(t => t.Item1 == "divisions").Item2; int noOfCells = (2 << divisions) * 8; c.GridFunc = delegate { GridCommons grid = Grid1D.LineGrid( GenericBlas.Linspace(0.0, Math.PI / 2.0 + 0.0, noOfCells + 1)); grid.EdgeTagNames.Add(1, "subsonicPressureInlet"); grid.EdgeTagNames.Add(2, "subsonicOutlet"); grid.DefineEdgeTags((Vector x) => Math.Abs(x[0]) < 1e-14 ? (byte)1 : (byte)2); return(grid); }; c.AddBoundaryValue("subsonicPressureInlet", "p0", totalPressure); c.AddBoundaryValue("subsonicPressureInlet", "T0", totalTemperature); c.AddBoundaryValue("subsonicOutlet", CNSVariables.Pressure, exactPressure); } return(templates); }
protected override GridCommons CreateOrLoadGrid() { double[] xnodes1 = GenericBlas.Linspace(-1, 0, a1 + 1); double[] xnodes2 = GenericBlas.Linspace(0, 0.5, a2 + 1); double[] xnodes3 = GenericBlas.Linspace(0.5, 1, a3 + 1); double[] xComplete = new double[xnodes1.Length + xnodes2.Length + xnodes3.Length - 2]; for (int i = 0; i < xnodes1.Length; i++) { xComplete[i] = xnodes1[i]; } for (int i = 1; i < xnodes2.Length; i++) { xComplete[i + xnodes1.Length - 1] = xnodes2[i]; } for (int i = 1; i < xnodes3.Length; i++) { xComplete[i + xnodes1.Length + xnodes2.Length - 2] = xnodes3[i]; } double[] ynodes = GenericBlas.Linspace(0, 0.1, 2); GridCommons grd = Grid2D.Cartesian2DGrid(xComplete, ynodes, CellType.Square_Linear, true, false); grd.Description = "2D cartesian grid 35x1 cells"; return(grd); }
/// <summary> /// Override the original run method defined by the super-class because /// we don't want to run an actual calculation. Plots the data for /// every selected time-step. /// </summary> protected void Run() { ISessionInfo session = m_Database.Controller.GetSessionInfo(m_config.SessionGuid); var timesteps = session.Timesteps.Where( tsi => this.m_config.TimeSteps.Contains(tsi.TimeStepNumber)).ToArray(); int TotCnt = timesteps.Count(); int process = this.DBDriver.MyRank + 1; int processCount = this.DBDriver.Size; this.m_info = this.m_Database.Controller.GetSessionInfo(this.m_config.SessionGuid); GC.Collect(); for (int i = 0; i < timesteps.Length; i++) { var ts = timesteps[i]; double physTime = ts.PhysicalTime; TimestepNumber timestepNo = ts.TimeStepNumber; if (this.GridDat == null || !this.GridDat.Grid.ID.Equals(ts.Grid.ID)) { WriteMessage(process, processCount, "Loading grid ..."); GridCommons grid = DBDriver.LoadGrid(ts.Grid.ID, m_Database); this.GridDat = this.m_Database.Controller.GetInitializationContext(ts).GridData; WriteMessage(process, processCount, " Number of cells: " + this.GridDat.Grid.NoOfUpdateCells); this.CreatePlotter(); } WriteMessage(process, processCount, "Loading timestep ... (" + (i + 1) + " of " + TotCnt + ")"); var fields = DBDriver.LoadFields(ts, this.GridDat, this.m_config.FieldNames).ToList(); WriteMessage(process, processCount, "Loaded timestep " + timestepNo + ". Plotting..."); //{ // Console.WriteLine("computing vorticity..."); // DGField velX = fields.Single(f => f.Identification == "VelocityX"); // DGField velY = fields.Single(f => f.Identification == "VelocityY"); // DGField vortZ = velX.CloneAs(); // vortZ.Identification = "Vorticity"; // vortZ.Clear(); // vortZ.DerivativeByFlux(1.0, velY, 0); // vortZ.DerivativeByFlux(-1.0, velX, 1); // Console.WriteLine("done."); // fields.Add(vortZ); //} PlotCurrentState(fields, physTime, timestepNo); double perc = Math.Round(100.0 * (double)(i + 1) / (double)TotCnt, 1); WriteMessage(process, processCount, "Finished timestep (" + perc + "% of timesteps done)"); // Free memory if possible timesteps[i] = null; GC.Collect(); } }
/// <summary> /// Experimental /// </summary> /// <param name="grid"></param> public static void Save(this IGridInfo grid) { if (grid is GridCommons) { GridCommons realGrid = (GridCommons)grid; grid.Database.Controller.DBDriver.SaveGrid(realGrid); } else { throw new NotImplementedException(); } }
/// <summary> /// Cartesian grid, nothing fancy. /// </summary> public void CreateGrid(Context _Context, out GridCommons grd, out IncompressibleBoundaryCondMap bcMap) { grd = new Cartesian2DGrid(_Context.CommMaster, Grid1D.Linspace(-2, 2, 10), Grid1D.Linspace(-2, 2, 10)); grd.EdgeTagsNames.Add(1, "Pressure_Outlet"); grd.DefineEdgeTags(x => 1); bcMap = null; }
public VoronoiGrid(GridCommons pGrid, int[][] logialToGeometricalCellMap, VoronoiNodes nodes, VoronoiBoundary boundary) : base(pGrid, logialToGeometricalCellMap) { this.nodes = nodes; this.boundary = boundary; }
protected override void AdaptMesh(int TimestepNo, out GridCommons newGrid, out GridCorrelation old2NewGrid) { if (TimestepNo > 3 && TimestepNo % 3 != 0) { //{ newGrid = null; old2NewGrid = null; return; } // Check grid changes // ================== bool AnyChange; List <int> CellsToRefineList; List <int[]> Coarsening; GridRefinementController gridRefinementController = new GridRefinementController((GridData)this.GridData, LsTrk.Regions.GetCutCellMask()); if (MPISize > 1) { List <Tuple <int, BitArray> > cellMaskRefinementLevel = GetCellMaskWithRefinementLevels(); AnyChange = gridRefinementController.ComputeGridChange(cellMaskRefinementLevel, out CellsToRefineList, out Coarsening); } else { AnyChange = gridRefinementController.ComputeGridChange(LevelIndicator, out CellsToRefineList, out Coarsening); } int NoOfCellsToRefine = 0; int NoOfCellsToCoarsen = 0; if (AnyChange) { int[] glb = (new int[] { CellsToRefineList.Count, Coarsening.Sum(L => L.Length), }).MPISum(); NoOfCellsToRefine = glb[0]; NoOfCellsToCoarsen = glb[1]; } int oldJ = this.GridData.CellPartitioning.TotalLength; // Update Grid // =========== if (AnyChange) { Console.WriteLine(" Refining " + NoOfCellsToRefine + " of " + oldJ + " cells"); Console.WriteLine(" Coarsening " + NoOfCellsToCoarsen + " of " + oldJ + " cells"); newGrid = ((GridData)this.GridData).Adapt(CellsToRefineList, Coarsening, out old2NewGrid); } else { newGrid = null; old2NewGrid = null; } }
/// <summary> /// Imports the grid stored at the given location into /// <paramref name="database"/>. /// </summary> /// <param name="database"> /// The database where the grid should be stored /// </param> /// <param name="fileName"> /// The path to the grid file /// </param> /// <param name="test"> /// If set to true, a <see cref="GridData"/> object is created in order to do more extensive testing on the imported grid. /// </param> /// <returns> /// The newly imported grid /// </returns> public static IGridInfo ImportGrid(this IDatabaseInfo database, string fileName, bool test = true) { GridCommons grid = GridImporter.Import(fileName); if (test) { new GridData(grid); } database.Controller.SaveGridInfo(grid); return(grid); }
public void RegisterEdgesTo(GridCommons grid) { if (boundary.EdgeTagNames != null) { RegisterTagNamesTo(grid); } if (periodicBoundaryConverter != null) { periodicBoundaryConverter.RegisterPeriodicBoundariesTo(grid); } }
/// <summary> /// Determines the mesh size of a given <paramref name="gridInfo"/> /// based on <see cref="GridData.CellData.h_maxGlobal"/>. /// </summary> /// <param name="gridInfo">A grid</param> /// <returns> /// A (heuristic) measure for the mesh size of /// <paramref name="gridInfo"/>. /// </returns> public static double GetMeshSize(this IGridInfo gridInfo) { if (gridInfo is GridProxy) { gridInfo = gridInfo.Cast<GridProxy>().RealGrid; } GridCommons grid = gridInfo as GridCommons; if (!(grid is GridCommons)) { throw new ArgumentException("Only works for grids of type 'GridCommons'"); } return new GridData(grid).Cells.h_maxGlobal; }
/// <summary> /// Creates a plotting instruction with default configuration options. /// </summary> /// <param name="grid"> /// The grid to be plotted. /// </param> public GridExportInstruction(IGridInfo grid) { this.Grid = grid; // because hacks work. (TODO) IFileSystemDriver fsdrv = new StandardFsDriver(grid.Database.Path); dbDriver = new DatabaseDriver(fsdrv); GridCommons gridComm = dbDriver.LoadGrid(grid.ID, grid.Database); GridDat = new GridData(gridComm); }
/// <summary> /// creates a simple 2d/3d Cartesian grid within the domain (-7,7)x(-7,7); /// </summary> protected override GridCommons CreateOrLoadGrid() { //m_GridPartitioningType = GridPartType.none; double[] xnodes = GenericBlas.Linspace(-7, 7, 101); double[] ynodes = GenericBlas.Linspace(-7, 7, 101); GridCommons grd = Grid2D.Cartesian2DGrid(xnodes, ynodes, type: CellType.Square_Linear); //double[] xnodes = GenericBlas.Linspace(-7, 7, 25); //double[] ynodes = GenericBlas.Linspace(-7, 7, 25); //double[] znodes = GenericBlas.Linspace(-7, 7, 25); //var grd = Grid3D.Cartesian3DGrid(xnodes, ynodes, znodes); return(grd); }
/// <summary> /// Creation of DG fields. /// </summary> protected override void CreateFields() { int GridDeg; int D = this.GridData.SpatialDimension; if (this.Grid is GridCommons) { GridCommons _Grid = (GridCommons)this.Grid; GridDeg = _Grid.Cells.Select(cl => _Grid.GetRefElement(cl.Type).GetInterpolationDegree(cl.Type)).Max(); if (_Grid.GetRefElement(_Grid.Cells[0].Type) == Square.Instance || _Grid.GetRefElement(_Grid.Cells[0].Type) == Cube.Instance) { // hack: otherwise DG deg gets to large GridDeg = (int)Math.Round(Math.Pow(GridDeg, 1.0 / D)); } } else { GridDeg = 1; // aggregation grid } Basis b = new Basis(this.GridData, 2 + GridDeg); Console.WriteLine("Grid degree is " + GridDeg + " => Using DG order: " + b.Degree); f1 = new SinglePhaseField(b, "f1"); f2 = new SinglePhaseField(b, "f2"); Laplace_f1_Numerical = new SinglePhaseField(b, "Laplace_f1_Numerical"); Laplace_f2_Numerical = new SinglePhaseField(b, "Laplace_f2_Numerical"); Laplace_f1_Analytical = new SinglePhaseField(b, "Laplace_f1_Analytical"); Laplace_f2_Analytical = new SinglePhaseField(b, "Laplace_f2_Analytical"); f1Gradient_Analytical = new SinglePhaseField[D]; f2Gradient_Analytical = new SinglePhaseField[D]; f1Gradient_Numerical = new SinglePhaseField[D]; f2Gradient_Numerical = new SinglePhaseField[D]; for (int d = 0; d < D; d++) { f1Gradient_Analytical[d] = new SinglePhaseField(b, string.Format("df1_dx{0}_Analytical", d)); f2Gradient_Analytical[d] = new SinglePhaseField(b, string.Format("df2_dx{0}_Analytical", d)); f1Gradient_Numerical[d] = new SinglePhaseField(b, string.Format("df1_dx{0}_Numerical", d)); f2Gradient_Numerical[d] = new SinglePhaseField(b, string.Format("df2_dx{0}_Numerical", d)); } }
/// <summary> /// Override the original run method defined by the super-class because /// we don't want to run an actual calculation. Plots the data for /// every selected time-step. /// </summary> protected void Run() { ISessionInfo session = m_Database.Controller.GetSessionInfo(m_config.SessionGuid); var timesteps = session.Timesteps.Where( tsi => this.m_config.TimeSteps.Contains(tsi.TimeStepNumber)).ToArray(); int TotCnt = timesteps.Count(); int process = this.DBDriver.MyRank + 1; int processCount = this.DBDriver.Size; this.m_info = this.m_Database.Controller.GetSessionInfo(this.m_config.SessionGuid); GC.Collect(); for (int i = 0; i < timesteps.Length; i++) { var ts = timesteps[i]; double physTime = ts.PhysicalTime; TimestepNumber timestepNo = ts.TimeStepNumber; if (this.GridDat == null || !this.GridDat.Grid.ID.Equals(ts.Grid.ID)) { WriteMessage(process, processCount, "Loading grid ..."); GridCommons grid = DBDriver.LoadGrid(ts.Grid.ID, m_Database); this.GridDat = this.m_Database.Controller.GetInitializationContext(ts).GridData; WriteMessage(process, processCount, " Number of cells: " + this.GridDat.Grid.NoOfUpdateCells); this.CreatePlotter(); } WriteMessage(process, processCount, "Loading timestep ... (" + (i + 1) + " of " + TotCnt + ")"); var fields = DBDriver.LoadFields(ts, this.GridDat, this.m_config.FieldNames); WriteMessage(process, processCount, "Loaded timestep " + timestepNo + ". Plotting..."); PlotCurrentState(fields, physTime, timestepNo); double perc = Math.Round(100.0 * (double)(i + 1) / (double)TotCnt, 1); WriteMessage(process, processCount, "Finished timestep (" + perc + "% of timesteps done)"); // Free memory if possible timesteps[i] = null; GC.Collect(); } }
public GridCommons GenerateBoSSSGrid() { GridCommons ret = null; foreach (var zone in this.Zones) { GridCommons g = zone.GenerateBoSSSGrid(); if (ret == null) { ret = g; } else { ret = GridCommons.MergeGrids(ret, g); ret.MergeUnspecifiedEdges(); } } return(ret); }
public void RegisterPeriodicBoundariesTo(GridCommons grid) { Debug.Assert(boundaryMap.PeriodicTrafos is SortedList <byte, AffineTrafo>); var periodicTrafos = boundaryMap.PeriodicTrafos; //Sort by edgeTag foreach (var pair in periodicTrafos) { AffineTrafo trafo = pair.Value; byte edgeTag = pair.Key; byte edgeTagInGrid = grid.AddPeriodicEdgeTrafo(trafo); Debug.Assert(edgeTag == edgeTagInGrid); if (!grid.EdgeTagNames.ContainsKey(edgeTagInGrid)) { grid.EdgeTagNames.Add(edgeTagInGrid, $"periodic corner {edgeTagInGrid}"); } } }
/// <summary> /// Test using <see cref="SupersonicInlet"/> (Dirichlet) everywhere /// </summary> /// <returns></returns> public static CNSControl[] EulerSupersonicInlet1D() { CNSControl[] templates = GetTemplates(); foreach (CNSControl c in templates) { int divisions = (int)c.Paramstudy_CaseIdentification.Single(t => t.Item1 == "divisions").Item2; int noOfCells = (2 << divisions) * 8; c.GridFunc = delegate { GridCommons grid = Grid1D.LineGrid( GenericBlas.Linspace(0.0, Math.PI / 2.0 + 0.0, noOfCells + 1)); grid.EdgeTagNames.Add(1, "supersonicInlet"); grid.DefineEdgeTags(x => 1); return(grid); }; c.ProjectName += "_supersonicAll"; } return(templates.ToArray()); }
/// <summary> /// Uses <see cref="SubsonicPressureInlet"/> at the inlet and /// <see cref="SupersonicInlet"/> (Dirichlet) at the outlet /// </summary> /// <returns></returns> public static CNSControl[] EulerSubsonicPressureInletTest1D() { CNSControl[] templates = GetTemplates(); foreach (CNSControl c in templates) { int divisions = (int)c.Paramstudy_CaseIdentification.Single(t => t.Item1 == "divisions").Item2; int noOfCells = (2 << divisions) * 8; c.GridFunc = delegate { GridCommons grid = Grid1D.LineGrid( GenericBlas.Linspace(0.0, Math.PI / 2.0 + 0.0, noOfCells + 1)); grid.EdgeTagNames.Add(1, "supersonicInlet"); grid.EdgeTagNames.Add(2, "subsonicPressureInlet"); grid.DefineEdgeTags(x => Math.Abs(x[0]) < 1e-14 ? (byte)2 : (byte)1); return(grid); }; } return(templates); }
/// <summary> /// Common settings for all tests within this set of test cases /// </summary> /// <param name="divisions"></param> /// <param name="dgDegree"></param> /// <returns></returns> private static VortexControl Template(int divisions, int dgDegree) { VortexControl c = new VortexControl(); c.savetodb = false; c.ActiveOperators = Operators.Convection; c.ExplicitScheme = ExplicitSchemes.RungeKutta; c.ExplicitOrder = 4; c.MachNumber = 1 / Math.Sqrt(c.EquationOfState.HeatCapacityRatio); c.AddVariable(Variables.Density, dgDegree); c.AddVariable(Variables.Momentum.xComponent, dgDegree); c.AddVariable(Variables.Momentum.yComponent, dgDegree); c.AddVariable(Variables.Energy, dgDegree); c.AddVariable(Variables.Pressure, dgDegree); c.AddVariable(Variables.Entropy, dgDegree); c.GridFunc = delegate { int noOfCellsPerDirection = (2 << divisions) * 10; GridCommons grid = Grid2D.Cartesian2DGrid( GenericBlas.Linspace(-10.0, 10.0, noOfCellsPerDirection + 1), GenericBlas.Linspace(-10.0, 10.0, noOfCellsPerDirection + 1), periodicX: true, periodicY: true); return(grid); }; c.VortexSpeed = 1.0; c.dtMin = 0.01; c.dtMax = 0.01; c.CFLFraction = double.NaN; c.Endtime = 0.2; c.NoOfTimesteps = int.MaxValue; return(c); }
protected override IGrid CreateOrLoadGrid() { GridCommons grd = grid.GetGrid(); return(grd); }
internal static GridData FOAMmesh_to_BoSSS(int nCells, int[][] faces, int[] neighbour, int[] owner, double[,] points) { // Checks // ====== int nFaces = faces.Length; int nInternalFaces = neighbour.Length; Debug.Assert(nFaces == owner.Length); int nPoints = points.GetLength(0); if (owner.Length != faces.Length) { throw new ArgumentException("mismatch between length of faces and owner array"); } #if DEBUG // extended sanity checks for (int i = 0; i < faces.Length; i++) { int[] pts = faces[i]; foreach (int iVtx in pts) { if (iVtx < 0) { throw new ArgumentException("negative vertex index for face " + i); } if (iVtx >= points.GetLength(0)) { throw new ArgumentException("vertex index out-of-range for face " + i); } } if (owner[i] < 0 || owner[i] >= nCells) { throw new ArgumentException("face owner out-of-range for face " + i); } } for (int i = 0; i < neighbour.Length; i++) { if (owner[i] < 0 || owner[i] >= nCells) { throw new ArgumentException("face neighbor out-of-range for face " + i); } } #endif // Build Cells-to-Faces correlation // ================================ List <int>[] Cells2Faces = new List <int> [nCells]; for (int j = 0; j < nCells; j++) { Cells2Faces[j] = new List <int>(); } for (int iFace = 0; iFace < nFaces; iFace++) { Debug.Assert(Cells2Faces[owner[iFace]].Contains(iFace) == false); Cells2Faces[owner[iFace]].Add(iFace); } for (int iInternalFace = 0; iInternalFace < nInternalFaces; iInternalFace++) { int NeighCell = neighbour[iInternalFace]; Debug.Assert(Cells2Faces[NeighCell].Contains(iInternalFace) == false); Cells2Faces[NeighCell].Add(iInternalFace); } // convert to BoSSS grid // ===================== Cell[] bosss_cells = new Cell[nCells]; for (int iCell = 0; iCell < nCells; iCell++) { var Cell2Faces = Cells2Faces[iCell]; if (Cell2Faces.Count == 6 && !Cell2Faces.Select(iFace => faces[iFace].Length == 4).Contains(false)) { // +++++++++++++++ // found some Cube // +++++++++++++++ int[][] cube_faces = Cell2Faces.Select(iFace => faces[iFace]).ToArray(); Debug.Assert(cube_faces.Length == 6); HashSet <int> NodesUnsorted = new HashSet <int>(); foreach (int iFace in Cell2Faces) { foreach (int iPoint in faces[iFace]) { NodesUnsorted.Add(iPoint); } } if (NodesUnsorted.Count != 8) { throw new NotImplementedException("Degenerate cubes are not supported."); } // create cell Cell cl = new Cell(); bosss_cells[iCell] = cl; cl.GlobalID = iCell; cl.Type = CellType.Cube_8; cl.NodeIndices = new int[8]; cl.TransformationParams = MultidimensionalArray.Create(8, 3); // Find point indices for bottom, i.e. 'y == -1' (in ref. coordinates): cl.NodeIndices[0] = cube_faces[0][0]; cl.NodeIndices[1] = cube_faces[0][1]; cl.NodeIndices[6] = cube_faces[0][2]; cl.NodeIndices[3] = cube_faces[0][3]; // Find point indices for 'x == -1'-wall (in ref. coordinates): bool found = false; for (int iCF = 1; iCF < 6; iCF++) { found = ContainsEdge(cube_faces[iCF], cl.NodeIndices[0], cl.NodeIndices[3], out cl.NodeIndices[2], out cl.NodeIndices[7]); if (found) { break; } } if (found == false) { throw new NotSupportedException("weired cell topology in cell " + iCell + "; assuming a cube/hex;"); } // Find point indices for 'x == +1'-wall (in ref. coordinates): found = false; for (int iCF = 1; iCF < 6; iCF++) { found = ContainsEdge(cube_faces[iCF], cl.NodeIndices[1], cl.NodeIndices[6], out cl.NodeIndices[4], out cl.NodeIndices[5]); if (found) { break; } } if (found == false) { throw new NotSupportedException("weired cell topology in cell " + iCell + "; assuming a cube/hex;"); } // set point coordinates for (int i = 0; i < 8; i++) { cl.TransformationParams.SetRow(i, points.GetRow(cl.NodeIndices[i])); } // Jacobian Test JacobianTest(cl, out bool PositiveJacobianFlag, out bool NegativeJacobianFlag, out bool Linear); if (NegativeJacobianFlag) { // flip top/bottom int _0 = cl.NodeIndices[0]; int _1 = cl.NodeIndices[1]; int _6 = cl.NodeIndices[6]; int _3 = cl.NodeIndices[3]; cl.NodeIndices[0] = cl.NodeIndices[2]; cl.NodeIndices[1] = cl.NodeIndices[4]; cl.NodeIndices[6] = cl.NodeIndices[5]; cl.NodeIndices[3] = cl.NodeIndices[7]; cl.NodeIndices[2] = _0; cl.NodeIndices[4] = _1; cl.NodeIndices[5] = _6; cl.NodeIndices[7] = _3; for (int i = 0; i < 8; i++) { cl.TransformationParams.SetRow(i, points.GetRow(cl.NodeIndices[i])); } JacobianTest(cl, out PositiveJacobianFlag, out NegativeJacobianFlag, out Linear); } if (NegativeJacobianFlag || !PositiveJacobianFlag) { throw new NotSupportedException("Found degenerate Jacobian in cell " + iCell); } Debug.Assert(PositiveJacobianFlag == true); Debug.Assert(NegativeJacobianFlag == false); if (Linear) { cl.Type = CellType.Cube_Linear; cl.TransformationParams = cl.TransformationParams.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { 3, 2 }).CloneAs(); } } else { throw new NotImplementedException("At the moment, only support for hex cells."); } } // create BoSSS grid // ================== GridCommons grd = new GridCommons(new RefElement[] { Cube.Instance }, new RefElement[] { Square.Instance }) { Cells = bosss_cells, Description = "imported form OpenFOAM" }; var gDat = new GridData(grd); return(gDat); }
/// <summary> /// Generates a grid commons object /// </summary> /// <returns>the grid commons object</returns> public GridCommons GenerateBoSSSGrid() { int j, k, l, i; int max_bc_index = -1; GenerateZonelessAndSectionlessArrays(); CoordinateSystemTransformation(); VertexIndexNumberingTransformation(); //BuildFaces(); //BuildAndShareBoundaryConditions(); //BuildNeighbourship(); double[, ,] vertices = new double[bosss_elements, verticesPerCell, number_of_coord_dimensions]; long[] globalID = new long[bosss_elements]; byte[,] edgeTags = new byte[bosss_elements, number_of_faces_per_element]; for (l = 0, k = 0; l < bosss_elements; l++) { j = bosss_element_index_to_cgns_element_index[l]; for (int n = 0; n < verticesPerCell; n++) { k = cgns_element_index_to_bosss_element_index[j]; int node_no = elements[j][n]; vertices[k, n, 0] = x[node_no]; vertices[k, n, 1] = y[node_no]; if (number_of_coord_dimensions == 3) { vertices[k, n, 2] = z[node_no]; } } } GridCommons grd = null; if (bosss_element_type.Equals(ElementType_t.QUAD_4)) { grd = new Grid2D(new Square()); } else if (bosss_element_type.Equals(ElementType_t.TRI_3)) { grd = new Grid2D(new Triangle()); } else if (bosss_element_type.Equals(ElementType_t.HEXA_8)) { throw new NotImplementedException(); } else if (bosss_element_type.Equals(ElementType_t.TETRA_4)) { throw new NotImplementedException(); } else { throw new NotSupportedException("Unsupported BoSSS element type"); } int tag_number = 1; for (i = 0; i < bcelements.Length; i++) // over boundary condition indices { foreach (int z in bc_to_element_indices[i]) // over elements { j = z >> number_of_faces_per_element; j = cgns_element_index_to_bosss_element_index[j]; k = z & number_of_faces_per_element_mask; edgeTags[j, k] = (byte)tag_number; if (tag_number > max_bc_index) { max_bc_index = tag_number; } } tag_number++; } bool duplicatedBoundaryConditionNames = false; List <string> edgeTagNameList = new List <string>(); for (i = 0; i < max_bc_index; i++) // over boundary condition interfaces { string edgeTagName = CleanString(new string(boconames[i])); if (edgeTagNameList.Contains(edgeTagName)) { duplicatedBoundaryConditionNames = true; } edgeTagNameList.Add(edgeTagName); } tag_number = 1; List <string> edgeTagNameForbiddenList = new List <string>(); List <int> numberList = new List <int>(); if (duplicatedBoundaryConditionNames) { for (i = 0; i < edgeTagNameList.Count; i++) { string edgeTagName = edgeTagNameList[i]; if (edgeTagNameForbiddenList.Contains(edgeTagName)) { continue; } for (j = i + 1; j < edgeTagNameList.Count; j++) { if (edgeTagNameList[j].Equals(edgeTagName)) { replaceEdgeTagNumerInCaseOfDublicateBoundaryConditions(edgeTags, (byte)(j + 1), (byte)(i + 1)); max_bc_index--; if (numberList.Contains(i + 1)) { continue; } numberList.Add(i + 1); } } edgeTagNameForbiddenList.Add(edgeTagName); } for (i = 0; i < max_bc_index; i++) // over boundary condition interfaces { replaceEdgeTagNumerInCaseOfDublicateBoundaryConditions(edgeTags, (byte)numberList[i], (byte)(i + 1)); } for (i = 0; i < max_bc_index; i++) // over boundary condition interfaces { grd.EdgeTagsNames.Add((byte)tag_number, edgeTagNameForbiddenList[i]); tag_number++; } } else { foreach (string edgeTagName in edgeTagNameList) { grd.EdgeTagsNames.Add((byte)tag_number, edgeTagName); tag_number++; } } /* * * // remove 'internal' boundaries ... * { * // pointvise may also assign boundaries for internal edges... * // this is not allowed by bosss, so we have to clear them * * int E = cell_neighbours.GetLength(1); * * for (j = 0; j < bosss_elements; j++) { * for (int e = 0; e < E; e++) { * if (cell_neighbours[j, e] >= 0) * // this is an internal edge * if (edgeTags[j, e] != 0) * edgeTags[j, e] = 0; * } * } * * // remove unused edgetag-names * int[] EdgeTagUseCnt = new int[tag_number]; * for (j = 0; j < bosss_elements; j++) { * for (int e = 0; e < E; e++) { * int tag = edgeTags[j, e]; * EdgeTagUseCnt[tag]++; * } * } * * * for (int tag = 0; tag < tag_number; tag++) { * if (EdgeTagUseCnt[tag] <= 0) * grd.EdgeTagsNames.Remove((byte)tag); * } * * * //// test whether all boundary edges have an assigned edge tag... * //// (it's legal for a BoSSS grid to have unspecified edge tags) * //for (j = 0; j < bosss_elements; j++) { * // for (int e = 0; e < E; e++) { * // int tag = edgeTags[j, e]; * // long neigh = cell_neighbours[j,e]; * * // if (neigh < 0 && tag == 0) * // throw new ApplicationException("found boundary edge without assigned edge tag."); * // } * //} * * } */ grd.Description = "Created from BoSSS"; grd.Cells = new Cell[bosss_elements]; for (j = 0; j < bosss_elements; j++) { grd.Cells[j] = new Cell(); grd.Cells[j].GlobalID = j; //grd.Cells[j].Neighbours = new long[number_of_faces_per_element]; //grd.Cells[j].EdgeTags = new byte[number_of_faces_per_element]; throw new NotImplementedException("todo"); for (i = 0; i < number_of_faces_per_element; i++) { //grd.Cells[j].Neighbours[i] = cell_neighbours[j, i]; //grd.Cells[j].EdgeTags[i] = edgeTags[j, i]; } } //grd.Vertices = vertices; throw new NotImplementedException("todo"); //return grd; }
/// <summary> /// See also <see cref="GRID_CASE"/> and <see cref="GRID_FILE"/>. /// </summary> protected override GridCommons CreateOrLoadGrid() { GridCommons grd; switch (GRID_CASE) { case 1: grd = Grid1D.LineGrid(GenericBlas.Linspace(-4, 4, 5)); break; case 2: { grd = Grid1D.LineGrid(GenericBlas.Linspace(-4, 4, 20)); break; } case 3: { double[] xnodes = new double[] { -2, 0, 2 }; double[] ynodes = new double[] { -2, 0, 2 }; double dx = xnodes[1] - xnodes[0]; double dy = ynodes[1] - ynodes[0]; //this.CellVolume = dx * dy; //if(Math.Abs(dx - dy) <= 1.0e-12) // EdgeArea = dx; grd = Grid2D.Cartesian2DGrid(xnodes, ynodes, periodicX: false, periodicY: false, type: CellType.Square_4); break; } case 4: { double[] xnodes = GenericBlas.Linspace(-1, 5, 9); double[] ynodes = GenericBlas.Linspace(-1, 5, 13); double dx = xnodes[1] - xnodes[0]; double dy = ynodes[1] - ynodes[0]; this.CellVolume = dx * dy; if (Math.Abs(dx - dy) <= 1.0e-12) { EdgeArea = dx; } grd = Grid2D.Cartesian2DGrid(xnodes, ynodes, periodicX: false, periodicY: false, type: CellType.Square_4); break; } case 5: { double[] xnodes = GenericBlas.Linspace(-1, 1, 8); double[] ynodes = GenericBlas.Linspace(-1, 1, 13); grd = Grid2D.UnstructuredTriangleGrid(xnodes, ynodes, JitterScale: 0.5); break; } case 6: { grd = Circle(); break; } case 7: { // test periodicity grd = Grid2D.CurvedSquareGrid(GenericBlas.Linspace(1, 2, 4), GenericBlas.Linspace(0, 0.25, 10), CellType.Square_9, PeriodicS: true); AltRefSol = true; break; } case 8: { double[] rNodes = GenericBlas.Linspace(1, 4, 8); double[] sNodes = GenericBlas.Linspace(0, 0.5, 15); grd = Grid2D.CurvedSquareGrid(rNodes, sNodes, CellType.Square_4, PeriodicS: false); break; } case 9: { double[] xNodes1 = GenericBlas.Linspace(-1, 0.3, 7); double[] yNodes1 = GenericBlas.Linspace(-1, 1, 13); double[] xNodes2 = GenericBlas.Linspace(0.3, 1, 5); double[] yNodes2 = GenericBlas.Linspace(-1, 1, 25); double[] xNodes3 = GenericBlas.Linspace(-1, 1, 8); double[] yNodes3 = GenericBlas.Linspace(-2, -1, 5); var grd1 = Grid2D.Cartesian2DGrid(xNodes1, yNodes1, type: CellType.Square_Linear); var grd2 = Grid2D.Cartesian2DGrid(xNodes2, yNodes2, type: CellType.Square_Linear); var grd3 = Grid2D.Cartesian2DGrid(xNodes3, yNodes3, type: CellType.Square_Linear); var grdJ = GridCommons.MergeLogically(grd1, GridCommons.MergeLogically(grd2, grd3)); grd = GridCommons.Seal(grdJ, 4); break; } case 10: { double[] xNodes1 = GenericBlas.Linspace(-1, 0.3, 4); double[] xNodes2 = GenericBlas.Linspace(0.3, 1, 5); double[] yNodes1 = GenericBlas.Linspace(-1, 1, 9); double[] yNodes2 = GenericBlas.Linspace(-1, 1, 5); double[] zNodes1 = GenericBlas.Linspace(-1, 1, 5); double[] zNodes2 = GenericBlas.Linspace(-1, 1, 3); var grd1 = Grid3D.Cartesian3DGrid(xNodes1, yNodes1, zNodes1); var grd2 = Grid3D.Cartesian3DGrid(xNodes2, yNodes2, zNodes2); var grdJ = GridCommons.MergeLogically(grd1, grd2); grd = GridCommons.Seal(grdJ, 4); break; } case 11: { grd = Grid2D.Trapezoidal2dGrid(4, 2, 2, GenericBlas.Linspace(0, 1, 2)); break; } case 12: { var grid1 = Grid2D.Cartesian2DGrid(GenericBlas.Linspace(-3, 5, 5), GenericBlas.Linspace(-1, 1, 2)); //grd = base_grid; //grid1.Plot2DGrid(); var gdat1 = new GridData(grid1); var grid2 = gdat1.Adapt(new int[] { 1, 2 }, null, out GridCorrelation o2c_1); //grid2.Plot2DGrid(); var gdat2 = new GridData(grid2); var grid3 = gdat2.Adapt(new int[] { 2, 4 }, null, out GridCorrelation o2c_2); //grid3.Plot2DGrid(); var gdat3 = new GridData(grid3); var grid4 = gdat3.Adapt(new int[] { 11, 14, 15 }, null, out GridCorrelation o2c_3); //grid4.Plot2DGrid(); var gdat4 = new GridData(grid4); var grid5 = gdat4.Adapt(new[] { 4, 21, 22, 10 }, new[] { new[] { 13, 14, 15, 16 } }, out GridCorrelation o2c_4); //grid5.Plot2DGrid(); grd = grid5; break; } case 13: { double[] rNodes = GenericBlas.Linspace(1, 4, 8); double[] sNodes = GenericBlas.Linspace(0, 0.5, 15); grd = Grid2D.CurvedSquareGrid(rNodes, sNodes, CellType.Square_9, PeriodicS: false); break; } case 14: { double[] rNodes = GenericBlas.Linspace(1, 4, 13); double[] sNodes = GenericBlas.Linspace(0, 0.5, 25); grd = Grid2D.CurvedSquareGrid(rNodes, sNodes, CellType.Square_16, PeriodicS: false); break; } case 15: { double[] rNodes = GenericBlas.Linspace(1, 2, 4); double[] sNodes = GenericBlas.Linspace(0, 0.5, 4); double[] zNodes = GenericBlas.Linspace(-1, 1, 5); grd = Grid3D.CylinderGrid(rNodes, sNodes, zNodes, CellType.Cube_27, PeriodicS: false, PeriodicZ: false); break; } case 16: { grd = Grid2D.Ogrid(0.5, 1, 5, 3, CellType.Square_4); break; } case 17: { grd = Grid3D.Ogrid(0.5, 1, 3, 3, GenericBlas.Linspace(0, 4, 3)); break; } case 18: { // aggregation grid double[] xNodes = GenericBlas.Linspace(-1, 1, 5); double[] yNodes = GenericBlas.Linspace(-1, 1, 5); var baseGrid = Grid2D.UnstructuredTriangleGrid(xNodes, yNodes); var baseGdat = new GridData(baseGrid); var aggGrid = CoarseningAlgorithms.Coarsen(baseGdat, 2); base.AggGrid = aggGrid; grd = null; double dx = xNodes[1] - xNodes[0]; double dy = yNodes[1] - yNodes[0]; this.CellVolume = dx * dy; if (Math.Abs(dx - dy) <= 1.0e-12) { EdgeArea = dx; } break; } // ++++++++++++++++++++++++++++++++++++++++++++++++++++ // more expensive grids (not tested in DEBUG MODE) // ++++++++++++++++++++++++++++++++++++++++++++++++++++ case 30: { double[] xnodes = GenericBlas.Linspace(-1, 1, 7); double[] ynodes = GenericBlas.Linspace(-1, 1, 9); double[] znodes = GenericBlas.Linspace(-1, 1, 8); grd = Grid3D.Cartesian3DGrid(xnodes, ynodes, znodes, periodicX: false, periodicY: false, periodicZ: false); break; } // +++++++++++++++++++++++++++++++++ // grids imported from GMSH/CGNS // +++++++++++++++++++++++++++++++++ case 50: { // gmsh grid import test Console.WriteLine("Loading file: '" + GRID_FILE + "'..."); grd = GridImporter.Import(GRID_FILE); //Console.WriteLine("done. " + grd.NoOfUpdateCells.MPISum() + " cells loaded."); //Plot2dGridGnuplot(grd); HashSet <CellType> cellTypes = new HashSet <CellType>(); foreach (var cell in grd.Cells) { if (!cellTypes.Contains(cell.Type)) { cellTypes.Add(cell.Type); } } Console.Write("Cell types: "); foreach (var ct in cellTypes) { Console.Write(ct); Console.Write(" "); } Console.WriteLine(); break; } default: throw new NotSupportedException(); } return(grd); }
/// <summary> /// sets values for <see cref="Cell.CellFaceTags"/> by using a /// <paramref name="EdgeTagFunc"/>-function; also adds entries with empty names /// to the <see cref="EdgeTagNames"/>-dictionary, if the edge tag /// returned by the <paramref name="EdgeTagFunc"/>-function is not in /// the dictionary /// </summary> static public void DefineEdgeTags(this IGrid g, Func <Vector, string> EdgeTagFunc, params string[] EdgeTagNamesToEnsure) { int D = g.SpatialDimension; double[] x = new double[D]; MultidimensionalArray GlobalVerticesOut = MultidimensionalArray.CreateWrapper(x, 1, D); Dictionary <string, byte> EdgeTagNames_Reverse = new Dictionary <string, byte>(); EdgeTagNames_Reverse.Add("inner edge", 0); int[] etUseCount = new int[byte.MaxValue]; foreach (var kv in g.EdgeTagNames) { if (kv.Key == 0) { } else { EdgeTagNames_Reverse.Add(kv.Value, kv.Key); if (kv.Key >= GridCommons.FIRST_PERIODIC_BC_TAG) { etUseCount[kv.Key] = 1; } } } GridCommons baseGrid = null; if (g is GridCommons gcm) { baseGrid = gcm; } else if (g is Aggregation.AggregationGrid ag) { baseGrid = ag.RootGrid as GridCommons; } var GrdDatTmp = g.iGridData; // loop over edges... bool LoopOverEdges(Func <int, int, int, byte> GetEt) { bool _GridChanged = false; int NoOfEdges = GrdDatTmp.iGeomEdges.Count; for (int iEdge = 0; iEdge < NoOfEdges; ++iEdge) { if (GrdDatTmp.iGeomEdges.IsEdgeBoundaryEdge(iEdge)) { int jCell = GrdDatTmp.iGeomEdges.CellIndices[iEdge, 0]; int iFace = GrdDatTmp.iGeomEdges.FaceIndices[iEdge, 0]; // get edge tag byte et = GetEt(iEdge, jCell, iFace); // record edge tag if (baseGrid != null) { var _Cell = baseGrid.Cells[jCell]; var allCFTs = _Cell.CellFaceTags; int found = 0; if (allCFTs != null) { for (int i = 0; i < allCFTs.Length; i++) { if (allCFTs[i].NeighCell_GlobalID < 0 && allCFTs[i].FaceIndex == iFace) { found++; if (allCFTs[i].EdgeTag == et) { // nop } else { allCFTs[i].EdgeTag = et; _GridChanged = true; } } } } if (found > 1) { throw new ApplicationException(string.Format("Cell face tags inconsistent in cell (GlId={0},LocIdx={1}): found {2} boundary tags for face {3}.", _Cell.GlobalID, jCell, found, iFace)); } if (found <= 0) { CellFaceTag CFT = new CellFaceTag() { EdgeTag = et, FaceIndex = iFace, NeighCell_GlobalID = long.MinValue }; CFT.AddToArray(ref baseGrid.Cells[jCell].CellFaceTags); _GridChanged = true; } } GrdDatTmp.iGeomEdges.EdgeTags[iEdge] = et; etUseCount[et]++; } } return(_GridChanged); } byte RecordTag(int iedge, int jCell, int iFace) { var KRef = GrdDatTmp.iGeomCells.GetRefElement(jCell); // call edge-tag-name function GrdDatTmp.TransformLocal2Global(KRef.GetFaceCenter(iFace), GlobalVerticesOut, jCell); string EdgeTagName = EdgeTagFunc(x); // obtain edge tag if (!EdgeTagNames_Reverse.ContainsKey(EdgeTagName)) { int NewTag = EdgeTagNames_Reverse.Count; Debug.Assert(NewTag > 0); if (NewTag >= GridCommons.FIRST_PERIODIC_BC_TAG) { throw new ApplicationException("To many different edge tag names; at maximum " + (Classic.GridCommons.FIRST_PERIODIC_BC_TAG - 1) + " different tags for non-periodic boundaries."); } EdgeTagNames_Reverse.Add(EdgeTagName, (byte)NewTag); } var et = EdgeTagNames_Reverse[EdgeTagName]; return(et); } // pass 1: assign edge tags locally bool GridChanged = LoopOverEdges(RecordTag); GridChanged = GridChanged.MPIOr(); // pass 2: MPI syncronization if (GridChanged && g.Size > 1) { byte[] ETTranslation = SyncEdgeTagsOverMPI(EdgeTagNames_Reverse); if (ETTranslation != null) { LoopOverEdges(delegate(int iedge, int jCell, int iFace) { byte oldEt = GrdDatTmp.iGeomEdges.EdgeTags[iedge]; byte newEt = ETTranslation[oldEt]; return(newEt); }); } } // store & return etUseCount = etUseCount.MPISum(); g.EdgeTagNames.Clear(); foreach (var kv in EdgeTagNames_Reverse) { if (kv.Value == 0 || etUseCount[kv.Value] > 0) { g.EdgeTagNames.Add(kv.Value, kv.Key); } } if (GridChanged) { g.InvalidateGridData(); Console.WriteLine("Grid Edge Tags changed."); } foreach (string EdgeTagName in EdgeTagNamesToEnsure) { g.AddEdgeTag(EdgeTagName); } }
protected override GridCommons CreateOrLoadGrid() { // Options string dataPath = @"\\fdyprime\userspace\mueller\Jan\waves\"; string databasePath = @"e:\bosss_db\GridOfTomorrow\"; noOfCellsX = 64; noOfNodesPerEdge = 4; dgDegree = 6; //noOfCellsX = 85; //noOfNodesPerEdge = 4; //dgDegree = 6; Directory.SetCurrentDirectory(dataPath); DatabaseInfo database = new DatabaseInfo(databasePath); string sessionDescription = "Blafasel"; // Create the grid aspectRatio = 4; GridCommons grid = Grid2D.Cartesian2DGrid( GenericBlas.Linspace(0.0, 1.0, noOfCellsX + 1), GenericBlas.Linspace(-1.5, 2.5, aspectRatio * noOfCellsX + 1), CellType.Square_Linear, periodicX: true, periodicY: false); grid.EdgeTagNames.Add(1, "subsonicOutlet"); grid.EdgeTagNames.Add(2, "supersonicInlet"); grid.DefineEdgeTags(delegate(double[] x) { if (x[1] > 0.0) { return(2); } else { return(1); } }); gridData = new GridData(grid); // Read the values MultidimensionalArray rho = ReadVariableValues("rho"); MultidimensionalArray u = ReadVariableValues("vx1"); MultidimensionalArray v = ReadVariableValues("vx2"); MultidimensionalArray p = ReadVariableValues("prs"); // Assemble node set corresponding to the ordering from Matlab double[] nodes1D = GenericBlas.Linspace(-1.0, 1.0, noOfNodesPerEdge); int noOfNodesPerCell = noOfNodesPerEdge * noOfNodesPerEdge; double[,] localNodes = new double[noOfNodesPerCell, gridData.SpatialDimension]; for (int i = 0; i < noOfNodesPerEdge; i++) { for (int j = 0; j < noOfNodesPerEdge; j++) { int localNodeIndex = i * noOfNodesPerEdge + j; localNodes[localNodeIndex, 0] = nodes1D[i]; localNodes[localNodeIndex, 1] = nodes1D[j]; } } nodeSet = new NodeSet(gridData.Grid.RefElements[0], localNodes); // Interpolate //SinglePhaseField[] fields = LeastSquaresInterpolation(rho, u, v, p); SinglePhaseField[] fields = SpecFEMInterpolation(rho, u, v, p); // Save everything database.Controller.DBDriver.SaveGrid(grid); SessionInfo session = database.Controller.DBDriver.CreateNewSession(database); session.Description = sessionDescription; session.Save(); database.Controller.DBDriver.SaveTimestep( 0.0, 0, session, gridData, fields); return(grid); }
static void Plot2dGridGnuplot(GridCommons grd) { using (var gp = new Gnuplot()) { int J = grd.Cells.Length; double xmin = double.MaxValue, xmax = double.MinValue, ymin = double.MaxValue, ymax = double.MinValue; for (int j = 0; j < J; j++) { var Cell = grd.Cells[j]; var Kref = grd.GetRefElement(Cell.Type); int[] R; if (Kref.GetType() == typeof(Triangle)) { R = new int[] { 0, 1, 2, 0 }; } else if (Kref.GetType() == typeof(Square)) { R = new int[] { 0, 1, 3, 2, 0 }; } else { throw new NotSupportedException(); } int I = 4; int K = 20; NodeSet LocNodes = new NodeSet(Kref, I * K * (R.Length - 1), 2); var vtx = Kref.Vertices; double alpha = 1.0 / (K - 1); for (int iFace = 0; iFace < R.Length - 1; iFace++) { for (int k = 0; k < K; k++) { double a = alpha * k; for (int d = 0; d < 2; d++) { LocNodes[iFace * K + k, d] = vtx[R[iFace], d] * (1 - a) + vtx[R[iFace + 1], d] * a; } } } for (int i = 0; i < I; i++) { int ind0 = K * (R.Length - 1) * i; int indE = K * (R.Length - 1) * (i + 1) - 1; int indp0 = K * (R.Length - 1) * (i - 1); int indpE = K * (R.Length - 1) * i - 1; var LocNodes_i = LocNodes.ExtractSubArrayShallow(new int[] { ind0, 0 }, new int[] { indE, 1 }); if (i > 0) { var LocNodes_iP = LocNodes.ExtractSubArrayShallow(new int[] { indp0, 0 }, new int[] { indpE, 1 }); LocNodes_i.Set(LocNodes_iP); LocNodes_i.Scale(0.65); } else { LocNodes_i.Scale(0.9); } } LocNodes.LockForever(); MultidimensionalArray GlobalNodes = Transform(Kref, Cell, LocNodes); xmin = Math.Min(xmin, GlobalNodes.ExtractSubArrayShallow(-1, 0).Min()); xmax = Math.Max(xmax, GlobalNodes.ExtractSubArrayShallow(-1, 0).Max()); ymin = Math.Min(ymin, GlobalNodes.ExtractSubArrayShallow(-1, 1).Min()); ymax = Math.Max(ymax, GlobalNodes.ExtractSubArrayShallow(-1, 1).Max()); gp.PlotXY(GlobalNodes.GetColumn(0), GlobalNodes.GetColumn(1), title: ("tri" + j), format: new PlotFormat(lineColor: ((LineColors)j))); } gp.SetXRange(xmin - 0.1, xmax + 0.1); gp.SetYRange(ymin - 0.1, ymax + 0.1); gp.Execute(); Console.WriteLine("press any key to continue..."); Console.ReadKey(); } }