Example #1
0
        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);
            }
        }
Example #3
0
        /// <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);
        }
Example #6
0
        /// <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);
                }
            }
        }
Example #10
0
        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;
                    }
                }
            }
        }
Example #11
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.");
                    //    }
                    //}
                }
            }
        }
Example #13
0
        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();
            }
        }
Example #14
0
        /// <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);
        }
Example #15
0
        /// <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;
                }
            }
        }
Example #16
0
        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);
        }
Example #17
0
        /// <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;
                }
            }
        }
Example #18
0
        /// <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();
        }
Example #19
0
            /// <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;
            }
        }
Example #21
0
        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);
 }
Example #23
0
        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.");
     }
 }
Example #26
0
 public void DefineMatrix(IMutableMatrixEx M)
 {
     FullMatrix = M.ToFullMatrixOnProc0();
 }
Example #27
0
 /// <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);
 }
Example #28
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);
        }
Example #30
0
        /// <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);
        }