예제 #1
0
        /// <summary>
        /// Create maximum velocity field for a dfs2 file
        /// <para>
        /// FFrom a dfs2 file containing items (H-P-Q), (P-Q-Speed) or  (u-v-Speed),
        /// find maximum velocity for each cell and store in [outputFilename]
        /// </para>
        /// </summary>
        public static void MaxVelocityField(string sourceFilename, string outfilename)
        {
            // Open source file
            IDfs2File source = DfsFileFactory.Dfs2FileOpen(sourceFilename);

            // Create output file
            Dfs2Builder builder = Dfs2Builder.Create("Max Velocity", @"MIKE SDK", 0);

            // Set up the header
            builder.SetDataType(1);
            builder.SetGeographicalProjection(source.FileInfo.Projection);
            builder.SetTemporalAxis(source.FileInfo.TimeAxis);
            builder.SetSpatialAxis(source.SpatialAxis);
            builder.DeleteValueFloat = -1e-30f;

            // Add custom block
            foreach (IDfsCustomBlock customBlock in source.FileInfo.CustomBlocks)
            {
                builder.AddCustomBlock(customBlock);
            }

            // Set up dynamic items
            builder.AddDynamicItem("Maximum Speed", eumQuantity.Create(eumItem.eumIFlowVelocity, eumUnit.eumUmeterPerSec), DfsSimpleType.Float, DataValueType.Instantaneous);
            builder.AddDynamicItem("u-velocity", eumQuantity.Create(eumItem.eumIFlowVelocity, eumUnit.eumUmeterPerSec), DfsSimpleType.Float, DataValueType.Instantaneous);
            builder.AddDynamicItem("v-velocity", eumQuantity.Create(eumItem.eumIFlowVelocity, eumUnit.eumUmeterPerSec), DfsSimpleType.Float, DataValueType.Instantaneous);
            //builder.AddDynamicItem("H Water Depth m", eumQuantity.Create(eumItem.eumIWaterLevel, eumUnit.eumUmeter), DfsSimpleType.Float, DataValueType.Instantaneous);

            // Create file
            builder.CreateFile(outfilename);

            // Add static items containing bathymetri data, use data from source

            IDfsStaticItem sourceStaticItem;

            while (null != (sourceStaticItem = source.ReadStaticItemNext()))
            {
                builder.AddStaticItem(sourceStaticItem.Name, sourceStaticItem.Quantity, sourceStaticItem.Data);
            }

            // Get the file
            Dfs2File file = builder.GetFile();

            // Arrays storing max-speed values
            int numberOfCells = file.SpatialAxis.SizeOfData;

            float[] maxSpeed    = new float[numberOfCells];
            float[] uAtMaxSpeed = new float[numberOfCells];
            float[] vAtMaxSpeed = new float[numberOfCells];
            // Initialize with delete values
            for (int i = 0; i < numberOfCells; i++)
            {
                maxSpeed[i]    = source.FileInfo.DeleteValueFloat;
                uAtMaxSpeed[i] = source.FileInfo.DeleteValueFloat;
                vAtMaxSpeed[i] = source.FileInfo.DeleteValueFloat;
            }

            // Create empty ItemData's, for easing reading of source data
            IDfsItemData2D <float>[] datas = new IDfsItemData2D <float> [source.ItemInfo.Count];
            for (int i = 0; i < source.ItemInfo.Count; i++)
            {
                datas[i] = source.CreateEmptyItemData <float>(i + 1);
            }

            // Find HPQ items in file - uses StartsWith, since the string varies slightly with the version of the engine.
            int dIndex = source.ItemInfo.FindIndex(item => item.Name.StartsWith("H Water Depth", StringComparison.OrdinalIgnoreCase));
            int pIndex = source.ItemInfo.FindIndex(item => item.Name.StartsWith("P Flux", StringComparison.OrdinalIgnoreCase));
            int qIndex = source.ItemInfo.FindIndex(item => item.Name.StartsWith("Q Flux", StringComparison.OrdinalIgnoreCase));
            int sIndex = source.ItemInfo.FindIndex(item => item.Name.StartsWith("Current Speed", StringComparison.OrdinalIgnoreCase));
            int uIndex = source.ItemInfo.FindIndex(item => item.Name.StartsWith("U velocity", StringComparison.OrdinalIgnoreCase));
            int vIndex = source.ItemInfo.FindIndex(item => item.Name.StartsWith("V velocity", StringComparison.OrdinalIgnoreCase));
            // Either p and q must be there, or u and v, and either d or s must be there.
            bool haspq = (pIndex >= 0 && qIndex >= 0);
            bool hasuv = (uIndex >= 0 && vIndex >= 0);

            if (!hasuv && !haspq || dIndex < 0 && sIndex < 0)
            {
                throw new Exception("Could not find items. File must have H-P-Q items, P-Q-Speed or U-V-Speed items");
            }
            IDfsItemData2D <float> dItem = dIndex >= 0 ? datas[dIndex] : null;
            IDfsItemData2D <float> pItem = pIndex >= 0 ? datas[pIndex] : null;
            IDfsItemData2D <float> qItem = qIndex >= 0 ? datas[qIndex] : null;
            IDfsItemData2D <float> sItem = sIndex >= 0 ? datas[sIndex] : null;
            IDfsItemData2D <float> uItem = uIndex >= 0 ? datas[uIndex] : null;
            IDfsItemData2D <float> vItem = vIndex >= 0 ? datas[vIndex] : null;

            // Spatial 2D axis
            IDfsAxisEqD2 axis = (IDfsAxisEqD2)source.SpatialAxis;
            double       dx   = axis.Dx;
            double       dy   = axis.Dy;

            // Loop over all time steps
            for (int i = 0; i < source.FileInfo.TimeAxis.NumberOfTimeSteps; i++)
            {
                // Read data for all items from source file. That will also update the depth, p and q.
                for (int j = 0; j < source.ItemInfo.Count; j++)
                {
                    source.ReadItemTimeStep(datas[j], i);
                }

                // For each cell, find maximum speed and store u, v and depth at that point in time.
                for (int j = 0; j < numberOfCells; j++)
                {
                    // Skip delete values
                    if (dItem?.Data[j] == source.FileInfo.DeleteValueFloat ||
                        sItem?.Data[j] == source.FileInfo.DeleteValueFloat)
                    {
                        continue;
                    }

                    double p = pItem.Data[j];
                    double q = qItem.Data[j];
                    double speed, u, v;
                    if (sItem != null)
                    {
                        // Use speed from result file
                        speed = sItem.Data[j];

                        if (hasuv)
                        {
                            // Use u and v from result file
                            u = uItem.Data[j];
                            v = vItem.Data[j];
                        }
                        else // (haspq)
                        {
                            // Calculate u and v from speed and direction of p and q
                            double pqLength = System.Math.Sqrt(p * p + q * q);
                            u = hasuv ? uItem.Data[j] : speed * p / pqLength;
                            v = hasuv ? vItem.Data[j] : speed * q / pqLength;
                        }
                    }
                    else // (dItem != null)
                    {
                        // Current speed is not directly available in source file, calculate from u and v
                        if (hasuv)
                        {
                            u = uItem.Data[j];
                            v = vItem.Data[j];
                        }
                        else
                        {
                            // u and v is not available, calculate fromdh, p and q.
                            double d = dItem.Data[j];
                            u = pItem.Data[j] / d;
                            v = qItem.Data[j] / d;
                        }
                        speed = System.Math.Sqrt(u * u + v * v);
                    }
                    if (speed > maxSpeed[j])
                    {
                        maxSpeed[j]    = (float)speed;
                        uAtMaxSpeed[j] = (float)u;
                        vAtMaxSpeed[j] = (float)v;
                    }
                }
            }

            file.WriteItemTimeStepNext(0, maxSpeed);
            file.WriteItemTimeStepNext(0, uAtMaxSpeed);
            file.WriteItemTimeStepNext(0, vAtMaxSpeed);
            //file.WriteItemTimeStepNext(0, maxDepth);

            source.Close();
            file.Close();
        }
예제 #2
0
        /// <summary>
        /// Example of how to create a Dfs2 file from scratch. This method
        /// creates a copy of the OresundHD.dfs2 test file.
        /// <para>
        /// Data for static and dynamic item is taken from a source dfs file,
        /// which here is the OresundHD.dfs2 test file. The data could come
        /// from any other source.
        /// </para>
        /// </summary>
        /// <param name="sourceFilename">Path and name of the OresundHD.dfs2 test file</param>
        /// <param name="filename">Path and name of the new file to create</param>
        public static void CreateDfs2File(string sourceFilename, string filename)
        {
            IDfs2File source = DfsFileFactory.Dfs2FileOpen(sourceFilename);

            DfsFactory  factory = new DfsFactory();
            Dfs2Builder builder = Dfs2Builder.Create("", @"C:\Program Files\DHI\2010\bin\nmodel.exe", 0);

            // Set up the header
            builder.SetDataType(1);
            builder.SetGeographicalProjection(factory.CreateProjectionGeoOrigin("UTM-33", 12.438741600559766, 55.225707842436385, 326.99999999999955));
            builder.SetTemporalAxis(factory.CreateTemporalEqCalendarAxis(eumUnit.eumUsec, new DateTime(1993, 12, 02, 0, 0, 0), 0, 86400));
            builder.SetSpatialAxis(factory.CreateAxisEqD2(eumUnit.eumUmeter, 71, 0, 900, 91, 0, 900));
            builder.DeleteValueFloat = -1e-30f;

            // Add custom block
            // M21_Misc : {orientation (should match projection), drying depth, -900=has projection, land value, 0, 0, 0}
            builder.AddCustomBlock(factory.CreateCustomBlock("M21_Misc", new float[] { 327f, 0.2f, -900f, 10f, 0f, 0f, 0f }));

            // Set up dynamic items
            builder.AddDynamicItem("H Water Depth m", eumQuantity.Create(eumItem.eumIWaterLevel, eumUnit.eumUmeter), DfsSimpleType.Float, DataValueType.Instantaneous);
            builder.AddDynamicItem("P Flux m^3/s/m", eumQuantity.Create(eumItem.eumIFlowFlux, eumUnit.eumUm3PerSecPerM), DfsSimpleType.Float, DataValueType.Instantaneous);
            builder.AddDynamicItem("Q Flux m^3/s/m", eumQuantity.Create(eumItem.eumIFlowFlux, eumUnit.eumUm3PerSecPerM), DfsSimpleType.Float, DataValueType.Instantaneous);

            // Create file
            builder.CreateFile(filename);

            // Add static items containing bathymetri data, use data from source
            IDfsStaticItem sourceStaticItem = source.ReadStaticItemNext();

            builder.AddStaticItem("Static item", eumQuantity.UnDefined, sourceStaticItem.Data);

            // Get the file
            Dfs2File file = builder.GetFile();

            // Loop over all time steps
            for (int i = 0; i < source.FileInfo.TimeAxis.NumberOfTimeSteps; i++)
            {
                // Loop over all items
                for (int j = 0; j < source.ItemInfo.Count; j++)
                {
                    // Add data for all item-timesteps, copying data from source file.

                    // Read data from source file
                    IDfsItemData2D <float> sourceData = (IDfsItemData2D <float>)source.ReadItemTimeStepNext();

                    // Create empty item data, and copy over data from source
                    // The IDfsItemData2D can handle 2D indexing, on the form data2D[k,l].
                    // An ordinary array, float[], can also be used, though indexing from 2D to 1D must be
                    // handled by user code i.e. using data1D[k + l*xCount] compared to data2D[k,l]
                    IDfsItemData2D <float> itemData2D = (IDfsItemData2D <float>)file.CreateEmptyItemData(j + 1);
                    for (int k = 0; k < 71; k++)
                    {
                        for (int l = 0; l < 91; l++)
                        {
                            itemData2D[k, l] = sourceData[k, l];
                        }
                    }
                    // the itemData2D.Data is a float[], so any float[] of the correct size is valid here.
                    file.WriteItemTimeStep(j + 1, i, sourceData.Time, itemData2D.Data);
                }
            }

            source.Close();
            file.Close();
        }