Ejemplo n.º 1
0
        public void InterpolateNodeTest()
        {
            string triMesh  = UnitTestHelper.TestDataDir + "odense_rough.mesh";
            string quadMesh = UnitTestHelper.TestDataDir + "odense_rough_quads.mesh";
            // Source mesh
            MeshFile  sourcemeshFile = MeshFile.ReadMesh(triMesh);
            SMeshData sourcemesh     = sourcemeshFile.ToSMeshData();

            sourcemesh.BuildDerivedData();
            // Target mesh
            MeshFile  targetMeshFile = MeshFile.ReadMesh(quadMesh);
            SMeshData targetmesh     = targetMeshFile.ToSMeshData();

            targetmesh.BuildDerivedData();

            MeshInterpolator2D interpolator = new MeshInterpolator2D(sourcemesh, MeshValueType.Nodes);

            interpolator.SetTarget(targetmesh, MeshValueType.Nodes);

            double[] target = new double[targetmesh.NumberOfNodes];
            interpolator.InterpolateNodeToTarget(sourcemesh.Z, target);

            Assert.False(target.Any(vv => vv == interpolator.DeleteValue));

            targetMeshFile.Z = target;
            targetMeshFile.Write(UnitTestHelper.TestDataDir + "test_odense_rough_quads-fromTri.mesh");
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Process the incoming mesh file names
        /// </summary>
        /// <param name="files">List of mesh file names to merge</param>
        /// <param name="fileBoundaryCodesToRemove">List of boundary codes to remove for each mesh. Must match the size of the files argument</param>
        public void Process(List <string> files, List <List <int> > fileBoundaryCodesToRemove = null)
        {
            // Extent of entire domain, all meshes
            Extent extent = new Extent();

            // Load all meshes
            List <MeshFile> meshes = new List <MeshFile>(files.Count);

            for (int i = 0; i < files.Count; i++)
            {
                MeshFile mesh = MeshFile.ReadMesh(files[i]);
                meshes.Add(mesh);
                for (int j = 0; j < mesh.NumberOfNodes; j++)
                {
                    extent.Include(mesh.X[j], mesh.Y[j]);
                }
            }
            // grow it a littl bit, in case of rounding errors
            extent.XMin = extent.XMin - NodeTolerance;
            extent.XMax = extent.XMax + NodeTolerance;
            extent.YMin = extent.YMin - NodeTolerance;
            extent.YMax = extent.YMax + NodeTolerance;

            // Initialize search tree
            _nodeSearchTree = new QuadSearchTree(extent);

            // Create new mesh nodes and elements
            for (int i = 0; i < files.Count; i++)
            {
                int        prevNodeMergeCount    = NodeMergeCount;
                List <int> boundaryCodesToRemove = fileBoundaryCodesToRemove != null ? fileBoundaryCodesToRemove[i] : null;
                AddMesh(meshes[i], boundaryCodesToRemove);
                if (i > 0)
                {
                    Console.Out.WriteLine("Mesh {0}, number of nodes merged in: {1}", i + 1, NodeMergeCount - prevNodeMergeCount);
                }
            }
            Console.Out.WriteLine("Total number of nodes merged in  : {0}", NodeMergeCount);

            RemoveInternalBoundaryCodes(_code, _connectivity);

            // Create new mesh file
            string      projection  = meshes[0].ProjectionString;
            eumQuantity eumQuantity = meshes[0].EumQuantity;

            MeshBuilder builder = new MeshBuilder();

            builder.SetNodes(_x.ToArray(), _y.ToArray(), _z.ToArray(), _code.ToArray());
            builder.SetElements(_connectivity.ToArray());
            builder.SetProjection(projection);
            builder.SetEumQuantity(eumQuantity);

            MeshFile newMesh = builder.CreateMesh();

            MeshValidator meshValidator = new MeshValidator();

            meshValidator.ValidateMesh(newMesh.X, newMesh.Y, newMesh.Code, newMesh.ElementTable);

            foreach (string error in meshValidator.Errors)
            {
                Console.Out.WriteLine(error);
            }

            newMesh.Write(_newMeshFileName);

            //-------------------------------------
            // Do some statistics on the mesh:

            // collect number of face codes for each mesh
            SortedDictionary <int, int[]> bcCodesStats = new SortedDictionary <int, int[]>();
            List <MeshValidator>          validators   = new List <MeshValidator>();

            for (int meshIndex = 0; meshIndex < meshes.Count; meshIndex++)
            {
                MeshFile      meshFile  = meshes[meshIndex];
                MeshValidator validator = new MeshValidator();
                validator.ValidateMesh(meshFile.X, meshFile.Y, meshFile.Code, meshFile.ElementTable);
                validators.Add(validator);
                UpdateStatistics(meshes.Count + 1, meshIndex, bcCodesStats, validator.GetFaceCodeStatistics());
            }
            UpdateStatistics(meshes.Count + 1, meshes.Count, bcCodesStats, meshValidator.GetFaceCodeStatistics());

            Console.Out.Write("---------------------");
            Console.Out.Write(" Statistics of faces ");
            Console.Out.Write("---------------------");
            Console.Out.WriteLine("");
            Console.Out.Write("FaceCode  |");
            for (int i = 0; i < meshes.Count; i++)
            {
                Console.Out.Write(" mesh {0,2}  ", i + 1);
            }
            Console.Out.Write(" |  total | new mesh");
            Console.Out.WriteLine("");

            int[] totals = new int[meshes.Count + 2];
            foreach (KeyValuePair <int, int[]> keyValuePair in bcCodesStats)
            {
                Console.Out.Write("    {0,4}  |", keyValuePair.Key);
                int total = 0;
                for (int index = 0; index < keyValuePair.Value.Length - 1; index++)
                {
                    int meshCodeCount = keyValuePair.Value[index];
                    total         += meshCodeCount;
                    totals[index] += meshCodeCount;
                    Console.Out.Write(" {0,7}  ", meshCodeCount);
                }
                totals[meshes.Count]     += total;
                totals[meshes.Count + 1] += keyValuePair.Value.Last();
                Console.Out.Write(" |{0,7} | ", total);
                Console.Out.Write(" {0,7}  ", keyValuePair.Value.Last());
                Console.Out.WriteLine("");
            }
            Console.Out.Write("   total  |");
            for (int index = 0; index < meshes.Count; index++)
            {
                Console.Out.Write(" {0,7}  ", totals[index]);
            }
            Console.Out.Write(" |{0,7} | ", totals[meshes.Count]);
            Console.Out.Write(" {0,7}  ", totals[meshes.Count + 1]);
            Console.Out.WriteLine("");
            Console.Out.Write("---------------------");
            Console.Out.Write("---------------------");
            Console.Out.Write("---------------------");
            Console.Out.WriteLine("");
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Create dfsu and mesh file from dfs2 file.
        /// <para>
        /// Note 1: Boundary code is set to land value at
        ///         all boundaries of mesh and dfsu file.
        ///         These must be updated to something "better"
        ///         if to use as input in another simulation.
        /// </para>
        /// <para>
        /// Note 2: P and Q values are not rotated with the
        ///         grid, but should be so, if used in the
        ///         projected coordinate system. It must take
        ///         the 327 degrees rotation into account.
        /// </para>
        /// </summary>
        /// <param name="dfs2Filename">Name of input dfs2 file, e.g. the OresundHD.dfs2</param>
        /// <param name="meshFilename">Name of output mesh file</param>
        /// <param name="dfsuFilename">Name of output dfsu file</param>
        public static void CreateDfsuFromDfs2(string dfs2Filename, string meshFilename, string dfsuFilename)
        {
            // Open file
            Dfs2File dfs2 = DfsFileFactory.Dfs2FileOpen(dfs2Filename);

            // Read bathymetry from first static item
            IDfsStaticItem bathymetryItem = dfs2.ReadStaticItemNext();

            float[] bathymetry = (float[])bathymetryItem.Data;

            // Extract spatial axis
            IDfsAxisEqD2 spatialAxis = (IDfsAxisEqD2)dfs2.SpatialAxis;
            // Some convenience variables
            double dx     = spatialAxis.Dx;
            double dy     = spatialAxis.Dy;
            double x0     = spatialAxis.X0;
            double y0     = spatialAxis.Y0;
            int    xCount = spatialAxis.XCount;
            int    yCount = spatialAxis.YCount;

            // First custom block (index 0) contains the M21_MISC values,
            // where the 4th (index 3) is the land value
            float landValue = (float)dfs2.FileInfo.CustomBlocks[0][3];

            //-----------------------------------------
            // Find out which elements in the dfs2 grid that is not a land value
            // and include all those elements and their surrounding nodes in mesh

            // Arrays indicating if element and node in grid is used or not in mesh
            bool[,] elmts = new bool[xCount, yCount];
            int[,] nodes  = new int[xCount + 1, yCount + 1];

            // Loop over all elements in 2D grid
            for (int l = 0; l < yCount; l++)
            {
                for (int k = 0; k < xCount; k++)
                {
                    // If bathymetry is not land value, use element.
                    if (bathymetry[k + l * xCount] != landValue)
                    {
                        // element [l,k] is used, and also the 4 nodes around it
                        elmts[k, l]         = true;
                        nodes[k, l]         = 1;
                        nodes[k + 1, l]     = 1;
                        nodes[k, l + 1]     = 1;
                        nodes[k + 1, l + 1] = 1;
                    }
                }
            }

            //-----------------------------------------
            // Create new mest nodes

            // Cartography object can convert grid (x,y) to projection (east,north)
            IDfsProjection proj = dfs2.FileInfo.Projection;

            DHI.Projections.Cartography cart = new DHI.Projections.Cartography(proj.WKTString, proj.Longitude, proj.Latitude, proj.Orientation);

            // New mesh nodes
            List <double> X    = new List <double>();
            List <double> Y    = new List <double>();
            List <float>  Zf   = new List <float>();  // float values for dfsu file
            List <double> Zd   = new List <double>(); // double values for mesh file
            List <int>    Code = new List <int>();

            // Loop over all nodes
            int nodesCount = 0;

            for (int l = 0; l < yCount + 1; l++)
            {
                for (int k = 0; k < xCount + 1; k++)
                {
                    // Check if node is included in mesh
                    if (nodes[k, l] > 0)
                    {
                        // Convert from mesh (x,y) to projection (east,north)
                        double east, north;
                        cart.Xy2Proj((k - 0.5) * dx + x0, (l - 0.5) * dy + y0, out east, out north);

                        // Average Z on node from neighbouring grid cell values, cell value is used
                        // unless they are outside grid or has land values
                        double z      = 0;
                        int    zCount = 0;
                        if (k > 0 && l > 0 && bathymetry[k - 1 + (l - 1) * xCount] != landValue)
                        {
                            zCount++;                z += bathymetry[k - 1 + (l - 1) * xCount];
                        }
                        if (k < xCount && l > 0 && bathymetry[k + (l - 1) * xCount] != landValue)
                        {
                            zCount++;                z += bathymetry[k + (l - 1) * xCount];
                        }
                        if (k > 0 && l < yCount && bathymetry[k - 1 + (l) * xCount] != landValue)
                        {
                            zCount++;                z += bathymetry[k - 1 + (l) * xCount];
                        }
                        if (k < xCount && l < yCount && bathymetry[k + (l) * xCount] != landValue)
                        {
                            zCount++;                z += bathymetry[k + (l) * xCount];
                        }

                        if (zCount > 0)
                        {
                            z /= zCount;
                        }
                        else
                        {
                            z = landValue;
                        }

                        // Store new node number and add node
                        nodesCount++;
                        nodes[k, l] = nodesCount; // this is the node number to use in the element table
                        X.Add(east);
                        Y.Add(north);
                        Zf.Add((float)z);
                        Zd.Add(z);
                        Code.Add(zCount == 4 ? 0 : 1); // Land boundary if zCount < 4
                    }
                }
            }

            // New mesh elements
            List <int[]> elmttable2 = new List <int[]>();

            for (int l = 0; l < yCount; l++)
            {
                for (int k = 0; k < xCount; k++)
                {
                    // Check if element is included in mesh
                    if (elmts[k, l])
                    {
                        // For this element, add the four surrounding nodes,
                        // counter-clockwise order
                        int[] newNodes = new int[4];
                        newNodes[0] = nodes[k, l];
                        newNodes[1] = nodes[k + 1, l];
                        newNodes[2] = nodes[k + 1, l + 1];
                        newNodes[3] = nodes[k, l + 1];
                        elmttable2.Add(newNodes);
                    }
                }
            }

            //-----------------------------------------
            // Create mesh
            {
                // Create 2D dfsu file
                MeshBuilder builder = new MeshBuilder();

                // Setup header and geometry
                builder.SetNodes(X.ToArray(), Y.ToArray(), Zd.ToArray(), Code.ToArray());
                builder.SetElements(elmttable2.ToArray());
                builder.SetProjection(dfs2.FileInfo.Projection);

                // Create new file
                MeshFile mesh = builder.CreateMesh();
                mesh.Write(meshFilename);
            }

            //-----------------------------------------
            // Create dfsu file
            {
                // dfs2 time axis
                IDfsEqCalendarAxis timeAxis = (IDfsEqCalendarAxis)dfs2.FileInfo.TimeAxis;

                // Create 2D dfsu file
                DfsuBuilder builder = DfsuBuilder.Create(DfsuFileType.Dfsu2D);

                // Setup header and geometry
                builder.SetNodes(X.ToArray(), Y.ToArray(), Zf.ToArray(), Code.ToArray());
                builder.SetElements(elmttable2.ToArray());
                builder.SetProjection(dfs2.FileInfo.Projection);
                builder.SetTimeInfo(timeAxis.StartDateTime, timeAxis.TimeStepInSeconds());
                builder.SetZUnit(eumUnit.eumUmeter);

                // Add dynamic items, copying from dfs2 file
                for (int i = 0; i < dfs2.ItemInfo.Count; i++)
                {
                    IDfsSimpleDynamicItemInfo itemInfo = dfs2.ItemInfo[i];
                    builder.AddDynamicItem(itemInfo.Name, itemInfo.Quantity);
                }

                // Create new file
                DfsuFile dfsu = builder.CreateFile(dfsuFilename);

                // Add dfs2 data to dfsu file
                float[] dfsuData = new float[dfsu.NumberOfElements];
                for (int i = 0; i < dfs2.FileInfo.TimeAxis.NumberOfTimeSteps; i++)
                {
                    for (int j = 0; j < dfs2.ItemInfo.Count; j++)
                    {
                        // Read dfs2 grid data
                        IDfsItemData2D <float> itemData = (IDfsItemData2D <float>)dfs2.ReadItemTimeStep(j + 1, i);
                        // Extract 2D grid data to dfsu data array
                        int lk = 0;
                        for (int l = 0; l < yCount; l++)
                        {
                            for (int k = 0; k < xCount; k++)
                            {
                                if (elmts[k, l])
                                {
                                    dfsuData[lk++] = itemData[k, l];
                                }
                            }
                        }
                        // write data
                        dfsu.WriteItemTimeStepNext(itemData.Time, dfsuData);
                    }
                }
                dfsu.Close();
            }

            dfs2.Close();
        }