private void AssembleMatrix(double dt, out BlockMsrMatrix SystemMatrix, out double[] SystemAffine) { // Init Matrix and Affine Part SystemMatrix = new BlockMsrMatrix(Mapping); SystemAffine = new double[Mapping.LocalLength]; // choose TimeStepping-Scheme, based on what has been pushed to the stack,yet int Smax = TSCchain[0].S; Debug.Assert(Smax == TSCchain.Length); Tsc = TSCchain[Smax - PopulatedStackDepth]; UpdateOperatorMatrix(); //Implicit Part of RHS SystemMatrix.Acc(Tsc.theta1, Stack_OpMatrix[1]); SystemAffine.AccV(Tsc.theta1, Stack_OpAffine[1]); //Implicit Part of LHS SystemMatrix.AccEyeSp(1 / dt); // Explicit part of RHS Stack_OpMatrix[0].SpMV(-Tsc.theta0, CurrentState, 1.0, SystemAffine); SystemAffine.AccV(-Tsc.theta0, Stack_OpAffine[0]); //Explicit parts of LHS for (int i = 0; i < Tsc.beta.Length; i++) { SystemAffine.AccV(Tsc.beta[i] * 1 / dt, Stack_u[i]); } Debug.Assert(SystemMatrix.InfNorm() > 0); Debug.Assert(SystemAffine.L2Norm() > 0); if (subGrid != null) { int[] SubVecIdx = Mapping.GetSubvectorIndices(subGrid, true, new int[] { 0 }); int L = SubVecIdx.Length; for (int i = 0; i < L; i++) { SystemMatrix.ClearRow(SubVecIdx[i]); SystemMatrix[SubVecIdx[i], SubVecIdx[i]] = 1; SystemAffine[SubVecIdx[i]] = 0; } } }
/// <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; } } } } }