Example #1
0
        /// <summary>
        /// Projects a DG field <paramref name="source"/>, which may be defined on some different mesh,
        /// onto the DG field <paramref name="target"/>.
        /// </summary>
        static public void ProjectFromForeignGrid(this ConventionalDGField target, double alpha, ConventionalDGField source, CellQuadratureScheme scheme = null)
        {
            using (new FuncTrace()) {
                Console.WriteLine(string.Format("Projecting {0} onto {1}... ", source.Identification, target.Identification));
                int maxDeg       = Math.Max(target.Basis.Degree, source.Basis.Degree);
                var CompQuadRule = scheme.SaveCompile(target.GridDat, maxDeg * 3 + 3); // use over-integration
                int D            = target.GridDat.SpatialDimension;



                if (object.ReferenceEquals(source.GridDat, target.GridDat))
                {
                    // +++++++++++++++++
                    // equal grid branch
                    // +++++++++++++++++

                    target.ProjectField(alpha, source.Evaluate, CompQuadRule);
                }
                else
                {
                    // +++++++++++++++++++++
                    // different grid branch
                    // +++++++++++++++++++++

                    if (source.GridDat.SpatialDimension != D)
                    {
                        throw new ArgumentException("Spatial Dimension Mismatch.");
                    }

                    var eval = new FieldEvaluation(GridHelper.ExtractGridData(source.GridDat));


                    //
                    // Difficulty with MPI parallelism:
                    // While the different meshes may represent the same geometrical domain,
                    // their MPI partitioning may be different.
                    //
                    // Solution Approach: we circulate unlocated points among all MPI processes.
                    //

                    int MPIsize = target.GridDat.MpiSize;


                    // pass 1: collect all points
                    // ==========================
                    MultidimensionalArray allNodes = null;
                    void CollectPoints(MultidimensionalArray input, MultidimensionalArray output)
                    {
                        Debug.Assert(input.Dimension == 2);
                        Debug.Assert(input.NoOfCols == D);

                        if (allNodes == null)
                        {
                            allNodes = input.CloneAs();
                        }
                        else
                        {
                            /*
                             * var newNodes = MultidimensionalArray.Create(allNodes.NoOfRows + input.NoOfRows, D);
                             * newNodes.ExtractSubArrayShallow(new[] { 0, 0 }, new[] { allNodes.NoOfRows - 1, D - 1 })
                             *  .Acc(1.0, allNodes);
                             * newNodes.ExtractSubArrayShallow(new[] {  allNodes.NoOfRows, 0 }, new[] { newNodes.NoOfRows - 1, D - 1 })
                             *  .Acc(1.0, allNodes);
                             */
                            allNodes = allNodes.CatVert(input);
                        }
                        Debug.Assert(allNodes.NoOfCols == D);
                    }

                    target.ProjectField(alpha, CollectPoints, CompQuadRule);

                    int L = allNodes != null?allNodes.GetLength(0) : 0;

                    // evaluate
                    // ========

                    //allNodes = MultidimensionalArray.Create(2, 2);
                    //allNodes[0, 0] = -1.5;
                    //allNodes[0, 1] = 2.0;
                    //allNodes[1, 0] = -0.5;
                    //allNodes[1, 1] = 2.0;
                    //L = 2;
                    var Res           = L > 0 ? MultidimensionalArray.Create(L, 1) : default(MultidimensionalArray);
                    int NoOfUnlocated = eval.EvaluateParallel(1.0, new DGField[] { source }, allNodes, 0.0, Res);

                    int TotalNumberOfUnlocated = NoOfUnlocated.MPISum();
                    if (TotalNumberOfUnlocated > 0)
                    {
                        Console.Error.WriteLine($"WARNING: {TotalNumberOfUnlocated} unlocalized points in 'ProjectFromForeignGrid(...)'");
                    }

                    // perform the real projection
                    // ===========================


                    int lc = 0;
                    void ProjectionIntegrand(MultidimensionalArray input, MultidimensionalArray output)
                    {
                        Debug.Assert(input.Dimension == 2);
                        Debug.Assert(input.NoOfCols == D);

                        int LL = input.GetLength(0);

                        output.Set(Res.ExtractSubArrayShallow(new int[] { lc, 0 }, new int[] { lc + LL - 1, -1 }));
                        lc += LL;
                    }

                    target.ProjectField(alpha, ProjectionIntegrand, CompQuadRule);
                }
            }
        }