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> /// control of mesh adaptation /// </summary> protected override void AdaptMesh(int TimestepNo, out GridCommons newGrid, out GridCorrelation old2NewGrid) { if (this.Control.AdaptiveMeshRefinement && TimestepNo > 1) { int oldJ = this.GridData.CellPartitioning.TotalLength; double LocNormPow2 = this.ResiualKP1.CoordinateVector.L2NormPow2(); // norm of residual on this processor double TotNormPow2 = LocNormPow2.MPISum(); // norm of residual over all processors double MeanNormPow2PerCell = TotNormPow2 / oldJ; // mean norm per cell double maxSoFar = 0; int jMax = -1; for (int j = 0; j < oldJ; j++) { double CellNorm = Error.Coordinates.GetRow(j).L2NormPow2(); if (CellNorm > maxSoFar) { jMax = j; maxSoFar = CellNorm; } } int LevelIndicator(int j, int CurrentLevel) { double CellNorm = this.ResiualKP1.Coordinates.GetRow(j).L2NormPow2(); if (j == jMax) { return(CurrentLevel + 1); } else { return(CurrentLevel); } } bool AnyChange = GridRefinementController.ComputeGridChange((GridData)(this.GridData), null, LevelIndicator, out List <int> CellsToRefineList, out List <int[]> 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]; } // 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; } } else { newGrid = null; old2NewGrid = null; } }
/// <summary> /// Locally refine p-Order in Cutcells /// </summary> protected override void AdaptMesh(int TimestepNo, out GridCommons newGrid, out GridCorrelation old2NewGrid) { throw new NotImplementedException(); }
/// <summary> /// Apply the resorting (including mesh adaptation). /// </summary> public void Resort(GridCorrelation r, GridData NewGrid) { using (new FuncTrace()) { this.GridAdaptation = false; m_Old2NewCorr = r; m_OldGrid = null; m_OldTracker = null; m_NewGrid = NewGrid; m_newJ = m_NewGrid.iLogicalCells.NoOfLocalUpdatedCells; // fix the sequence in which we serialize/de-serialize fields string[] FieldNames = this.m_oldDGFieldData.Keys.ToArray(); int NoFields = FieldNames.Length; // format data for serialization double[][] oldFieldsData = new double[m_oldJ][]; // 1st: cell; 2nd enum { double[][][] oldFields = FieldNames.Select(rstring => this.m_oldDGFieldData[rstring]).ToArray(); // 1st: field; 2nd: cell; 3rd: DG coord for (int j = 0; j < m_oldJ; j++) { int Ntot = 0; for (int iF = 0; iF < NoFields; iF++) { Ntot += oldFields[iF][j].Length; } // pack the DG coords for each field into one array of the form // { Np_f1, DGcoords_f1, Np_f2, DGcoords_f2, .... }; double[] data_j = new double[Ntot + NoFields]; int cnt = 0; for (int iF = 0; iF < NoFields; iF++) { double[] data_iF_j = oldFields[iF][j]; int Nj = data_iF_j.Length; data_j[cnt] = Nj; cnt++; for (int n = 0; n < Nj; n++) { data_j[cnt] = data_iF_j[n]; cnt++; } } oldFieldsData[j] = data_j; } oldFields = null; m_oldDGFieldData = null; } // redistribute data double[][][] newFieldsData = new double[m_newJ][][]; { //Resorting.ApplyToVector(oldFieldsData, newFieldsData, m_NewGrid.CellPartitioning); r.ApplyToVector(oldFieldsData, newFieldsData, m_NewGrid.CellPartitioning); oldFieldsData = null; Debug.Assert(newFieldsData.Length == m_newJ); } // re-format re-distributed data m_newDGFieldData_GridAdapta = new Dictionary <string, double[][][]>(); { double[][][][] newFields = new double[FieldNames.Length][][][]; // indices: [field, cell idx, enum over coarsening, DG mode] for (int iF = 0; iF < NoFields; iF++) { newFields[iF] = new double[m_newJ][][]; } for (int j = 0; j < m_newJ; j++) { double[][] data_j = newFieldsData[j]; int L = data_j.Length; // cell cluster size (equal 1 for refined or conserved cells) for (int iF = 0; iF < NoFields; iF++) { newFields[iF][j] = new double[L][]; } for (int l = 0; l < L; l++) { double[] data_jl = data_j[l]; int cnt = 0; for (int iF = 0; iF < NoFields; iF++) { int Nj = (int)data_jl[cnt]; cnt++; double[] data_iF_jl = new double[Nj]; for (int n = 0; n < Nj; n++) { data_iF_jl[n] = data_jl[cnt]; cnt++; } newFields[iF][j][l] = data_iF_jl; } Debug.Assert(cnt == data_jl.Length); } } for (int iF = 0; iF < NoFields; iF++) { m_newDGFieldData_GridAdapta.Add(FieldNames[iF], newFields[iF]); } } } }
static private void DoCellj(int j, DGField f, GridData NewGrid, int pDeg, int[] TargMappingIdx_j, double[][] ReDistDGCoords_j, int l, GridCorrelation Old2NewCorr, int N0rcv, int N0acc, int Np, double[] ReDistDGCoords_jl, double[] Coords_j) { Debug.Assert(ReDistDGCoords_j.Length == TargMappingIdx_j.Length); int iKref = NewGrid.Cells.GetRefElementIndex(j); Debug.Assert(Coords_j.Length == Np); Debug.Assert(ReDistDGCoords_jl.Length == Np); for (int n = 0; n < Np; n++) { Coords_j[n] = f.Coordinates[j, N0acc + n]; } int L = ReDistDGCoords_j.Length; if (TargMappingIdx_j.Length == 1) { // ++++++++++ // refinement // ++++++++++ Debug.Assert(l == 0); MultidimensionalArray Trafo = Old2NewCorr.GetSubdivBasisTransform(iKref, TargMappingIdx_j[0], pDeg); for (int n = 0; n < Np; n++) { ReDistDGCoords_jl[n] = ReDistDGCoords_j[0][N0rcv + n]; } Trafo.gemv(1.0, ReDistDGCoords_jl, 1.0, Coords_j, transpose: false); } else { // ++++++++++ // coarsening // ++++++++++ var Trafo = Old2NewCorr.GetSubdivBasisTransform(iKref, TargMappingIdx_j[l], pDeg); for (int n = 0; n < Np; n++) { ReDistDGCoords_jl[n] = ReDistDGCoords_j[l][N0rcv + n]; } Trafo.gemv(1.0, ReDistDGCoords_jl, 1.0, Coords_j, transpose: true); } for (int n = 0; n < Np; n++) { f.Coordinates[j, N0acc + n] = Coords_j[n]; } }
static private void DoCellj(int j, DGField f, GridData NewGrid, int pDeg, int[] TargMappingIdx_j, double[][] ReDistDGCoords_j, int l, GridCorrelation Old2NewCorr, int N0rcv, int N0acc, int Np, double[] ReDistDGCoords_jl, double[] Coords_j) { Debug.Assert(ReDistDGCoords_j.Length == TargMappingIdx_j.Length); Debug.Assert(object.ReferenceEquals(NewGrid, f.GridDat)); int iKref = NewGrid.Cells.GetRefElementIndex(j); Debug.Assert(Coords_j.Length == Np); Debug.Assert(ReDistDGCoords_jl.Length == Np); for (int n = 0; n < Np; n++) { Coords_j[n] = f.Coordinates[j, N0acc + n]; // for coarsening, we 'touch' each cell multiple times -- therefore, values must be accumulated } int L = ReDistDGCoords_j.Length; if (TargMappingIdx_j.Length == 1) { // ++++++++++ // refinement // ++++++++++ Debug.Assert(l == 0); MultidimensionalArray Trafo = Old2NewCorr.GetSubdivBasisTransform(iKref, TargMappingIdx_j[0], pDeg).Item1; double scale = Old2NewCorr.GetSubdivBasisTransform(iKref, TargMappingIdx_j[0], pDeg).Item2; for (int n = 0; n < Np; n++) { ReDistDGCoords_jl[n] = ReDistDGCoords_j[0][N0rcv + n]; } Trafo.gemv(1.0, ReDistDGCoords_jl, 1.0, Coords_j, transpose: false); BckTrafo(Coords_j, Np, 0, NewGrid, j, pDeg, scale.Sqrt()); } else { // ++++++++++ // coarsening // ++++++++++ var Trafo = Old2NewCorr.GetSubdivBasisTransform(iKref, TargMappingIdx_j[l], pDeg).Item1; double scale = Old2NewCorr.GetSubdivBasisTransform(iKref, TargMappingIdx_j[l], pDeg).Item2; for (int n = 0; n < Np; n++) { ReDistDGCoords_jl[n] = ReDistDGCoords_j[l][N0rcv + n]; } //if (!Oasch) { // Trafo.gemv(1.0, ReDistDGCoords_jl, 1.0, Coords_j, transpose: true); //} else { double[] buf = new double[Np]; Trafo.gemv(1.0, ReDistDGCoords_jl, 1.0, buf, transpose: true); BckTrafo(buf, Np, 0, NewGrid, j, pDeg, 1.0 / scale.Sqrt()); Coords_j.AccV(1.0, buf); //} } for (int n = 0; n < Np; n++) { f.Coordinates[j, N0acc + n] = Coords_j[n]; } }