static public double[] GetParticleForces(VectorField <SinglePhaseField> U, SinglePhaseField P, LevelSetTracker LsTrk, double muA) { int D = LsTrk.GridDat.SpatialDimension; // var UA = U.Select(u => u.GetSpeciesShadowField("A")).ToArray(); var UA = U.ToArray(); int RequiredOrder = U[0].Basis.Degree * 3 + 2; //int RequiredOrder = LsTrk.GetXQuadFactoryHelper(momentFittingVariant).GetCachedSurfaceOrders(0).Max(); //Console.WriteLine("Order reduction: {0} -> {1}", _RequiredOrder, RequiredOrder); //if (RequiredOrder > agg.HMForder) // throw new ArgumentException(); Console.WriteLine("Forces coeff: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder); ConventionalDGField pA = null; //pA = P.GetSpeciesShadowField("A"); pA = P; double[] forces = new double[D]; for (int d = 0; d < D; d++) { ScalarFunctionEx ErrFunc = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) { int K = result.GetLength(1); // No nof Nodes MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Len, K, D, D);; MultidimensionalArray pARes = MultidimensionalArray.Create(Len, K); // Evaluate tangential velocity to level-set surface var Normals = LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len); for (int i = 0; i < D; i++) { UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1); } pA.Evaluate(j0, Len, Ns, pARes); if (LsTrk.GridDat.SpatialDimension == 2) { for (int j = 0; j < Len; j++) { for (int k = 0; k < K; k++) { double acc = 0.0; // pressure switch (d) { case 0: acc += pARes[j, k] * Normals[j, k, 0]; acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1]; break; case 1: acc += pARes[j, k] * Normals[j, k, 1]; acc -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0]; break; default: throw new NotImplementedException(); } result[j, k] = acc; } } } else { for (int j = 0; j < Len; j++) { for (int k = 0; k < K; k++) { double acc = 0.0; // pressure switch (d) { case 0: acc += pARes[j, k] * Normals[j, k, 0]; acc -= (2 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 2]; acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 2]; break; case 1: acc += pARes[j, k] * Normals[j, k, 1]; acc -= (2 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 2]; acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 2]; break; case 2: acc += pARes[j, k] * Normals[j, k, 2]; acc -= (2 * muA) * Grad_UARes[j, k, 2, 2] * Normals[j, k, 2]; acc -= (muA) * Grad_UARes[j, k, 2, 0] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 2, 1] * Normals[j, k, 1]; acc -= (muA) * Grad_UARes[j, k, 0, 2] * Normals[j, k, 0]; acc -= (muA) * Grad_UARes[j, k, 1, 2] * Normals[j, k, 1]; break; default: throw new NotImplementedException(); } result[j, k] = acc; } } } }; var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper; //var SchemeHelper = new XQuadSchemeHelper(LsTrk, momentFittingVariant, ); CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask()); CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat, cqs.Compile(LsTrk.GridDat, RequiredOrder), // agg.HMForder), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { ErrFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { forces[d] += ResultsOfIntegration[i, 0]; } } ).Execute(); } for (int i = 0; i < D; i++) { forces[i] = MPI.Wrappers.MPIExtensions.MPISum(forces[i]); } return(forces); }
/// <summary> /// only for debugging and testing; converts the matrix to a full matrix; /// when running in parallel, the matrix is collected on process 0. /// </summary> /// <returns> /// null on all MPI processes, except on rank 0; /// </returns> static public MultidimensionalArray ToFullMatrixOnProc0(this IMutableMatrixEx tis) { var comm = tis.MPI_Comm; int Rank = tis.RowPartitioning.MpiRank; int Size = tis.RowPartitioning.MpiSize; double[,] ret = null; if (Rank == 0) { ret = new double[tis.NoOfRows, tis.NoOfCols]; } SerialisationMessenger sms = new SerialisationMessenger(comm); if (Rank > 0) { sms.SetCommPath(0); } sms.CommitCommPaths(); Tuple <int, int[], double[]>[] data; { int L = tis.RowPartitioning.LocalLength; data = new Tuple <int, int[], double[]> [L]; int i0 = (int)tis.RowPartitioning.i0; for (int i = 0; i < L; i++) { double[] val = null; // this mem. must be inside the loop/allocated for every i and cannot be reused because we need all rows later. int[] col = null; int Lr = tis.GetRow(i + i0, ref col, ref val); data[i] = new Tuple <int, int[], double[]>(Lr, col, val); } } if (Rank > 0) { sms.Transmit(0, data); } int rcvProc = 0; if (Rank == 0) { do { int i0 = (int)tis.RowPartitioning.GetI0Offest(rcvProc); if (data.Length != tis.RowPartitioning.GetLocalLength(rcvProc)) { throw new ApplicationException("internal error"); } for (int i = 0; i < data.Length; i++) { //foreach (MsrMatrix.MatrixEntry entry in data[i]) { // if (entry.m_ColIndex >= 0) // ret[i + i0, entry.m_ColIndex] = entry.Value; //} int Lr = data[i].Item1; int[] col = data[i].Item2; double[] val = data[i].Item3; for (int lr = 0; lr < Lr; lr++) { ret[i + i0, col[lr]] = val[lr]; } } } while (sms.GetNext(out rcvProc, out data)); } else { if (sms.GetNext(out rcvProc, out data)) { throw new ApplicationException("internal error"); } } if (Rank == 0) { var _ret = MultidimensionalArray.Create(ret.GetLength(0), ret.GetLength(1)); for (int i = 0; i < _ret.NoOfRows; i++) { for (int j = 0; j < _ret.NoOfCols; j++) { _ret[i, j] = ret[i, j]; } } return(_ret); } else { return(null); } }
/// <summary> /// multiplies an <see cref="BlockDiagonalMatrix"/> by an <see cref="MsrMatrix"/> /// </summary> public static MsrMatrix Multiply(BlockDiagonalMatrix left, MsrMatrix right) { using (new FuncTrace()) { if (left.NoOfCols != right.NoOfRows) { throw new ArgumentException("matrix size mismatch"); } int _N = left.NoOfRowsPerBlock; // left blocks: no. of rows int _M = left.NoOfColsPerBlock; // left blocks: no. of columns = right blocks: no. of rows int _L = _M; // right blocks: no. of columns. Hope that fits, otherwise inefficient MsrMatrix result = new MsrMatrix(left.RowPartitioning, right.ColPartition); MultidimensionalArray lBlock = MultidimensionalArray.Create(_N, _M); //MsrMatrix.MSREntry[][] BlockRow = new MsrMatrix.MSREntry[_M][]; //List<int> OccupiedBlocks = new List<int>(); var OccupiedBlocks = new SortedDictionary <int, MultidimensionalArray>(); List <MultidimensionalArray> MatrixPool = new List <MultidimensionalArray>(); // avoid realloc int poolCnt = 0; MultidimensionalArray resBlock = MultidimensionalArray.Create(_N, _L); // loop over all blocks ... int NoBlks = left.m_RowPart.LocalLength / left.NoOfRowsPerBlock; for (int iBlk = 0; iBlk < NoBlks; iBlk++) { // reset: OccupiedBlocks.Clear(); poolCnt = 0; foreach (var M in MatrixPool) { M.Clear(); } // upper left corner of block int i0 = iBlk * _N + (int)left.RowPartitioning.i0; int j0 = (i0 / _N) * _M; // load block for (int n = 0; n < _N; n++) { for (int m = 0; m < _M; m++) { lBlock[n, m] = left.Blox[iBlk, n, m]; } } // read Msr rows int Last_rBlkCol = int.MinValue; MultidimensionalArray Block = null; for (int m = 0; m < _N; m++) { var BlockRow = right.GetRowShallow(j0 + m); foreach (var e in BlockRow) { if (e.m_ColIndex >= 0) { int rBlkCol = e.m_ColIndex / _L; if (rBlkCol != Last_rBlkCol) { if (!OccupiedBlocks.TryGetValue(rBlkCol, out Block)) { if (MatrixPool.Count <= poolCnt) { MatrixPool.Add(MultidimensionalArray.Create(_M, _L)); } Block = MatrixPool[poolCnt]; OccupiedBlocks.Add(rBlkCol, Block); poolCnt++; } Last_rBlkCol = rBlkCol; } int jj = e.m_ColIndex % _L; Block[m, jj] = e.Value; } } } Block = null; // execute multiplys foreach (KeyValuePair <int, MultidimensionalArray> rBlock in OccupiedBlocks) { resBlock.GEMM(1.0, lBlock, rBlock.Value, 0.0); // upper left edge of resBlock int _i0 = i0; int _j0 = rBlock.Key * _L; // write block for (int i = 0; i < _M; i++) { for (int j = 0; j < _L; j++) { result[i + _i0, j + _j0] = resBlock[i, j]; } } } } // return return(result); } }
public void Update(MultiphaseCellAgglomerator Agglomerator) { using (new FuncTrace()) { //if(!this.XDGBasis.IsSubBasis(mmf.MaxBasis)) // throw new ArgumentException(); var LsTrk = this.XDGBasis.Tracker; var CCBit = LsTrk.Regions.GetCutCellMask().GetBitMask(); int N = this.DGBasis.Length; int JAGG = base.AggGrid.iLogicalCells.NoOfLocalUpdatedCells; UpdateSpeciesMapping(Agglomerator); // mass matrix in the aggregate cell, before we orthonormalize: var AggCellMMb4Ortho = MultidimensionalArray.Create(N, N); for (int jagg = 0; jagg < JAGG; jagg++) { int NoOfSpc_jagg = this.NoOfSpecies[jagg]; int[] AggCell = base.AggGrid.iLogicalCells.AggregateCellToParts[jagg]; int K = AggCell.Length; int[,] sim = this.SpeciesIndexMapping[jagg]; Debug.Assert((sim == null) || (sim.GetLength(0) == NoOfSpc_jagg)); Debug.Assert((sim == null) || (sim.GetLength(1) == K)); if (sim == null) { // nothing to do. // +++++++++++++++++++++++++++++++++++++++++++++++ this.XCompositeBasis[jagg] = null; } else { // the cut-cell may require some special treatment // +++++++++++++++++++++++++++++++++++++++++++++++ for (int iSpc_agg = 0; iSpc_agg < NoOfSpc_jagg; iSpc_agg++) // loop over all species in aggregate cell { bool emptyCell = false; // true: at least one of the base cells which form // aggregate cell 'jagg' is empty with respect to the 'iSpc_agg'--th species. // => this will alter the projection operator. for (int k = 0; k < K; k++) { if (sim[iSpc_agg, k] < 0) { emptyCell = true; break; } } #if DEBUG { bool NonEmpty = false; for (int k = 0; k < K; k++) { if (sim[iSpc_agg, k] >= 0) { NonEmpty = true; break; } } Debug.Assert(NonEmpty); // there should be at least one non-empty base cell (for species 'iSpc_agg') // in aggregate cell 'jagg' } #endif if (this.XCompositeBasis[jagg] == null || (this.XCompositeBasis[jagg].Length != NoOfSpc_jagg)) { this.XCompositeBasis[jagg] = new MultidimensionalArray[NoOfSpc_jagg]; } if (emptyCell) { // compute mass matrix in aggregate cell 'jagg' for species index 'iSpc_agg' // ------------------------------------------------------------------------- AggCellMMb4Ortho.Clear(); for (int k = 0; k < K; k++) // loop over the base cells in the aggregate cell { if (sim[iSpc_agg, k] >= 0) { var ExPolMtx = base.CompositeBasis[jagg].ExtractSubArrayShallow(k, -1, -1); AggCellMMb4Ortho.Multiply(1.0, ExPolMtx, ExPolMtx, 1.0, "lm", "im", "il"); } } // change to orthonormal basis // --------------------------- MultidimensionalArray B = MultidimensionalArray.Create(N, N); AggCellMMb4Ortho.SymmetricLDLInversion(B, default(double[])); if (this.XCompositeBasis[jagg][iSpc_agg] == null) { this.XCompositeBasis[jagg][iSpc_agg] = MultidimensionalArray.Create(K, N, N); } var X_ExPolMtx = this.XCompositeBasis[jagg][iSpc_agg]; var NonX_ExPolMtx = CompositeBasis[jagg]; X_ExPolMtx.Allocate(NonX_ExPolMtx.Lengths); // should not reallocate if lengths stay the same; X_ExPolMtx.Multiply(1.0, NonX_ExPolMtx, B, 0.0, "imn", "imk", "kn"); } else { // no empty cell with respect to species 'iSpc_agg' in aggregate cell // --> non-XDG projector can be used. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ this.XCompositeBasis[jagg][iSpc_agg] = null; } } } } } }
/// <summary> /// /// </summary> /// <param name="jCell"> /// Local index of cell which should be recalculated. /// </param> /// <param name="AcceptedMask"> /// Bitmask which marks accepted cells - if any neighbor of /// <paramref name="jCell"/> is _accepted_, this defines a Dirichlet /// boundary; otherwise, the respective cell face is a free boundary. /// </param> /// <param name="Phi"> /// Input and output: /// - input for _accepted_ cells, i.e. Dirichlet boundary values /// - input and output for <paramref name="jCell"/>: an initial value for the iterative procedure, resp. on exit the result of the iteration. /// </param> /// <param name="gradPhi"> /// Auxillary variable to store the gradient of the level-set-field. /// </param> /// <returns></returns> public bool LocalSolve(int jCell, BitArray AcceptedMask, SinglePhaseField Phi, VectorField <SinglePhaseField> gradPhi) { Stpw_tot.Start(); int N = this.LevelSetBasis.GetLength(jCell); int i0G = this.LevelSetMapping.GlobalUniqueCoordinateIndex(0, jCell, 0); int i0L = this.LevelSetMapping.LocalUniqueCoordinateIndex(0, jCell, 0); double penaltyBase = ((double)(this.LevelSetBasis.Degree + 2)).Pow2(); double CellVolume = this.GridDat.Cells.GetCellVolume(jCell); int p = Phi.Basis.Degree; // subgrid on which we are working, consisting only of one cell SubGrid jCellGrid = new SubGrid(new CellMask(this.GridDat, Chunk.GetSingleElementChunk(jCell))); var VolScheme = new CellQuadratureScheme(domain: jCellGrid.VolumeMask); var EdgScheme = new EdgeQuadratureScheme(domain: jCellGrid.AllEdgesMask); //var VolRule = VolScheme.SaveCompile(GridDat, 3 * p); //var EdgRule = EdgScheme.SaveCompile(GridDat, 3 * p); // parameter list for operator DGField[] Params = new DGField[] { Phi }; gradPhi.ForEach(f => f.AddToArray(ref Params)); // build operator var comp = new EllipticReinitForm(AcceptedMask, jCell, penaltyBase, this.GridDat.Cells.cj); comp.LhsSwitch = 1.0; // matrix is constant -- Lhs Matrix only needs to be computed once comp.RhsSwitch = -1.0; // Rhs must be updated in every iteration var op = comp.Operator((DomDeg, ParamDeg, CodDeg) => 3 * p); // iteration loop: MultidimensionalArray Mtx = MultidimensionalArray.Create(N, N); double[] Rhs = new double[N]; double ChangeNorm = 0; int iIter; for (iIter = 0; iIter < 100; iIter++) { // update gradient gradPhi.Clear(jCellGrid.VolumeMask); gradPhi.Gradient(1.0, Phi, jCellGrid.VolumeMask); // assemble matrix and rhs { // clear for (int n = 0; n < N; n++) { if (iIter == 0) { m_LaplaceMatrix.ClearRow(i0G + n); } this.m_LaplaceAffine[i0L + n] = 0; } // compute matrix (only in iteration 0) and rhs if (iIter == 0) { Stpw_Mtx.Start(); } Stpw_Rhs.Start(); op.ComputeMatrixEx(this.LevelSetMapping, Params, this.LevelSetMapping, iIter == 0 ? this.m_LaplaceMatrix : null, this.m_LaplaceAffine, OnlyAffine: iIter > 0, volQuadScheme: VolScheme, edgeQuadScheme: EdgScheme, //volRule: VolRule, edgeRule: EdgRule, ParameterMPIExchange: false); //op.Internal_ComputeMatrixEx(this.GridDat, // this.LevelSetMapping, Params, this.LevelSetMapping, // iIter == 0 ? this.m_LaplaceMatrix : default(MsrMatrix), this.m_LaplaceAffine, iIter > 0, // 0.0, // EdgRule, VolRule, // null, false); if (iIter == 0) { Stpw_Mtx.Stop(); } Stpw_Rhs.Stop(); // extract matrix for 'jCell' for (int n = 0; n < N; n++) { #if DEBUG int Lr; int[] row_cols = null; double[] row_vals = null; Lr = this.m_LaplaceMatrix.GetRow(i0G + n, ref row_cols, ref row_vals); for (int lr = 0; lr < Lr; lr++) { int ColIndex = row_cols[lr]; double Value = row_vals[lr]; Debug.Assert((ColIndex >= i0G && ColIndex < i0G + N) || (Value == 0.0), "Matrix is expected to be block-diagonal."); } #endif if (iIter == 0) { for (int m = 0; m < N; m++) { Mtx[n, m] = this.m_LaplaceMatrix[i0G + n, i0G + m]; } } else { #if DEBUG for (int m = 0; m < N; m++) { Debug.Assert(Mtx[n, m] == this.m_LaplaceMatrix[i0G + n, i0G + m]); } #endif } Rhs[n] = -this.m_LaplaceAffine[i0L + n]; } } // solve double[] sol = new double[N]; Mtx.Solve(sol, Rhs); ChangeNorm = GenericBlas.L2Dist(sol, Phi.Coordinates.GetRow(jCell)); Phi.Coordinates.SetRow(jCell, sol); if (ChangeNorm / CellVolume < 1.0e-10) { break; } } //Console.WriteLine("Final change norm: {0}, \t iter: {1}", ChangeNorm, iIter ); if (ChangeNorm > 1.0e-6) { Console.WriteLine(" local solver funky in cell: " + jCell + ", last iteration change norm = " + ChangeNorm); } Stpw_tot.Stop(); return(true); }
/// <summary> /// Returns the minimum and the maximum value of <paramref name="mod"/>(this DG field), for each cell; /// </summary> /// <param name="max"> /// Vector, with the same number of entries as the cell mask <paramref name="cm"/>; /// On exit, the approximate local maximum within the cell. /// </param> /// <param name="min"> /// Vector, with the same number of entries as the cell mask <paramref name="cm"/>; /// On exit, the approximate local minimum within the cell. /// </param> /// <param name="cm"> /// optional domain restriction /// </param> /// <param name="mod"> /// optimal modifier, which e.g. may select the absolute value; if null, the identity function; /// </param> public void GetCellwiseExtremalValues <T1, T2>(T1 min, T2 max, CellMask cm = null, Func <double, double> mod = null) where T1 : IList <double> where T2 : IList <double> // { using (new FuncTrace()) { int J = Basis.GridDat.iLogicalCells.NoOfLocalUpdatedCells; int Jcm = cm == null ? J : cm.NoOfItemsLocally; if (min.Count != Jcm) { throw new ArgumentException("wrong length of output vector", "min"); } if (max.Count != Jcm) { throw new ArgumentException("wrong length of output vector", "max"); } min.SetAll(double.MaxValue); max.SetAll(double.MinValue); if (mod == null) { mod = (x => x); } //int N = m_context.Grid.GridSimplex.NoOfVertices + 1; // find maximum on this processor // ------------------------------ // create node set if (m_ExtremalProbeNS == null) { // nodes for the evaluation of the velocity vector // (all vertices an 0) int D = Basis.GridDat.SpatialDimension; var KrefS = Basis.GridDat.iGeomCells.RefElements; m_ExtremalProbeNS = new NodeSet[KrefS.Length]; for (int i = 0; i < KrefS.Length; i++) { m_ExtremalProbeNS[i] = new NodeSet(KrefS[i], KrefS[i].Vertices); } } // vectorisation of this method int VectorSize = -1; int N0 = m_ExtremalProbeNS[0].NoOfNodes; // number of nodes MultidimensionalArray fieldValues = new MultidimensionalArray(2); IEnumerable <Chunk> all_chunks; if (cm == null) { var _ch = new Chunk[1]; _ch[0].i0 = 0; _ch[0].Len = J; all_chunks = _ch; } else { all_chunks = cm; } int jSub = 0; foreach (Chunk chk in all_chunks) { VectorSize = this.GridDat.iGeomCells.GetNoOfSimilarConsecutiveCells(CellInfo.RefElementIndex_Mask, chk.i0, Math.Min(100, chk.Len)); // try to be a little vectorized; int _J = chk.Len + chk.i0; for (int j0 = chk.i0; j0 < _J; j0 += VectorSize) { if (j0 + VectorSize > _J) { VectorSize = _J - j0; } int iKref = Basis.GridDat.iGeomCells.GetRefElementIndex(j0); int N = m_ExtremalProbeNS[iKref].NoOfNodes; if (fieldValues.GetLength(0) != VectorSize || fieldValues.GetLength(1) != N) { fieldValues = MultidimensionalArray.Create(VectorSize, N); } this.Evaluate(j0, VectorSize, m_ExtremalProbeNS[iKref], fieldValues, 0.0); // loop over cells ... for (int jCell = j0; jCell < j0 + VectorSize; jCell++) { // loop over nodes ... for (int n = 0; n < N; n++) { double vel = 0; vel = mod(fieldValues[jCell - j0, n]); min[jSub] = Math.Min(min[jSub], vel); max[jSub] = Math.Max(max[jSub], vel); } jSub++; } } } } }
public override void ProlongateToFullGrid <T, V>(T FullGridVector, V AggGridVector) { var fullMapping = new UnsetteledCoordinateMapping(this.XDGBasis); if (FullGridVector.Count != fullMapping.LocalLength) { throw new ArgumentException("mismatch in vector length", "FullGridVector"); } int L = this.LocalDim; if (AggGridVector.Count != L) { throw new ArgumentException("mismatch in vector length", "AggGridVector"); } var ag = this.AggGrid; var agCls = ag.iLogicalCells.AggregateCellToParts; int JAGG = ag.iLogicalCells.NoOfLocalUpdatedCells; int Nmax = this.XDGBasis.MaximalLength; int N = this.DGBasis.Length; Debug.Assert(Nmax % N == 0); var FulCoords = new double[N]; var AggCoords = new double[N]; for (int jAgg = 0; jAgg < JAGG; jAgg++) // loop over all composite cells... { int[] agCl = agCls[jAgg]; int K = agCl.Length; if (this.SpeciesIndexMapping[jAgg] == null) { Debug.Assert(this.XCompositeBasis[jAgg] == null); int i0 = jAgg * Nmax; // index offset into 'AggGridVector' for (int n = 0; n < N; n++) { AggCoords[n] = AggGridVector[n + i0]; } for (int k = 0; k < K; k++) // loop over the cells wich form the aggregated cell... { int jCell = agCl[k]; int j0 = fullMapping.LocalUniqueCoordinateIndex(0, jCell, 0); MultidimensionalArray Trf = base.CompositeBasis[jAgg].ExtractSubArrayShallow(k, -1, -1); //Trf.Solve(FulCoords, AggCoords); Trf.GEMV(1.0, AggCoords, 0.0, FulCoords); for (int n = 0; n < N; n++) { FullGridVector[j0 + n] = FulCoords[n]; } } } else { int NoSpc = this.NoOfSpecies[jAgg]; int[,] sim = SpeciesIndexMapping[jAgg]; Debug.Assert(sim.GetLength(0) == NoSpc); Debug.Assert(sim.GetLength(1) == K); for (int iSpcAgg = 0; iSpcAgg < NoSpc; iSpcAgg++) { int i0 = jAgg * Nmax + iSpcAgg * N; // index offset into 'AggGridVector' for (int n = 0; n < N; n++) { AggCoords[n] = AggGridVector[n + i0]; } for (int k = 0; k < K; k++) // loop over the cells wich form the aggregated cell... { int jCell = agCl[k]; int iSpcBase = sim[iSpcAgg, k]; if (iSpcBase < 0) { continue; } int j0 = fullMapping.LocalUniqueCoordinateIndex(0, jCell, iSpcBase * N); MultidimensionalArray Trf; if (this.XCompositeBasis[jAgg] == null || this.XCompositeBasis[jAgg][iSpcAgg] == null) { Trf = base.CompositeBasis[jAgg].ExtractSubArrayShallow(k, -1, -1); } else { Trf = this.XCompositeBasis[jAgg][iSpcAgg].ExtractSubArrayShallow(k, -1, -1); } Trf.GEMV(1.0, AggCoords, 0.0, FulCoords); for (int n = 0; n < N; n++) { FullGridVector[j0 + n] = FulCoords[n]; } } } } } }
void INonlinEdgeform_GradV.BoundaryEdge(ref EdgeFormParams efp, MultidimensionalArray[] Uin, MultidimensionalArray[] GradUin, MultidimensionalArray f) { int L = efp.Len; Debug.Assert(f.GetLength(0) == L); int K = f.GetLength(1); // no of nodes per cell int D = efp.GridDat.SpatialDimension; int _NOParams = this.ParameterOrdering == null ? 0 : this.ParameterOrdering.Count; Debug.Assert(_NOParams == efp.ParameterVars_IN.Length); int _NOargs = this.ArgumentOrdering.Count; Debug.Assert(_NOargs == Uin.Length); Debug.Assert(_NOargs == GradUin.Length); CommonParamsBnd cpv; cpv.GridDat = efp.GridDat; cpv.Parameters_IN = new double[_NOParams]; cpv.Normale = new double[D]; cpv.X = new double[D]; cpv.time = efp.time; double[] _GradV_in = new double[D]; double[,] _GradU_in = new double[_NOargs, D]; double[] _U_in = new double[_NOargs]; double _V_in = 0.0; byte[] EdgeTags = efp.GridDat.iGeomEdges.EdgeTags; for (int l = 0; l < L; l++) // loop over cells... { cpv.iEdge = efp.e0 + l; cpv.EdgeTag = EdgeTags[cpv.iEdge]; for (int k = 0; k < K; k++) // loop over nodes... { for (int np = 0; np < _NOParams; np++) { cpv.Parameters_IN[np] = efp.ParameterVars_IN[np][l, k]; } for (int d = 0; d < D; d++) { cpv.Normale[d] = efp.Normals[l, k, d]; cpv.X[d] = efp.NodesGlobal[l, k, d]; } for (int na = 0; na < _NOargs; na++) { if (Uin[na] != null) { _U_in[na] = Uin[na][l, k]; } else { _U_in[na] = 0; } if (GradUin[na] != null) { for (int d = 0; d < D; d++) { _GradU_in[na, d] = GradUin[na][l, k, d]; } } else { for (int d = 0; d < D; d++) { _GradU_in[na, d] = 0; } } } for (int d = 0; d < D; d++) { _GradV_in[d] = 1; f[l, k, d] += edgeForm.BoundaryEdgeForm(ref cpv, _U_in, _GradU_in, _V_in, _GradV_in); _GradV_in[d] = 0; } } } }
void INonlinVolumeForm_V.Form(ref VolumFormParams prm, MultidimensionalArray[] U, MultidimensionalArray[] GradU, MultidimensionalArray f) { int L = prm.Len; Debug.Assert(f.GetLength(0) == L); int K = f.GetLength(1); // no of nodes per cell int D = prm.GridDat.SpatialDimension; int _NOParams = this.ParameterOrdering == null ? 0 : this.ParameterOrdering.Count; Debug.Assert(_NOParams == prm.ParameterVars.Length); int _NOargs = this.ArgumentOrdering.Count; Debug.Assert(_NOargs == U.Length); Debug.Assert(_NOargs == GradU.Length); CommonParamsVol cpv; cpv.GridDat = prm.GridDat; cpv.Parameters = new double[_NOParams]; cpv.Xglobal = new double[D]; cpv.time = prm.time; double[] _GradV = new double[D]; double[,] _GradU = new double[_NOargs, D]; double[] _U = new double[_NOargs]; double _V = 1.0; for (int l = 0; l < L; l++) // loop over cells... { cpv.jCell = prm.j0 + l; for (int k = 0; k < K; k++) // loop over nodes... { for (int np = 0; np < _NOParams; np++) { cpv.Parameters[np] = prm.ParameterVars[np][l, k]; } for (int d = 0; d < D; d++) { cpv.Xglobal[d] = prm.Xglobal[l, k, d]; } for (int na = 0; na < _NOargs; na++) { if (U[na] != null) { _U[na] = U[na][l, k]; } if (GradU[na] != null) { for (int d = 0; d < D; d++) { _GradU[na, d] = GradU[na][l, k, d]; } } } f[l, k] += volForm.VolumeForm(ref cpv, _U, _GradU, _V, _GradV); } } }
void INonlinVolumeForm_GradV.Form(ref VolumFormParams prm, MultidimensionalArray[] U, MultidimensionalArray[] GradU, MultidimensionalArray f) { int L = prm.Len; Debug.Assert(f.GetLength(0) == L); int K = f.GetLength(1); // no of nodes per cell int D = prm.GridDat.SpatialDimension; int _NOParams = this.ParameterOrdering == null ? 0 : this.ParameterOrdering.Count; Debug.Assert(_NOParams == prm.ParameterVars.Length); int _NOargs = this.ArgumentOrdering.Count; Debug.Assert(_NOargs == U.Length); Debug.Assert(_NOargs == GradU.Length); CommonParamsVol cpv; cpv.GridDat = prm.GridDat; cpv.Parameters = new double[_NOParams]; cpv.Xglobal = new double[D]; cpv.time = prm.time; double[] _GradV = new double[D]; double[,] _GradU = new double[_NOargs, D]; double[] _U = new double[_NOargs]; double _V = 0.0; //unsafe { // fixed(double* pParameters = cpv.Parameters, p_U = _U, p_GradU = _GradU, p_GradV = _GradV) { //bool* pUisNull = stackalloc bool[_NOargs]; //bool* pGradUisNull = stackalloc bool[_NOargs]; //for(int na = 0; na < _NOargs; na++) { // pUisNull[na] = (U[na] != null); // pGradUisNull[na] = (GradU[na] != null); //} // unsafe opt bringt hier relativ wenig/nix for (int l = 0; l < L; l++) // loop over cells... { cpv.jCell = prm.j0 + l; for (int k = 0; k < K; k++) // loop over nodes... { for (int d = 0; d < D; d++) { cpv.Xglobal[d] = prm.Xglobal[l, k, d]; } for (int np = 0; np < _NOParams; np++) { cpv.Parameters[np] = prm.ParameterVars[np][l, k]; } /* * bool* ppUisNull = pUisNull; * bool* ppGradUisNull = pGradUisNull; * double* pp_U = p_U, pp_GradU = p_GradU; * for(int na = 0; na < _NOargs; na++) { * if(*ppUisNull) { * pp_U = U[na][l, k]; * } else { * pp_U = double.NaN; * } * pp_U++; * if(*ppGradUisNull) { * for(int d = 0; d < D; d++) { * pp_GradU = GradU[na][l, k, d]; * pp_GradU++; * } * } else { * for(int d = 0; d < D; d++) { * pp_GradU = double.NaN; * pp_GradU++; * } * } * ppUisNull++; * ppGradUisNull++; * } */ for (int na = 0; na < _NOargs; na++) { if (U[na] != null) { _U[na] = U[na][l, k]; } else { _U[na] = double.NaN; } if (GradU[na] != null) { for (int d = 0; d < D; d++) { _GradU[na, d] = GradU[na][l, k, d]; } } else { for (int d = 0; d < D; d++) { _GradU[na, d] = double.NaN; } } } /* * double* pp_GradV = p_GradV; * for(int d = 0; d < D; d++) { * pp_GradV = 1.0; * f[l, k, d] += volForm.VolumeForm(ref cpv, _U, _GradU, _V, _GradV); * pp_GradV = 0.0; * pp_GradV++; * } */ for (int d = 0; d < D; d++) { _GradV[d] = 1.0; f[l, k, d] += volForm.VolumeForm(ref cpv, _U, _GradU, _V, _GradV); _GradV[d] = 0.0; } } } }
void INonlinEdgeform_GradV.InternalEdge(ref EdgeFormParams efp, MultidimensionalArray[] Uin, MultidimensionalArray[] Uout, MultidimensionalArray[] GradUin, MultidimensionalArray[] GradUout, MultidimensionalArray fin, MultidimensionalArray fot, bool adiaWall) { int L = efp.Len; Debug.Assert(fin.GetLength(0) == L); Debug.Assert(fot.GetLength(0) == L); int K = fin.GetLength(1); // no of nodes per cell int D = efp.GridDat.SpatialDimension; int _NOParams = this.ParameterOrdering == null ? 0 : this.ParameterOrdering.Count; Debug.Assert(_NOParams == efp.ParameterVars_IN.Length); Debug.Assert(_NOParams == efp.ParameterVars_OUT.Length); int _NOargs = this.ArgumentOrdering.Count; Debug.Assert(_NOargs == Uin.Length); Debug.Assert(_NOargs == GradUin.Length); Debug.Assert(_NOargs == Uout.Length); Debug.Assert(_NOargs == GradUout.Length); CommonParams cpv; cpv.GridDat = efp.GridDat; cpv.Parameters_IN = new double[_NOParams]; cpv.Parameters_OUT = new double[_NOParams]; cpv.Normale = new double[D]; cpv.X = new double[D]; cpv.time = efp.time; double[] _GradV_in = new double[D]; double[,] _GradU_in = new double[_NOargs, D]; double[] _U_in = new double[_NOargs]; double _V_in = 0.0; double[] _GradV_ot = new double[D]; double[,] _GradU_ot = new double[_NOargs, D]; double[] _U_ot = new double[_NOargs]; double _V_ot = 0.0; for (int l = 0; l < L; l++) // loop over cells... { cpv.iEdge = efp.e0 + l; for (int k = 0; k < K; k++) // loop over nodes... { for (int np = 0; np < _NOParams; np++) { cpv.Parameters_IN[np] = efp.ParameterVars_IN[np][l, k]; cpv.Parameters_OUT[np] = efp.ParameterVars_OUT[np][l, k]; } for (int d = 0; d < D; d++) { cpv.Normale[d] = efp.Normals[l, k, d]; cpv.X[d] = efp.NodesGlobal[l, k, d]; } for (int na = 0; na < _NOargs; na++) { Debug.Assert((Uin[na] != null) == (Uout[na] != null)); if (Uin[na] != null) { _U_in[na] = Uin[na][l, k]; _U_ot[na] = Uout[na][l, k]; } else { _U_in[na] = 0; _U_ot[na] = 0; } Debug.Assert((GradUin[na] != null) == (GradUout[na] != null)); if (GradUin[na] != null) { for (int d = 0; d < D; d++) { _GradU_in[na, d] = GradUin[na][l, k, d]; _GradU_ot[na, d] = GradUout[na][l, k, d]; } } else { for (int d = 0; d < D; d++) { _GradU_in[na, d] = 0; _GradU_ot[na, d] = 0; } } } for (int d = 0; d < D; d++) { _GradV_in[d] = 1; fin[l, k, d] += edgeForm.InnerEdgeForm(ref cpv, _U_in, _U_ot, _GradU_in, _GradU_ot, _V_in, _V_ot, _GradV_in, _GradV_ot); _GradV_in[d] = 0; _GradV_ot[d] = 1; fot[l, k, d] += edgeForm.InnerEdgeForm(ref cpv, _U_in, _U_ot, _GradU_in, _GradU_ot, _V_in, _V_ot, _GradV_in, _GradV_ot); _GradV_ot[d] = 0; } } } }
/// <summary> /// Spatial operator matrix analysis method /// </summary> public void SpatialOperatorMatrixAnalysis(bool CheckAssertions, int AnalysisLevel) { using (var solver = new Rheology()) { int D = solver.Grid.SpatialDimension; if (AnalysisLevel < 0 || AnalysisLevel > 2) { throw new ArgumentException(); } BlockMsrMatrix OpMatrix; double[] OpAffine; solver.AssembleMatrix(out OpMatrix, out OpAffine, solver.CurrentSolution.Mapping.ToArray(), true); // ============================= // AnalysisLevel 0 // ============================= { var OpMatrixT = OpMatrix.Transpose(); CoordinateVector TestVec = new CoordinateVector(solver.CurrentSolution.Mapping.Fields.Select(f => f.CloneAs()).ToArray()); double testsumPos = 0.0; double testsumNeg = 0.0; for (int rnd_seed = 0; rnd_seed < 20; rnd_seed++) { // fill the pressure components of the test vector TestVec.Clear(); Random rnd = new Random(rnd_seed); DGField Pressack = TestVec.Mapping.Fields[D] as DGField; int J = solver.GridData.iLogicalCells.NoOfLocalUpdatedCells; for (int j = 0; j < J; j++) { int N = Pressack.Basis.GetLength(j); for (int n = 0; n < N; n++) { Pressack.Coordinates[j, n] = rnd.NextDouble(); } } // Gradient times P: double[] R1 = new double[TestVec.Count]; OpMatrix.SpMV(1.0, TestVec, 0.0, R1); // R1 = Grad * P //Console.WriteLine("L2 of 'Grad * P': " + R1.L2Norm()); // transpose of Divergence times P: double[] R2 = new double[TestVec.Count]; OpMatrix.SpMV(1.0, TestVec, 0.0, R2); // R2 = divT * P //Console.WriteLine("L2 of 'divT * P': " + R2.L2Norm()); TestVec.Clear(); TestVec.Acc(1.0, R1); TestVec.Acc(1.0, R2); // analyze! testsumNeg += GenericBlas.L2Dist(R1, R2); R2.ScaleV(-1.0); testsumPos += GenericBlas.L2Dist(R1, R2); } Console.WriteLine("Pressure/Divergence Symmetry error in all tests (+): " + testsumPos); Console.WriteLine("Pressure/Divergence Symmetry error in all tests (-): " + testsumNeg); if (CheckAssertions) { Assert.LessOrEqual(Math.Abs(testsumNeg), testsumPos * 1.0e-13); } } // ============================= // AnalysisLevel 1 and 2 // ============================= if (AnalysisLevel > 0) { AggregationGridBasis[][] MgBasis = AggregationGridBasis.CreateSequence(solver.MultigridSequence, solver.CurrentSolution.Mapping.BasisS); MultigridOperator mgOp = new MultigridOperator(MgBasis, solver.CurrentSolution.Mapping, OpMatrix, null, solver.MultigridOperatorConfig); // extract //////////// MsrMatrix FullMatrix = mgOp.OperatorMatrix.ToMsrMatrix(); MsrMatrix DiffMatrix; { int[] VelVarIdx = D.ForLoop(d => d); int[] USubMatrixIdx_Row = mgOp.Mapping.GetSubvectorIndices(VelVarIdx); int[] USubMatrixIdx_Col = mgOp.Mapping.GetSubvectorIndices(VelVarIdx); int L = USubMatrixIdx_Row.Length; DiffMatrix = new MsrMatrix(L, L, 1, 1); FullMatrix.WriteSubMatrixTo(DiffMatrix, USubMatrixIdx_Row, default(int[]), USubMatrixIdx_Col, default(int[])); double DiffMatrix_sd = DiffMatrix.SymmetryDeviation(); Console.WriteLine("Diffusion assymetry:" + DiffMatrix_sd); } MsrMatrix SaddlePointMatrix; { int[] VelPVarIdx = new int[] { 0, 1, 2 }; int[] VelPSubMatrixIdx_Row = mgOp.Mapping.GetSubvectorIndices(VelPVarIdx); int[] VelPSubMatrixIdx_Col = mgOp.Mapping.GetSubvectorIndices(VelPVarIdx); int L = VelPSubMatrixIdx_Row.Length; SaddlePointMatrix = new MsrMatrix(L, L, 1, 1); FullMatrix.WriteSubMatrixTo(SaddlePointMatrix, VelPSubMatrixIdx_Row, default(int[]), VelPSubMatrixIdx_Col, default(int[])); } //SaddlePointMatrix.SaveToTextFileSparse("C:\\Users\\kikker\\Documents\\MATLAB\\spm.txt"); MsrMatrix ConstitutiveMatrix; { int[] StressVarIdx = new int[] { 3, 4, 5 }; int[] StressSubMatrixIdx_Row = mgOp.Mapping.GetSubvectorIndices(StressVarIdx); int[] StressSubMatrixIdx_Col = mgOp.Mapping.GetSubvectorIndices(StressVarIdx); int L = StressSubMatrixIdx_Row.Length; ConstitutiveMatrix = new MsrMatrix(L, L, 1, 1); FullMatrix.WriteSubMatrixTo(ConstitutiveMatrix, StressSubMatrixIdx_Row, default(int[]), StressSubMatrixIdx_Col, default(int[])); } // operator analysis ////////////////////// bool posDef; if (AnalysisLevel > 1) { // +++++++++++++++++++++++++++++++ // check condition number, etc // +++++++++++++++++++++++++++++++ MultidimensionalArray ret = MultidimensionalArray.Create(1, 5); Console.WriteLine("Calling MATLAB/Octave..."); using (BatchmodeConnector bmc = new BatchmodeConnector()) { bmc.PutSparseMatrix(FullMatrix, "FullMatrix"); bmc.PutSparseMatrix(SaddlePointMatrix, "SaddlePointMatrix"); bmc.PutSparseMatrix(ConstitutiveMatrix, "ConstitutiveMatrix"); bmc.PutSparseMatrix(DiffMatrix, "DiffMatrix"); bmc.Cmd("DiffMatrix = 0.5*(DiffMatrix + DiffMatrix');"); bmc.Cmd("condNoFullMatrix = condest(FullMatrix);"); bmc.Cmd("condNoSaddlePointMatrix = condest(SaddlePointMatrix);"); bmc.Cmd("condNoConstitutiveMatrix = condest(ConstitutiveMatrix);"); bmc.Cmd("condNoDiffMatrix = condest(DiffMatrix);"); //bmc.Cmd("eigiMaxiSaddle = 1.0; % eigs(SaddlePointMatrix,1,'lm')"); //bmc.Cmd("eigiMiniSaddle = 1.0; % eigs(SaddlePointMatrix,1,'sm')"); //bmc.Cmd("eigiMaxiConst = 1.0; % eigs(ConstitutiveMatrix,1,'lm')"); //bmc.Cmd("eigiMiniConst = 1.0; % eigs(ConstitutiveMatrix,1,'sm')"); //bmc.Cmd("eigiMaxiDiff = 1.0; % eigs(DiffMatrix,1,'lm')"); //bmc.Cmd("eigiMiniDiff = 1.0; % eigs(DiffMatrix,1,'sm')"); bmc.Cmd("lasterr"); bmc.Cmd("[V,r]=chol(SaddlePointMatrix);"); bmc.Cmd("[V,r]=chol(ConstitutiveMatrix);"); bmc.Cmd("ret = [condNoFullMatrix, condNoSaddlePointMatrix, condNoConstitutiveMatrix, condNoDiffMatrix, r]"); //eigiMaxiSaddle, eigiMiniSaddle, eigiMaxiConst, eigiMiniConst, eigiMaxiDiff, eigiMiniDiff, bmc.GetMatrix(ret, "ret"); bmc.Execute(false); } double condNoFullMatrix = ret[0, 0]; double condNoSaddlePMatrix = ret[0, 1]; double condNoConstitutiveMatrix = ret[0, 2]; double condNoDiffMatrix = ret[0, 3]; //double eigiMaxiSaddle = ret[0, 4]; //double eigiMiniSaddle = ret[0, 5]; //double eigiMaxiConst = ret[0, 6]; //double eigiMiniConst = ret[0, 7]; //double eigiMaxiDiff = ret[0, 8]; //double eigiMiniDiff = ret[0, 9]; posDef = ret[0, 4] == 0; //Console.WriteLine("Eigenvalue range of saddle point matrix: {0} to {1}", eigiMiniSaddle, eigiMaxiSaddle); //Console.WriteLine("Eigenvalue range of constitutive matrix: {0} to {1}", eigiMiniConst, eigiMaxiConst); //Console.WriteLine("Eigenvalue range of diffusion matrix: {0} to {1}", eigiMiniDiff, eigiMaxiDiff); Console.WriteLine("Condition number full operator: {0:0.####E-00}", condNoFullMatrix); Console.WriteLine("Condition number saddle point operator: {0:0.####E-00}", condNoSaddlePMatrix); Console.WriteLine("Condition number constitutive operator: {0:0.####E-00}", condNoConstitutiveMatrix); Console.WriteLine("Condition number diffusion operator: {0:0.####E-00}", condNoDiffMatrix); //base.QueryHandler.ValueQuery("ConditionNumber", condNoFullMatrix); } else { // +++++++++++++++++++++++++++++++++++++++ // test only for positive definiteness // +++++++++++++++++++++++++++++++++++++++ var SaddlePMatrixFull = SaddlePointMatrix.ToFullMatrixOnProc0(); var ConstMatrixFull = ConstitutiveMatrix.ToFullMatrixOnProc0(); posDef = true; try { SaddlePMatrixFull.Cholesky(); } catch (ArithmeticException) { posDef = false; } posDef = true; try { ConstMatrixFull.Cholesky(); } catch (ArithmeticException) { posDef = false; } } double SaddlePSymm = SaddlePointMatrix.SymmetryDeviation(); Console.WriteLine("Symmetry deviation of saddle point matrix: " + SaddlePSymm); if (posDef) { Console.WriteLine("Good news: Saddle point operator matrix seems to be positive definite."); } else { Console.WriteLine("WARNING: Saddle point operator matrix is not positive definite."); } double ConstSymm = ConstitutiveMatrix.SymmetryDeviation(); Console.WriteLine("Symmetry deviation of constitutive matrix: " + ConstSymm); if (posDef) { Console.WriteLine("Good news: constitutive operator matrix seems to be positive definite."); } else { Console.WriteLine("WARNING: constitutive operator matrix is not positive definite."); } //if (CheckAssertions) { // if (Control.AdvancedDiscretizationOptions.ViscosityMode == ViscosityMode.FullySymmetric && Control.PhysicalParameters.IncludeConvection == false) { // Assert.IsTrue(posDef, "Positive definiteness test failed."); // double compVal = DiffMatrix.InfNorm() * 1e-13; // Assert.LessOrEqual(DiffSymm, compVal, "Diffusion matrix seems to be non-symmetric."); // } //} } } }
public void Solve <U, V>(U X, V B) where U : IList <double> where V : IList <double> // { int L = B.Count; if (X.Count != this.m_mgop.OperatorMatrix.ColPartition.LocalLength) { throw new ArgumentException("Wrong length of unknowns vector.", "X"); } if (B.Count != this.m_mgop.OperatorMatrix.RowPartitioning.LocalLength) { throw new ArgumentException("Wrong length of RHS vector.", "B"); } MultidimensionalArray H = MultidimensionalArray.Create(MaxKrylovDim + 1, MaxKrylovDim); double[] X0 = X.ToArray(); double[] R0 = new double[B.Count]; List <double[]> Vau = new List <double[]>(); List <double[]> Zed = new List <double[]>(); int iPrecond = 0; // counter which iterates through preconditioners int iIter = 0; while (true) { // init for Arnoldi // ----------------- R0.SetV(B); this.m_mgop.OperatorMatrix.SpMV(-1.0, X0, 1.0, R0); if (this.IterationCallback != null) { this.IterationCallback(iIter, X0.CloneAs(), R0.CloneAs(), this.m_mgop); } // termination condition if (iIter > MaxIter) { break; } double beta = R0.L2NormPow2().MPISum().Sqrt(); Vau.Add(R0.CloneAs()); Vau[0].ScaleV(1.0 / beta); // inner iteration (Arnoldi) // -------------------------- for (int j = 0; j < MaxKrylovDim; j++) { Debug.Assert(Vau.Count == Zed.Count + 1); double[] Zj = new double[L]; this.PrecondS[iPrecond].Solve(Zj, Vau[j]); iPrecond++; if (iPrecond >= this.PrecondS.Length) { iPrecond = 0; } iIter++; // we count preconditioner calls as iterations Zed.Add(Zj); double[] W = new double[L]; this.m_mgop.OperatorMatrix.SpMV(1.0, Zj, 0.0, W); for (int i = 0; i <= j; i++) { double hij = GenericBlas.InnerProd(W, Vau[i]).MPISum(); H[i, j] = hij; W.AccV(-hij, Vau[i]); } double wNorm = W.L2NormPow2().MPISum().Sqrt(); H[j + 1, j] = wNorm; W.ScaleV(1.0 / wNorm); // W is now Vau[j + 1] !! Vau.Add(W); Debug.Assert(Vau.Count == Zed.Count + 1); } // compute minimized-Residual solution over 'Zed'-Vectors // ------------------------------------------------------- double[] alpha; { alpha = new double[MaxKrylovDim]; //var alpha2 = new double[MaxKrylovDim]; Debug.Assert(Vau.Count == H.NoOfRows); Debug.Assert(Zed.Count == H.NoOfCols); // solve small minimization problem double[] minimiRHS = new double[MaxKrylovDim + 1]; minimiRHS[0] = beta; H.LeastSquareSolve(alpha, minimiRHS); // using LAPACK DGELSY //H.CloneAs().LeastSquareSolve(alpha2, minimiRHS.CloneAs()); //var Q = H; // //var Qt = H.Transpose(); //var lhs = Qt.GEMM(Q); //var rhs = new double[Qt.NoOfRows]; //Qt.gemv(1.0, minimiRHS, 0.0, rhs); //lhs.Solve(alpha, rhs); alpha.ClearEntries(); alpha[0] = beta; } for (int i = 0; i < MaxKrylovDim; i++) { X0.AccV(alpha[i], Zed[i]); } // now, X0 = 'old X0' + sum(Z[i]*alpha[i]), // i.e. X0 is the new X for the next iteration // restart // ------- Vau.Clear(); Zed.Clear(); H.Clear(); } }
/// <summary> /// Calculates the drag (x-component) and lift (y-component) forces acting on a wall of a boundary fitted grid /// </summary> static public double[] GetForces_BoundaryFitted(VectorField <SinglePhaseField> GradU, VectorField <SinglePhaseField> GradV, SinglePhaseField StressXX, SinglePhaseField StressXY, SinglePhaseField StressYY, SinglePhaseField P, LevelSetTracker LsTrk, double muA, double beta) { int D = LsTrk.GridDat.SpatialDimension; if (D > 2) { throw new ArgumentException("Method GetForces_BoundaryFitted only implemented for 2D (viscoelastic)!"); } // var UA = U.Select(u => u.GetSpeciesShadowField("A")).ToArray(); //var UA = U.ToArray(); MultidimensionalArray Grad_U = new MultidimensionalArray(D); var _GradU = GradU.ToArray(); var _GradV = GradV.ToArray(); int RequiredOrder = _GradU[0].Basis.Degree * 3 + 2; //int RequiredOrder = U[0].Basis.Degree * 3 + 2; //int RequiredOrder = LsTrk.GetXQuadFactoryHelper(momentFittingVariant).GetCachedSurfaceOrders(0).Max(); //Console.WriteLine("Order reduction: {0} -> {1}", _RequiredOrder, RequiredOrder); //if (RequiredOrder > agg.HMForder) // throw new ArgumentException(); Console.WriteLine(); Console.WriteLine("Forces coeff: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder); SinglePhaseField _StressXX = StressXX; SinglePhaseField _StressXY = StressXY; SinglePhaseField _StressYY = StressYY; SinglePhaseField pA = null; //pA = P.GetSpeciesShadowField("A"); pA = P; double[] forces = new double[D]; for (int d = 0; d < D; d++) { ScalarFunctionEx ErrFunc = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) { int K = result.GetLength(1); // No nof Nodes MultidimensionalArray Grad_URes = MultidimensionalArray.Create(Len, K, D); MultidimensionalArray Grad_VRes = MultidimensionalArray.Create(Len, K, D); MultidimensionalArray pARes = MultidimensionalArray.Create(Len, K); MultidimensionalArray StressXXRes = MultidimensionalArray.Create(Len, K); MultidimensionalArray StressXYRes = MultidimensionalArray.Create(Len, K); MultidimensionalArray StressYYRes = MultidimensionalArray.Create(Len, K); var Normals = LsTrk.GridDat.Edges.NormalsCache.GetNormals_Edge(Ns, j0, Len); //var Normals = MultidimensionalArray.Create(1, Ns.Length, 1); //var Normals = LsTrk.GridDat.Edges.NormalsForAffine; for (int i = 0; i < D; i++) { _GradU[i].EvaluateEdge(j0, Len, Ns, Grad_URes.ExtractSubArrayShallow(-1, -1, i), Grad_URes.ExtractSubArrayShallow(-1, -1, i), ResultIndexOffset: 0, ResultPreScale: 1); _GradV[i].EvaluateEdge(j0, Len, Ns, Grad_VRes.ExtractSubArrayShallow(-1, -1, i), Grad_VRes.ExtractSubArrayShallow(-1, -1, i), ResultIndexOffset: 0, ResultPreScale: 1); //UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1), 0, 1); } //pA.Evaluate(j0, Len, Ns, pARes); pA.EvaluateEdge(j0, Len, Ns, pARes, pARes, ResultIndexOffset: 0, ResultPreScale: 1); _StressXX.EvaluateEdge(j0, Len, Ns, StressXXRes, StressXXRes, ResultIndexOffset: 0, ResultPreScale: 1); _StressXY.EvaluateEdge(j0, Len, Ns, StressXYRes, StressXYRes, ResultIndexOffset: 0, ResultPreScale: 1); _StressYY.EvaluateEdge(j0, Len, Ns, StressYYRes, StressYYRes, ResultIndexOffset: 0, ResultPreScale: 1); //if (LsTrk.GridDat.SpatialDimension == 2) //{ for (int j = 0; j < Len; j++) { for (int k = 0; k < K; k++) { double acc = 0.0; // pressure switch (d) { case 0: acc += pARes[j, k] * Normals[j, k, 0]; acc -= (2 * muA * beta) * Grad_URes[j, k, 0] * Normals[j, k, 0]; acc -= (muA * beta) * Grad_URes[j, k, 1] * Normals[j, k, 1]; acc -= (muA * beta) * Grad_VRes[j, k, 0] * Normals[j, k, 1]; acc -= (muA) * StressXXRes[j, k] * Normals[j, k, 0]; acc -= (muA) * StressXYRes[j, k] * Normals[j, k, 1]; break; case 1: acc += pARes[j, k] * Normals[j, k, 1]; acc -= (2 * muA * beta) * Grad_VRes[j, k, 1] * Normals[j, k, 1]; acc -= (muA * beta) * Grad_VRes[j, k, 0] * Normals[j, k, 0]; acc -= (muA * beta) * Grad_URes[j, k, 1] * Normals[j, k, 0]; acc -= (muA) * StressXYRes[j, k] * Normals[j, k, 0]; acc -= (muA) * StressYYRes[j, k] * Normals[j, k, 1]; break; default: throw new NotImplementedException(); } result[j, k] = acc; } } }; var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper; //EdgeMask Mask = new EdgeMask(LsTrk.GridDat, "Wall_bottom"); EdgeMask Mask = new EdgeMask(LsTrk.GridDat, "Wall_cylinder"); EdgeQuadratureScheme eqs = SchemeHelper.GetEdgeQuadScheme(LsTrk.GetSpeciesId("A"), IntegrationDomain: Mask); EdgeQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat, eqs.Compile(LsTrk.GridDat, RequiredOrder), // agg.HMForder), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { ErrFunc(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { forces[d] += ResultsOfIntegration[i, 0]; } } ).Execute(); } for (int i = 0; i < D; i++) { forces[i] = MPI.Wrappers.MPIExtensions.MPISum(forces[i]); } return(forces); }
/// <summary> /// <see cref="INonlinearFlux.InnerEdgeFlux"/> /// </summary> public override void InnerEdgeFlux( double time, int jEdge, MultidimensionalArray x, MultidimensionalArray normal, MultidimensionalArray[] Uin, MultidimensionalArray[] Uout, int Offset, int Length, MultidimensionalArray Output) { int NoOfNodes = Uin[0].GetLength(1); int D = CompressibleEnvironment.NumberOfDimensions; double gamma = this.material.EquationOfState.HeatCapacityRatio; double Mach = this.material.MachNumber; double MachScaling = gamma * Mach * Mach; for (int e = 0; e < Length; e++) { for (int n = 0; n < NoOfNodes; n++) { double densityIn = Uin[0][e + Offset, n]; double densityOut = Uout[0][e + Offset, n]; double momentumSquareIn = 0.0; double momentumSquareOut = 0.0; double normalVelocityIn = 0.0; double normalVelocityOut = 0.0; for (int d = 0; d < D; d++) { momentumSquareIn += Uin[d + 1][e + Offset, n] * Uin[d + 1][e + Offset, n]; momentumSquareOut += Uout[d + 1][e + Offset, n] * Uout[d + 1][e + Offset, n]; normalVelocityIn += Uin[d + 1][e + Offset, n] * normal[e + Offset, n, d]; normalVelocityOut += Uout[d + 1][e + Offset, n] * normal[e + Offset, n, d]; } normalVelocityIn /= densityIn; normalVelocityOut /= densityOut; double energyIn = Uin[D + 1][e + Offset, n]; double energyOut = Uout[D + 1][e + Offset, n]; double pIn = (gamma - 1.0) * (energyIn - MachScaling * 0.5 * momentumSquareIn / densityIn); double pOut = (gamma - 1.0) * (energyOut - MachScaling * 0.5 * momentumSquareOut / densityOut); //pIn = Math.Max(pIn, ilPSP.Utils.BLAS.MachineEps); //pOut = Math.Max(pOut, ilPSP.Utils.BLAS.MachineEps); double speedOfSoundIn = Math.Sqrt(pIn / densityIn) / Mach; double speedOfSoundOut = Math.Sqrt(pOut / densityOut) / Mach; Debug.Assert(!double.IsNaN(speedOfSoundIn) || double.IsInfinity(speedOfSoundIn)); Debug.Assert(!double.IsNaN(speedOfSoundOut) || double.IsInfinity(speedOfSoundOut)); double densityMean = 0.5 * (densityIn + densityOut); double pressureMean = 0.5 * (pIn + pOut); double speedOfSoundMean = 0.5 * (speedOfSoundIn + speedOfSoundOut); double velocityJump = normalVelocityOut - normalVelocityIn; // Calculate the pressure estimate at the edge and use it to // calculate the components of the correction factor qIn and qOut double pStar = pressureMean - 0.5 * MachScaling * velocityJump * speedOfSoundMean * densityMean; pStar = Math.Max(0.0, pStar); double qIn = 1.0; if (pStar > pIn) { qIn = Math.Sqrt(1.0 + 0.5 * (gamma + 1.0) * (pStar / pIn - 1.0) / gamma); } double qOut = 1.0; if (pStar > pOut) { qOut = Math.Sqrt(1.0 + 0.5 * (gamma + 1.0) * (pStar / pOut - 1.0) / gamma); } // Determine the wave speeds double waveSpeedIn = normalVelocityIn - speedOfSoundIn * qIn; double waveSpeedOut = normalVelocityOut + speedOfSoundOut * qOut; double cIn = densityIn * (waveSpeedIn - normalVelocityIn); double cOut = densityOut * (waveSpeedOut - normalVelocityOut); // cf. Toro2009, equation 10.70 double speedDiff = cOut * normalVelocityOut - cIn * normalVelocityIn; //if (Math.Abs(speedDiff) < 1e-13) { // speedDiff = 0.0; //} double pIn_minus_pOut = pIn - pOut; //if (Math.Abs(pIn_minus_pOut) < 1e-13) { // pIn_minus_pOut = 0.0; //} double intermediateWaveSpeed = (speedDiff + pIn_minus_pOut / MachScaling) / (cOut - cIn); //double intermediateWaveSpeed = // (cOut * normalVelocityOut - cIn * normalVelocityIn + (pIn - pOut) / MachScaling) / // (cOut - cIn); double edgeFlux = 0.0; // cf. Toro2009, equation 10.71 if (intermediateWaveSpeed > 0.0) { edgeFlux = normalVelocityIn * densityIn; if (waveSpeedIn <= 0.0) { double modifiedDensity = densityIn * (waveSpeedIn - normalVelocityIn) / (waveSpeedIn - intermediateWaveSpeed); edgeFlux += waveSpeedIn * (modifiedDensity - densityIn); } } else { edgeFlux = normalVelocityOut * densityOut; if (waveSpeedOut >= 0.0) { double modifiedDensity = densityOut * (waveSpeedOut - normalVelocityOut) / (waveSpeedOut - intermediateWaveSpeed); edgeFlux += waveSpeedOut * (modifiedDensity - densityOut); } } Debug.Assert(!double.IsNaN(edgeFlux) || double.IsInfinity(edgeFlux)); Output[e + Offset, n] += edgeFlux; } } }
public IEnumerable <IChunkRulePair <QuadRule> > GetQuadRuleSet(ExecutionMask mask, int order) { if (mask.MaskType != MaskType.Geometrical) { throw new ArgumentException("Expecting a geometrical mask."); } var standardVolumeRules = baseFactory.GetQuadRuleSet(mask, order); var pointRules = rootFactory.GetQuadRuleSet(mask, order); var result = new List <ChunkRulePair <QuadRule> >(); foreach (var chunkRulePair in standardVolumeRules) { foreach (int cell in chunkRulePair.Chunk.Elements) { QuadRule standardRule = chunkRulePair.Rule; var pointRule = pointRules.Single(pair => pair.Chunk.i0 <= cell && pair.Chunk.JE > cell).Rule; MultidimensionalArray gradientsAtRoots = tracker.DataHistories[0].Current.GetLevelSetGradients(pointRule.Nodes, cell, 1); QuadRule modifiedRule; switch (pointRule.NoOfNodes) { case 0: case 1: { // Cell not really cut MultidimensionalArray levelSetValue = tracker.DataHistories[0].Current.GetLevSetValues( new NodeSet(RefElement, new double[2]), cell, 1); if (Math.Sign(levelSetValue.Storage[0]) < 0) { // Cell is completely void QuadRule emptyRule = QuadRule.CreateEmpty(RefElement, 1, 2); emptyRule.Nodes.LockForever(); modifiedRule = emptyRule; } else { // Cell is completely non-void modifiedRule = standardRule; } } break; case 2: { double a, b, c; GetLevelSetApproximationCofficients(cell, pointRule.Nodes.GetRow(0), pointRule.Nodes.GetRow(1), out a, out b, out c); double[] eqcv = Heqpol_coefficients(a, b, c); modifiedRule = standardRule.CloneAs(); for (int i = 0; i < modifiedRule.NoOfNodes; i++) { double x = modifiedRule.Nodes[i, 0]; double y = modifiedRule.Nodes[i, 1]; // double[] v = new double[] { // 1.0, x, x * x, y, x * y, y * y }; double v = eqcv[0] + eqcv[1] * x + eqcv[2] * x * x + eqcv[3] * y + eqcv[4] * x * y + eqcv[5] * y * y; modifiedRule.Weights[i] *= v; } modifiedRule.Nodes.LockForever(); } break; case 4: { // Assume only single interface double[] xCoords = pointRule.Nodes.GetColumn(0); double maxXDist = xCoords.Max() - xCoords.Min(); double[] yCoords = pointRule.Nodes.GetColumn(1); double maxYDist = yCoords.Max() - yCoords.Min(); int orderingDirection; if (maxXDist > maxYDist) { orderingDirection = 0; } else { orderingDirection = 1; } double[][] roots = new double[pointRule.NoOfNodes][]; for (int i = 0; i < roots.Length; i++) { roots[i] = new double[] { pointRule.Nodes[i, 0], pointRule.Nodes[i, 1] }; } var orderedRoots = roots.OrderBy(t => t[orderingDirection]).ToArray(); // Now, do the equivalent polynomial thing double a, b, c; GetLevelSetApproximationCofficients(cell, orderedRoots[0], orderedRoots[1], out a, out b, out c); double[] eqcv1 = Heqpol_coefficients(a, b, c); GetLevelSetApproximationCofficients(cell, orderedRoots[2], orderedRoots[3], out a, out b, out c); double[] eqcv2 = Heqpol_coefficients(a, b, c); modifiedRule = standardRule.CloneAs(); for (int i = 0; i < modifiedRule.NoOfNodes; i++) { double x = modifiedRule.Nodes[i, 0]; double y = modifiedRule.Nodes[i, 1]; // double[] v = new double[] { // 1.0, x, x * x, y, x * y, y * y }; double v1 = eqcv1[0] + eqcv1[1] * x + eqcv1[2] * x * x + eqcv1[3] * y + eqcv1[4] * x * y + eqcv1[5] * y * y; double v2 = eqcv2[0] + eqcv2[1] * x + eqcv2[2] * x * x + eqcv2[3] * y + eqcv2[4] * x * y + eqcv2[5] * y * y; modifiedRule.Weights[i] *= v1 * v2; } } break; default: throw new NotImplementedException(); } result.Add(new ChunkRulePair <QuadRule>( Chunk.GetSingleElementChunk(cell), modifiedRule)); } } return(result); }
/// <summary> /// Returns the minimum and the maximum value of the DG field /// This is a collective call, it must be invoked by all /// MPI processes within the communicator; internally, it invokes MPI_Allreduce; /// </summary> /// <param name="max"> /// on all invoking MPI processes, the maximum value (over all processors) of /// this field; /// </param> /// <param name="min"> /// on all invoking MPI processes, the minimum value (over all processors) of /// this field; /// </param> /// <remarks> /// to find the maximum value, this field is evaluated on each vertex and the center of the simplex. /// </remarks> /// <param name="cm"> /// optional domain restriction /// </param> /// <param name="jMaxGlob"> /// global cell index in which the maximum value <paramref name="max"/> was found /// </param> /// <param name="jMinGlob"> /// global cell index in which the maximum value <paramref name="min"/> was found /// </param> public void GetExtremalValues(out double min, out double max, out int jMinGlob, out int jMaxGlob, CellMask cm = null) { MPICollectiveWatchDog.Watch(csMPI.Raw._COMM.WORLD); using (new FuncTrace()) { int J = Basis.GridDat.iLogicalCells.NoOfLocalUpdatedCells; // find maximum on this processor // ------------------------------ // create node set InitExtremalProbeNS(); // vectorisation of this method int VectorSize = -1; int N0 = m_ExtremalProbeNS[0].GetLength(0); // number of nodes MultidimensionalArray fieldValues = new MultidimensionalArray(2); IEnumerable <Chunk> all_chunks; if (cm == null) { var _ch = new Chunk[1]; _ch[0].i0 = 0; _ch[0].Len = J; all_chunks = _ch; } else { all_chunks = cm; } double LocMax = -double.MaxValue, LocMin = double.MaxValue; int jMinLoc = int.MaxValue, jMaxLoc = int.MaxValue; foreach (Chunk chk in all_chunks) { VectorSize = this.GridDat.iGeomCells.GetNoOfSimilarConsecutiveCells(CellInfo.RefElementIndex_Mask, chk.i0, Math.Min(100, chk.Len)); // try to be a little vectorized; int _J = chk.Len + chk.i0; for (int j = chk.i0; j < _J; j += VectorSize) { if (j + VectorSize > _J) { VectorSize = _J - j; } int iKref = Basis.GridDat.iGeomCells.GetRefElementIndex(j); int N = m_ExtremalProbeNS[iKref].GetLength(0); if (fieldValues.GetLength(0) != VectorSize || fieldValues.GetLength(1) != N) { fieldValues = MultidimensionalArray.Create(VectorSize, N); } this.Evaluate(j, VectorSize, m_ExtremalProbeNS[iKref], fieldValues, 0.0); // loop over cells ... for (int jj = j; jj < j + VectorSize; jj++) { // loop over nodes ... for (int n = 0; n < N; n++) { double vel = 0; vel = fieldValues[jj - j, n]; if (vel > LocMax) { LocMax = vel; jMaxLoc = jj; } if (vel < LocMin) { LocMin = vel; jMinLoc = jj; } } } } } // find the maximum over all processes via MPI and return // ------------------------------------------------------ if (Basis.GridDat.CellPartitioning.MpiSize > 1) { double[] total = new double[2]; double[] local = new double[] { LocMax, -LocMin }; unsafe { fixed(double *ploc = local, ptot = total) { csMPI.Raw.Allreduce((IntPtr)ploc, (IntPtr)ptot, 2, csMPI.Raw._DATATYPE.DOUBLE, csMPI.Raw._OP.MAX, csMPI.Raw._COMM.WORLD); } } max = total[0]; min = -total[1]; int i0 = Basis.GridDat.CellPartitioning.i0; int[] jGlob = new int[2]; if (max == LocMax) { // (at least one) global maximum on this processor jGlob[0] = jMaxLoc + i0; } else { // maximum on some other processor jGlob[0] = int.MaxValue; } if (min == LocMin) { // (at least one) global minimum on this processor jGlob[1] = jMinLoc + i0; } else { // minimum on some other processor jGlob[1] = int.MaxValue; } // in case of multiple global minimums/maximums, e.g. for a constant field, we return the lowest (jMaxGlob,jMinGlob) int[] jGlobM = new int[2]; unsafe { fixed(int *ploc = jGlob, ptot = jGlobM) { csMPI.Raw.Allreduce((IntPtr)ploc, (IntPtr)ptot, 2, csMPI.Raw._DATATYPE.INT, csMPI.Raw._OP.MIN, csMPI.Raw._COMM.WORLD); } } jMaxGlob = jGlob[0]; jMinGlob = jGlob[1]; } else { min = LocMin; max = LocMax; jMaxGlob = jMaxLoc; jMinGlob = jMinLoc; } } }
/// <summary> /// Vectorized implementation of <see cref="GetBoundaryState(double, Vector, Vector, StateVector)"/> /// </summary> public override void GetBoundaryState(MultidimensionalArray[] StateOut, double time, MultidimensionalArray X, MultidimensionalArray Normals, MultidimensionalArray[] StateIn, int Offset, int NoOfEdges, bool normalFlipped, Material material) { //Convection.OptimizedHLLCFlux.SupersonicInlet.Start(); if (X.Dimension != 3) { throw new ArgumentException(); } int D = X.GetLength(2); int NoOfNodes = X.GetLength(1); if (StateIn.Length != D + 2) { throw new ArgumentException(); } if (StateOut.Length != D + 2) { throw new ArgumentException(); } bool is3D = D >= 3; if (D < 2) { // base-implementation supports also 1D; // The implementation here is (a bit) tuned for performance, we only support 2D and 3D; // in 1D, performance is not so relevant anyway. base.GetBoundaryState(StateOut, time, X, Normals, StateIn, Offset, NoOfEdges, normalFlipped, material); return; } var Density = StateOut[0]; var Energy = StateOut[D + 1]; var MomentumX = StateOut[1]; var MomentumY = StateOut[2]; var MomentumZ = is3D ? StateOut[3] : null; var DensityIn = StateIn[0]; //var EnergyIn = StateIn[D + 1]; //var MomentumXin = StateIn[1]; //var MomentumYin = StateIn[2]; //var MomentumZin = is3D ? StateIn[3] : null; double MachScaling = material.EquationOfState.HeatCapacityRatio * material.MachNumber * material.MachNumber; double[] xLocal = new double[D]; //Vector uOut = new Vector(D); for (int e = 0; e < NoOfEdges; e++) { int edge = e + Offset; // Loop over nodes for (int n = 0; n < NoOfNodes; n++) { xLocal[0] = X[edge, n, 0]; xLocal[1] = X[edge, n, 1]; double uOut_x = VelocityFunctions[0](xLocal, time); double uOut_y = VelocityFunctions[1](xLocal, time); double uOut_z = 0.0; double velocity_AbsSquare = uOut_x * uOut_x + uOut_y * uOut_y; if (is3D) { xLocal[2] = X[edge, n, 2]; uOut_z = VelocityFunctions[2](xLocal, time); velocity_AbsSquare += uOut_z * uOut_z; } #if DEBUG var uOutVec = new Vector(D); uOutVec.x = uOut_x; uOutVec.y = uOut_y; uOutVec.z = uOut_z; StateVector stateBoundary = StateVector.FromPrimitiveQuantities( material, DensityFunction(xLocal, time), uOutVec, PressureFunction(xLocal, time)); #endif double density = DensityFunction(xLocal, time); double pressure = PressureFunction(xLocal, time); Density[edge, n] = density; MomentumX[edge, n] = uOut_x * density; MomentumY[edge, n] = uOut_y * density; if (is3D) { MomentumZ[edge, n] = uOut_z * density; } Energy[edge, n] = material.EquationOfState.GetInnerEnergy(density, pressure) + 0.5 * MachScaling * density * velocity_AbsSquare; #if DEBUG Debug.Assert(Density[edge, n].RelErrorSmallerEps(stateBoundary.Density), "density error"); for (int d = 0; d < D; d++) { Debug.Assert(StateOut[d + 1][edge, n].RelErrorSmallerEps(stateBoundary.Momentum[d]), "momentum error"); } Debug.Assert(Energy[edge, n].RelErrorSmallerEps(stateBoundary.Energy), "energy error"); #endif } } //Convection.OptimizedHLLCFlux.SupersonicInlet.Stop(); }
/// <summary> /// Integrand evaluation. /// </summary> protected override void Evaluate(int i0, int Length, QuadRule rule, MultidimensionalArray EvalResult) { NodeSet NodesUntransformed = rule.Nodes; int M = NodesUntransformed.GetLength(0); int D = NodesUntransformed.GetLength(1); // evaluate scalar function ans store result in 'EvalResult' // ========================================================= Debug.Assert(!((m_func != null) && (m_funcEx != null))); if (m_func != null || m_Map != null) { GridDat.TransformLocal2Global(NodesUntransformed, i0, Length, m_NodesTransformed, 0); } if (m_func != null) { MultidimensionalArray inp = m_NodesTransformed.ResizeShallow(new int[] { Length *M, D }); MultidimensionalArray outp = EvalResult.ResizeShallow(new int[] { Length *M }); m_func(inp, outp); Debug.Assert(m_funcEx == null); } if (m_funcEx != null) { m_funcEx(i0, Length, NodesUntransformed, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); Debug.Assert(m_func == null); } if (m_Map == null) { // L2 error branch // +++++++++++++++ MultidimensionalArray fieldvals = EvalResult.ResizeShallow(new int[] { Length, NodesUntransformed.GetLength(0) }); m_Owner.Evaluate(i0, Length, NodesUntransformed, fieldvals, -1.0); for (int j = 0; j < Length; j++) { for (int m = 0; m < M; m++) { double e; e = EvalResult[j, m, 0]; EvalResult[j, m, 0] = e * e; } } } else { // arbitrary mapping branch // ++++++++++++++++++++++++ MultidimensionalArray fieldvals = MultidimensionalArray.Create(new int[] { Length, NodesUntransformed.GetLength(0) }); m_Owner.Evaluate(i0, Length, NodesUntransformed, fieldvals, -1.0); double[] X = new double[D]; for (int j = 0; j < Length; j++) { for (int m = 0; m < M; m++) { double e; e = EvalResult[j, m, 0]; for (int d = 0; d < D; d++) { X[d] = m_NodesTransformed[j, m, d]; } EvalResult[j, m, 0] = this.m_Map(X, fieldvals[j, m], e); } } } }
static void AddToCellBoundaryRule(T cbqr, NodeSet nodes, MultidimensionalArray weights, int iFace, double scl) { Debug.Assert(nodes.GetLength(0) == weights.GetLength(0)); if (nodes.GetLength(0) <= 0) { return; } if (cbqr.Nodes == null) { cbqr.Nodes = nodes; Debug.Assert(cbqr.Weights == null); cbqr.Weights = weights.CloneAs(); cbqr.Weights.Scale(scl); cbqr.NumbersOfNodesPerFace[iFace] = nodes.GetLength(0); } else { int D = nodes.GetLength(1); Debug.Assert(D == cbqr.Nodes.GetLength(1)); int L1 = cbqr.Nodes.GetLength(0); int L2 = nodes.GetLength(0); NodeSet newNodes = new NodeSet(cbqr.Nodes.RefElement, L1 + L2, D); MultidimensionalArray newWeights = MultidimensionalArray.Create(L1 + L2); int K = 0; // total number of nodes on all faces; for (int k = 0; k < iFace; k++) { K += cbqr.NumbersOfNodesPerFace[k]; } if (K > 0) { newNodes.ExtractSubArrayShallow( new int[] { 0, 0 }, new int[] { K - 1, D - 1 }).Set( cbqr.Nodes.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { K - 1, D - 1 })); newWeights.ExtractSubArrayShallow( new int[] { 0 }, new int[] { K - 1 }).Set( cbqr.Weights.ExtractSubArrayShallow(new int[] { 0 }, new int[] { K - 1 })); } newNodes.ExtractSubArrayShallow(new int[] { K, 0 }, new int[] { K + L2 - 1, D - 1 }).Set(nodes); newWeights.ExtractSubArrayShallow(new int[] { K }, new int[] { K + L2 - 1 }).Acc(scl, weights); if (K < L1) { newNodes.ExtractSubArrayShallow( new int[] { K + L2, 0 }, new int[] { L1 + L2 - 1, D - 1 }).Set( cbqr.Nodes.ExtractSubArrayShallow(new int[] { K, 0 }, new int[] { L1 - 1, D - 1 })); newWeights.ExtractSubArrayShallow( new int[] { K + L2 }, new int[] { L1 + L2 - 1 }).Set( cbqr.Weights.ExtractSubArrayShallow(new int[] { K }, new int[] { L1 - 1 })); } cbqr.Nodes = newNodes; cbqr.Nodes.LockForever(); cbqr.Weights = newWeights; cbqr.NumbersOfNodesPerFace[iFace] += L2; } }
public override void RestictFromFullGrid <T, V>(T FullGridVector, V AggGridVector) { var fullMapping = new UnsetteledCoordinateMapping(this.XDGBasis); if (FullGridVector.Count != fullMapping.LocalLength) { throw new ArgumentException("mismatch in vector length", "FullGridVector"); } int L = this.LocalDim; if (AggGridVector.Count != L) { throw new ArgumentException("mismatch in vector length", "AggGridVector"); } var ag = this.AggGrid; var agCls = ag.iLogicalCells.AggregateCellToParts; int JAGG = ag.iLogicalCells.NoOfLocalUpdatedCells; int Nmax = this.XDGBasis.MaximalLength; int N = this.DGBasis.Length; Debug.Assert(Nmax % N == 0); var Buffer = MultidimensionalArray.Create(agCls.Max(cc => cc.Length), N); var AggCoords = MultidimensionalArray.Create(N); for (int jAgg = 0; jAgg < JAGG; jAgg++) // loop over all composite cells... { int[] agCl = agCls[jAgg]; int K = agCl.Length; MultidimensionalArray FulCoords = (K * N == Buffer.Length) ? Buffer : Buffer.ExtractSubArrayShallow(new int[] { 0, 0 }, new int[] { K - 1, N - 1 }); int i0Agg = jAgg * Nmax, i0Full; if (this.SpeciesIndexMapping[jAgg] == null) { // default branch: // use restiction/prolongation from un-cut basis // +++++++++++++++++++++++++++++++++++++++++++++ for (int k = 0; k < K; k++) // loop over the cells wich form the aggregated cell... { int jCell = agCl[k]; i0Full = jCell * Nmax; for (int n = 0; n < N; n++) { FulCoords[k, n] = FullGridVector[n + i0Full]; } } MultidimensionalArray Trf = base.CompositeBasis[jAgg]; AggCoords.Clear(); AggCoords.Multiply(1.0, Trf, FulCoords, 0.0, "n", "kmn", "km"); int _i0 = jAgg * N; for (int n = 0; n < N; n++) { AggGridVector[n + i0Agg] = AggCoords[n]; } } else { int NoSpc = this.NoOfSpecies[jAgg]; int[,] sim = SpeciesIndexMapping[jAgg]; Debug.Assert(sim.GetLength(0) == NoSpc); Debug.Assert(sim.GetLength(1) == K); for (int iSpcAgg = 0; iSpcAgg < NoSpc; iSpcAgg++) { for (int k = 0; k < K; k++) // loop over the cells wich form the aggregated cell... { int jCell = agCl[k]; int iSpcBase = sim[iSpcAgg, k]; if (iSpcBase < 0) { for (int n = 0; n < N; n++) { FulCoords[k, n] = 0; } } else { i0Full = fullMapping.LocalUniqueCoordinateIndex(0, jCell, iSpcBase * N); for (int n = 0; n < N; n++) { FulCoords[k, n] = FullGridVector[i0Full + n]; } } } MultidimensionalArray Trf; if (this.XCompositeBasis[jAgg] == null || this.XCompositeBasis[jAgg][iSpcAgg] == null) { Trf = base.CompositeBasis[jAgg]; } else { Trf = this.XCompositeBasis[jAgg][iSpcAgg]; } AggCoords.Clear(); AggCoords.Multiply(1.0, Trf, FulCoords, 0.0, "n", "kmn", "km"); for (int n = 0; n < N; n++) { AggGridVector[i0Agg + iSpcAgg * N + n] = AggCoords[n]; } } } } }
public void GetNormalsForCell(NodeSet Nodes, int jCell, int iFace, MultidimensionalArray NormalsOut, MultidimensionalArray QuadMetric, int Offset) { m_Owner.ParentGrid.iGeomEdges.GetNormalsForCell(Nodes, jCell, iFace, NormalsOut, QuadMetric, Offset); }
public override void GetRestrictionMatrix(BlockMsrMatrix RST, MultigridMapping mgMap, int iF) { if (!object.ReferenceEquals(mgMap.AggBasis[iF], this)) { throw new ArgumentException(); } //MsrMatrix RST = new MsrMatrix(mgMap.Partitioning, mgMap.ProblemMapping); int JAGG = this.AggGrid.iLogicalCells.NoOfLocalUpdatedCells; int[] degrees = mgMap.DgDegree; int NoFld = degrees.Length; int N_rest; // = new int[NoFld]; int N_full; // = new int[NoFld]; { BoSSS.Foundation.Basis b = mgMap.ProblemMapping.BasisS[iF]; BoSSS.Foundation.Basis NxB = (b is BoSSS.Foundation.XDG.XDGBasis) ? ((BoSSS.Foundation.XDG.XDGBasis)b).NonX_Basis : b; N_rest = NxB.Polynomials[0].Where(poly => poly.AbsoluteDegree <= degrees[iF]).Count(); N_full = NxB.Length; } int mgMap_Offset = mgMap.Partitioning.i0; for (int jAgg = 0; jAgg < JAGG; jAgg++) { int[] AgCell = this.AggGrid.iLogicalCells.AggregateCellToParts[jAgg]; int K = AgCell.Length; int NoSpc_Agg = this.NoOfSpecies[jAgg]; // number of species in aggregate cell for (int iSpc_Agg = 0; iSpc_Agg < NoSpc_Agg; iSpc_Agg++) // loop over all species in aggregate cell { { // loop over DG fields in the mapping int NROW = N_rest; int NCOL = N_full; Debug.Assert(mgMap.AggBasis[iF].GetLength(jAgg, degrees[iF]) == N_rest * NoSpc_Agg); int i0Agg_Loc = mgMap.LocalUniqueIndex(iF, jAgg, N_rest * iSpc_Agg); int i0Agg = i0Agg_Loc + mgMap_Offset; Debug.Assert(i0Agg >= mgMap.Partitioning.i0); Debug.Assert(i0Agg < mgMap.Partitioning.iE); if (this.SpeciesIndexMapping[jAgg] == null) { Debug.Assert(NoSpc_Agg == 1); Debug.Assert(NoSpc_Agg == 1); // default branch: // use restriction/prolongation from un-cut basis // +++++++++++++++++++++++++++++++++++++++++++++ MultidimensionalArray Trf = base.CompositeBasis[jAgg]; for (int k = 0; k < K; k++) // loop over the cells which form the aggregated cell... { int jCell = AgCell[k]; int i0Full = mgMap.ProblemMapping.GlobalUniqueCoordinateIndex(iF, jCell, 0); var Block = Trf.ExtractSubArrayShallow(k, -1, -1); for (int nRow = 0; nRow < NROW; nRow++) { for (int nCol = 0; nCol < NCOL; nCol++) { RST[i0Agg + nRow, i0Full + nCol] = Block[nCol, nRow]; } } } } else { int NoSpc = this.NoOfSpecies[jAgg]; int[,] sim = SpeciesIndexMapping[jAgg]; Debug.Assert(sim.GetLength(0) == NoSpc); Debug.Assert(sim.GetLength(1) == K); MultidimensionalArray Trf; if (this.XCompositeBasis[jAgg] == null || this.XCompositeBasis[jAgg][iSpc_Agg] == null) { Trf = base.CompositeBasis[jAgg]; } else { Trf = this.XCompositeBasis[jAgg][iSpc_Agg]; } for (int k = 0; k < K; k++) // loop over the cells which form the aggregated cell... { int jCell = AgCell[k]; int iSpcBase = sim[iSpc_Agg, k]; if (iSpcBase < 0) { //for(int n = 0; n < N; n++) // FulCoords[k, n] = 0; } else { int i0Full = mgMap.ProblemMapping.GlobalUniqueCoordinateIndex(iF, jCell, iSpcBase * N_full); var Block = Trf.ExtractSubArrayShallow(k, -1, -1); for (int nRow = 0; nRow < NROW; nRow++) { for (int nCol = 0; nCol < NCOL; nCol++) { RST[i0Agg + nRow, i0Full + nCol] = Block[nCol, nRow]; } } } } } } } } //return RST; }
/// <summary> /// Computes the maximum admissible step-size according to /// GassnerEtAl2008, equation 67. /// </summary> /// <param name="i0"></param> /// <param name="Length"></param> /// <returns></returns> protected override double GetCFLStepSize(int i0, int Length) { int iKref = gridData.Cells.GetRefElementIndex(i0); int noOfNodesPerCell = base.EvaluationPoints[iKref].NoOfNodes; double scaling = Math.Max(4.0 / 3.0, config.EquationOfState.HeatCapacityRatio / config.PrandtlNumber); DGField artificialViscosity = workingSet.ParameterFields.Where(c => c.Identification.Equals(Variables.ArtificialViscosity)).Single(); double cfl = double.MaxValue; switch (speciesMap) { case ImmersedSpeciesMap ibmMap: { MultidimensionalArray levelSetValues = ibmMap.Tracker.DataHistories[0].Current.GetLevSetValues(base.EvaluationPoints[iKref], i0, Length); SpeciesId species = ibmMap.Tracker.GetSpeciesId(ibmMap.Control.FluidSpeciesName); var hMinArray = ibmMap.CellAgglomeration.CellLengthScales[species]; for (int i = 0; i < Length; i++) { int cell = i0 + i; double hminlocal = hMinArray[cell]; double nu = artificialViscosity.GetMeanValue(cell) / config.ReynoldsNumber; Debug.Assert(!double.IsNaN(nu), "IBM ArtificialViscosityCFLConstraint: nu is NaN"); bool setCFL = false; for (int node = 0; node < noOfNodesPerCell; node++) { if (levelSetValues[i, node].Sign() != (double)ibmMap.Control.FluidSpeciesSign) { continue; } else if (setCFL == false) { setCFL = true; } } if (nu != 0 && setCFL) { double cflCell = hminlocal * hminlocal / scaling / nu; Debug.Assert(!double.IsNaN(cflCell), "Could not determine CFL number"); cfl = Math.Min(cfl, cflCell); } } } break; default: { for (int i = 0; i < Length; i++) { int cell = i0 + i; double hminlocal = gridData.Cells.h_min[cell]; double nu = artificialViscosity.GetMeanValue(cell) / config.ReynoldsNumber; Debug.Assert(!double.IsNaN(nu), "ArtificialViscosityCFLConstraint: nu is NaN"); if (nu != 0) { double cflCell = hminlocal * hminlocal / scaling / nu; Debug.Assert(!double.IsNaN(cflCell), "Could not determine CFL number"); cfl = Math.Min(cfl, cflCell); } } } break; } if (cfl == double.MaxValue) { return(cfl); } else { int degree = workingSet.ConservativeVariables.Max(f => f.Basis.Degree); int twoNPlusOne = 2 * degree + 1; return(cfl * GetBetaMax(degree) / twoNPlusOne / twoNPlusOne / Math.Sqrt(CNSEnvironment.NumberOfDimensions)); } }
/// <summary> /// ctor. /// </summary> public EllipticReinitForm(BitArray _AcceptedBitmask, int __jCell, double __penaltyBase, MultidimensionalArray __cj) { this.AcceptedBitmask = _AcceptedBitmask; this.penaltyBase = __penaltyBase; this.jCell = __jCell; this.cj = __cj; if (this.AcceptedBitmask[this.jCell]) { throw new ArgumentException("Cannot work on accepted cells."); } }
public void DefineMatrix(IMutableMatrixEx M) { FullMatrix = M.ToFullMatrixOnProc0(); }
/// <summary> /// Accumulates <paramref name="Block"/>*<paramref name="alpha"/> to this matrix, /// at the row/column offset <paramref name="i0"/> resp. <paramref name="j0"/>. /// </summary> /// <param name="i0">Row offset.</param> /// <param name="j0">Column offset.</param> /// <param name="alpha">Scaling factor for the accumulation operation.</param> /// <param name="Block">Block to accumulate.</param> public void AccBlock(int i0, int j0, double alpha, MultidimensionalArray Block) { this.AccBlock(i0, j0, alpha, Block, 1.0); }
public void Dispose() { FullMatrix = null; }
private QuadRule CombineQr(QuadRule qrEdge, CellBoundaryQuadRule givenRule, int iFace) { int D = grd.SpatialDimension; var volSplx = m_cellBndQF.RefElement; int coD = D - 1; Debug.Assert(this.RefElement.SpatialDimension == coD); // extract edge rule // ----------------- int i0 = 0, iE = 0; for (int i = 0; i < iFace; i++) { i0 += givenRule.NumbersOfNodesPerFace[i]; } iE = i0 + givenRule.NumbersOfNodesPerFace[iFace] - 1; if (iE < i0) { // rule is empty (measure is zero). if (qrEdge == null) { QuadRule ret = new QuadRule(); ret.OrderOfPrecision = int.MaxValue - 1; ret.Nodes = new NodeSet(this.RefElement, 1, Math.Max(1, D - 1)); ret.Weights = MultidimensionalArray.Create(1); // this is an empty rule, since the weight is zero! // (rules with zero nodes may cause problems at various places.) return(ret); } else { qrEdge.Nodes.Scale(0.5); qrEdge.Weights.Scale(0.5); return(qrEdge); } } MultidimensionalArray NodesVol = givenRule.Nodes.ExtractSubArrayShallow(new int[] { i0, 0 }, new int[] { iE, D - 1 }); MultidimensionalArray Weigts = givenRule.Weights.ExtractSubArrayShallow(new int[] { i0 }, new int[] { iE }).CloneAs(); NodeSet Nodes = new NodeSet(this.RefElement, iE - i0 + 1, coD); volSplx.GetInverseFaceTrafo(iFace).Transform(NodesVol, Nodes); Nodes.LockForever(); //Debug.Assert((Weigts.Sum() - grd.Grid.GridSimplex.EdgeSimplex.Volume).Abs() < 1.0e-6, "i've forgotten the gramian"); // combine // ------- if (qrEdge == null) { // no rule defined yet - just set the one we have got // ++++++++++++++++++++++++++++++++++++++++++++++++++ qrEdge = new QuadRule(); qrEdge.Weights = Weigts; qrEdge.Nodes = Nodes; qrEdge.OrderOfPrecision = givenRule.OrderOfPrecision; } else { // take the mean of already defined and new rule // +++++++++++++++++++++++++++++++++++++++++++++ int L1 = qrEdge.Nodes.GetLength(0); int L2 = Nodes.GetLength(0); Debug.Assert(coD == qrEdge.Nodes.GetLength(1)); NodeSet newNodes = new NodeSet(this.RefElement, L1 + L2, coD); newNodes.SetSubArray(qrEdge.Nodes, new int[] { 0, 0 }, new int[] { L1 - 1, coD - 1 }); newNodes.SetSubArray(Nodes, new int[] { L1, 0 }, new int[] { L1 + L2 - 1, coD - 1 }); newNodes.LockForever(); MultidimensionalArray newWeights = MultidimensionalArray.Create(L1 + L2); newWeights.AccSubArray(0.5, qrEdge.Weights, new int[] { 0 }, new int[] { L1 - 1 }); newWeights.AccSubArray(0.5, Weigts, new int[] { L1 }, new int[] { L1 + L2 - 1 }); double oldSum = qrEdge.Weights.Sum(); double newSum = Weigts.Sum(); WeightInbalance += Math.Abs(oldSum - newSum); qrEdge.Nodes = newNodes; qrEdge.Weights = newWeights; qrEdge.OrderOfPrecision = Math.Min(qrEdge.OrderOfPrecision, givenRule.OrderOfPrecision); } // return // ------ return(qrEdge); }
/// <summary> /// Calculates the Torque around the center of mass /// </summary> /// <param name="U"></param> /// <param name="P"></param> /// <param name="momentFittingVariant"></param> /// <param name="muA"></param> /// <param name="particleRadius"></param> /// <returns></returns> static public void GetCellValues(VectorField <XDGField> U, XDGField P, double muA, double particleRadius, SinglePhaseField P_atIB, SinglePhaseField gradU_atIB, SinglePhaseField gradUT_atIB) { var LsTrk = U[0].Basis.Tracker; int D = LsTrk.GridDat.SpatialDimension; var UA = U.Select(u => u.GetSpeciesShadowField("A")).ToArray(); if (D > 2) { throw new NotImplementedException("Currently only 2D cases supported"); } int RequiredOrder = U[0].Basis.Degree * 3 + 2; //if (RequiredOrder > agg.HMForder) // throw new ArgumentException(); Console.WriteLine("Cell values calculated by: {0}, order = {1}", LsTrk.CutCellQuadratureType, RequiredOrder); ConventionalDGField pA = null; double circumference = new double(); pA = P.GetSpeciesShadowField("A"); for (int n = 0; n < 4; n++) { ScalarFunctionEx ErrFunc_CellVal = delegate(int j0, int Len, NodeSet Ns, MultidimensionalArray result) { int K = result.GetLength(1); // No nof Nodes MultidimensionalArray Grad_UARes = MultidimensionalArray.Create(Len, K, D, D);; MultidimensionalArray pARes = MultidimensionalArray.Create(Len, K); // Evaluate tangential velocity to level-set surface var Normals = LsTrk.DataHistories[0].Current.GetLevelSetNormals(Ns, j0, Len); for (int i = 0; i < D; i++) { UA[i].EvaluateGradient(j0, Len, Ns, Grad_UARes.ExtractSubArrayShallow(-1, -1, i, -1)); } pA.Evaluate(j0, Len, Ns, pARes); for (int j = 0; j < Len; j++) { for (int k = 0; k < K; k++) { double acc = 0.0; double acc2 = 0.0; switch (n) { case 0: // Pressure part acc += pARes[j, k] * Normals[j, k, 0]; acc *= -Normals[j, k, 1] * particleRadius; acc2 += pARes[j, k] * Normals[j, k, 1]; acc2 *= Normals[j, k, 0] * particleRadius; result[j, k] = acc + acc2; break; case 1: // GradU part acc -= (1 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0]; // Attention was 2 times acc -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 1]; acc *= -Normals[j, k, 1] * particleRadius; acc2 -= (1 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1]; acc2 -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 0]; acc2 *= Normals[j, k, 0] * particleRadius; result[j, k] = acc + acc2; break; case 2: // GradU_T part acc -= (1 * muA) * Grad_UARes[j, k, 0, 0] * Normals[j, k, 0]; // Attention was 2 times acc -= (muA) * Grad_UARes[j, k, 1, 0] * Normals[j, k, 1]; acc *= -Normals[j, k, 1] * particleRadius; acc2 -= (1 * muA) * Grad_UARes[j, k, 1, 1] * Normals[j, k, 1]; // Attention was 2 times acc2 -= (muA) * Grad_UARes[j, k, 0, 1] * Normals[j, k, 0]; acc2 *= Normals[j, k, 0] * particleRadius; result[j, k] = acc + acc2; break; case 3: // Standardization with radians result[j, k] = 1; break; default: throw new NotImplementedException(); } } } }; var SchemeHelper = LsTrk.GetXDGSpaceMetrics(new[] { LsTrk.GetSpeciesId("A") }, RequiredOrder, 1).XQuadSchemeHelper; // new XQuadSchemeHelper(LsTrk, momentFittingVariant, ); CellQuadratureScheme cqs = SchemeHelper.GetLevelSetquadScheme(0, LsTrk.Regions.GetCutCellMask()); CellQuadrature.GetQuadrature(new int[] { 1 }, LsTrk.GridDat, cqs.Compile(LsTrk.GridDat, RequiredOrder), delegate(int i0, int Length, QuadRule QR, MultidimensionalArray EvalResult) { ErrFunc_CellVal(i0, Length, QR.Nodes, EvalResult.ExtractSubArrayShallow(-1, -1, 0)); }, delegate(int i0, int Length, MultidimensionalArray ResultsOfIntegration) { for (int i = 0; i < Length; i++) { switch (n) { case 0: P_atIB.SetMeanValue(i0, ResultsOfIntegration[i, 0]); break; case 1: gradU_atIB.SetMeanValue(i0, ResultsOfIntegration[i, 0]); break; case 2: gradUT_atIB.SetMeanValue(i0, ResultsOfIntegration[i, 0]); break; case 3: circumference += ResultsOfIntegration[i, 0]; P_atIB.SetMeanValue(i0, P_atIB.GetMeanValue(i0) / ResultsOfIntegration[i, 0]); gradU_atIB.SetMeanValue(i0, gradU_atIB.GetMeanValue(i0) / ResultsOfIntegration[i, 0]); gradUT_atIB.SetMeanValue(i0, gradUT_atIB.GetMeanValue(i0) / ResultsOfIntegration[i, 0]); break; default: throw new NotImplementedException(); } } } ).Execute(); } Console.WriteLine("Circle circumference: " + circumference); }