/// <summary> /// modifies a matrix <paramref name="Mtx"/> and a right-hand-side <paramref name="rhs"/> /// in order to fix the pressure at some reference point /// </summary> /// <param name="map">row mapping for <paramref name="Mtx"/> as well as <paramref name="rhs"/></param> /// <param name="iVar">the index of the pressure variable in the mapping <paramref name="map"/>.</param> /// <param name="LsTrk"></param> /// <param name="Mtx"></param> /// <param name="rhs"></param> static public void SetPressureReferencePoint <T>(UnsetteledCoordinateMapping map, int iVar, LevelSetTracker LsTrk, BlockMsrMatrix Mtx, T rhs) where T : IList <double> { using (new FuncTrace()) { var GridDat = map.GridDat; if (rhs.Count != map.LocalLength) { throw new ArgumentException(); } if (!Mtx.RowPartitioning.EqualsPartition(map) || !Mtx.ColPartition.EqualsPartition(map)) { throw new ArgumentException(); } Basis PressureBasis = (Basis)map.BasisS[iVar]; int D = GridDat.SpatialDimension; long GlobalID, GlobalCellIndex; bool IsInside, onthisProc; GridDat.LocatePoint(new double[D], out GlobalID, out GlobalCellIndex, out IsInside, out onthisProc, LsTrk.Regions.GetCutCellSubGrid().VolumeMask.Complement()); int iRowGl = -111; if (onthisProc) { int jCell = (int)GlobalCellIndex - GridDat.CellPartitioning.i0; NodeSet CenterNode = new NodeSet(GridDat.iGeomCells.GetRefElement(jCell), new double[D]); MultidimensionalArray LevSetValues = LsTrk.DataHistories[0].Current.GetLevSetValues(CenterNode, jCell, 1);; MultidimensionalArray CenterNodeGlobal = MultidimensionalArray.Create(1, D); GridDat.TransformLocal2Global(CenterNode, CenterNodeGlobal, jCell); //Console.WriteLine("Pressure Ref Point @( {0:0.###E-00} | {1:0.###E-00} )", CenterNodeGlobal[0,0], CenterNodeGlobal[0,1]); LevelSetSignCode scode = LevelSetSignCode.ComputeLevelSetBytecode(LevSetValues[0, 0]); ReducedRegionCode rrc; int No = LsTrk.Regions.GetNoOfSpecies(jCell, out rrc); int iSpc = LsTrk.GetSpeciesIndex(rrc, scode); iRowGl = (int)map.GlobalUniqueCoordinateIndex_FromGlobal(iVar, GlobalCellIndex, 0); } iRowGl = iRowGl.MPIMax(); // clear row // --------- if (onthisProc) { // ref. cell is on local MPI process int jCell = (int)GlobalCellIndex - GridDat.CellPartitioning.i0; ReducedRegionCode rrc; int NoOfSpc = LsTrk.Regions.GetNoOfSpecies(jCell, out rrc); // set matrix row to identity Mtx.ClearRow(iRowGl); Mtx.SetDiagonalElement(iRowGl, 1.0); // clear RHS int iRow = iRowGl - Mtx.RowPartitioning.i0; rhs[iRow] = 0; } // clear column // ------------ { for (int i = Mtx.RowPartitioning.i0; i < Mtx.RowPartitioning.iE; i++) { if (i != iRowGl) { Mtx[i, iRowGl] = 0; } } } } }
public void Solve <P, Q>(P X, Q B) where P : IList <double> where Q : IList <double> { int n = Mtx.NoOfCols; double sum = 0; var tempMtx = Mtx; // Zeros on diagonal elements because of saddle point structure for (int bla = 0; bla < n; bla++) { if (Mtx.GetDiagonalElement(bla) == 0) { throw new Exception("One or more diagonal elements are zero, ILU cannot work"); } Mtx.SetDiagonalElement(bla, 1); } // ILU decomposition of matrix for (int k = 0; k < n - 1; k++) { for (int i = k; i < n; i++) { if (tempMtx[i, k] == 0) { i = n; } else { Mtx[i, k] = Mtx[i, k] / Mtx[k, k]; for (int j = k + 1; j < n; j++) { if (tempMtx[i, j] == 0) { j = n; } else { Mtx[i, j] = Mtx[i, j] - Mtx[i, k] * Mtx[k, j]; } } } } } // LU decomposition of matrix //for (int i = 0; i < n; i++) { // for (int j = i; j < n; j++) { // sum = 0; // for (int k = 0; k < i; k++) // sum += Mtx[i, k] * Mtx[k, j]; // Mtx[i, j] = tempMtx[i, j] - sum; // } // for (int j = i + 1; j < n; j++) { // sum = 0; // for (int k = 0; k < i; k++) // sum += Mtx[j, k] * Mtx[k, i]; // Mtx[j, i] = (1 / Mtx[i, i]) * (tempMtx[j, i] - sum); // } //} // find solution of Ly = b double[] y = new double[n]; for (int i = 0; i < n; i++) { sum = 0; for (int k = 0; k < i; k++) { sum += Mtx[i, k] * y[k]; } y[i] = B[i] - sum; } // find solution of Ux = y for (int i = n - 1; i >= 0; i--) { sum = 0; for (int k = i + 1; k < n; k++) { sum += Mtx[i, k] * X[k]; } X[i] = (1 / Mtx[i, i]) * (y[i] - sum); } }