/// <summary> /// Creates the sub-grids of the clustering /// </summary> /// <param name="numOfClusters">Number of clusters</param> /// <returns>A list of sub-grids</returns> public Clustering CreateClustering(int numOfClusters, SubGrid subGrid = null) { if (subGrid == null) { subGrid = new SubGrid(CellMask.GetFullMask(gridData)); } // Attention: numOfCells can equal all local cells or only the local cells of a subgrid, // e.g., the fluid cells in an IBM simulation int numOfCells = subGrid.LocalNoOfCells; MultidimensionalArray cellMetric = GetStableTimestepSize(subGrid); MultidimensionalArray means = CreateInitialMeans(cellMetric, numOfClusters); Kmeans Kmean = new Kmeans(cellMetric.To1DArray(), numOfClusters, means.To1DArray()); // The corresponding sub-grid IDs int[] subGridCellToClusterMap = Kmean.Cluster(); int[] noOfCellsPerCluster = Kmean.ClusterCount; unsafe { int[] globalCC = new int[numOfClusters]; // send = means[] // receive = globalMeans[] fixed(int *pSend = &noOfCellsPerCluster[0], pRcv = &globalCC[0]) { csMPI.Raw.Allreduce((IntPtr)(pSend), (IntPtr)(pRcv), numOfClusters, csMPI.Raw._DATATYPE.INT, csMPI.Raw._OP.SUM, csMPI.Raw._COMM.WORLD); } noOfCellsPerCluster = globalCC; } int counter = numOfClusters; for (int i = 0; i < numOfClusters; i++) { if (noOfCellsPerCluster[i] == 0) { System.Console.WriteLine("Sub-grid/Cluster " + (i + 1) + ", with mean value " + Kmean.Means[i] + ", is empty and not used anymore!"); counter--; } } // Generating BitArray for all Subgrids, even for those which are empty, i.e ClusterCount == 0 BitArray[] baMatrix = new BitArray[numOfClusters]; for (int i = 0; i < numOfClusters; i++) { //baMatrix[i] = new BitArray(gridData.iLogicalCells.NoOfCells); baMatrix[i] = new BitArray(gridData.iLogicalCells.NoOfLocalUpdatedCells); } // Filling the BitArrays for (int i = 0; i < numOfCells; i++) { baMatrix[subGridCellToClusterMap[i]][subGrid.SubgridIndex2LocalCellIndex[i]] = true; } // Generating the sub-grids List <SubGrid> clusters = new List <SubGrid>(counter); for (int i = 0; i < numOfClusters; i++) { // Generating only the sub-grids which are not empty if (noOfCellsPerCluster[i] != 0) { BitArray ba = baMatrix[i]; clusters.Add(new SubGrid(new CellMask(gridData, ba))); } } return(new Clustering(clusters, subGrid)); }
/// <summary> /// Creates the sub-grids of the clustering /// </summary> /// <param name="numOfClusters">Number of clusters</param> /// <returns>A list of sub-grids</returns> public Clustering CreateClustering(int numOfClusters, IList <TimeStepConstraint> timeStepConstraints, SubGrid subGrid = null) { //using (var tr = new ilPSP.Tracing.FuncTrace()) { if (subGrid == null) { subGrid = new SubGrid(CellMask.GetFullMask(gridData)); } // Attention: numOfCells can equal all local cells or only the local cells of a subgrid, // e.g., the fluid cells in an IBM simulation int numOfCells = subGrid.LocalNoOfCells; MultidimensionalArray cellMetric = GetStableTimestepSize(subGrid, timeStepConstraints); MultidimensionalArray means = CreateInitialMeans(cellMetric, numOfClusters); Kmeans Kmean = new Kmeans(cellMetric.To1DArray(), numOfClusters, means.To1DArray()); // The corresponding sub-grid IDs int[] subGridCellToClusterMap = Kmean.Cluster(); int[] noOfCellsPerCluster = Kmean.ClusterCount; unsafe { int[] globalCC = new int[numOfClusters]; // send = means[] // receive = globalMeans[] fixed(int *pSend = &noOfCellsPerCluster[0], pRcv = &globalCC[0]) { csMPI.Raw.Allreduce((IntPtr)(pSend), (IntPtr)(pRcv), numOfClusters, csMPI.Raw._DATATYPE.INT, csMPI.Raw._OP.SUM, csMPI.Raw._COMM.WORLD); } noOfCellsPerCluster = globalCC; } int counter = numOfClusters; for (int i = 0; i < numOfClusters; i++) { if (noOfCellsPerCluster[i] == 0) { if (consoleOutput) { Console.WriteLine("Sub-grid/Cluster " + (i + 1) + ", with mean value " + Kmean.Means[i] + ", is empty and not used anymore!"); } counter--; } } // Generating BitArray for all Subgrids, even for those which are empty, i.e ClusterCount == 0 BitArray[] baMatrix = new BitArray[numOfClusters]; for (int i = 0; i < numOfClusters; i++) { //baMatrix[i] = new BitArray(gridData.iLogicalCells.NoOfCells); baMatrix[i] = new BitArray(gridData.iLogicalCells.NoOfLocalUpdatedCells); } // Filling the BitArrays for (int i = 0; i < numOfCells; i++) { baMatrix[subGridCellToClusterMap[i]][subGrid.SubgridIndex2LocalCellIndex[i]] = true; } // IBM source cells are assigned to the cluster of the corresponding target cells // This code is only excuted in IBM simulation runs if (this.cellAgglomerator != null) { // MPI exchange in order to get cellToClusterMap (local + external cells) int JE = gridData.iLogicalCells.Count; int J = gridData.iLogicalCells.NoOfLocalUpdatedCells; int[] cellToClusterMap = new int[JE]; int JSub = subGrid.LocalNoOfCells; int[] jSub2j = subGrid.SubgridIndex2LocalCellIndex; for (int jsub = 0; jsub < JSub; jsub++) { cellToClusterMap[jSub2j[jsub]] = subGridCellToClusterMap[jsub]; } cellToClusterMap.MPIExchange(gridData); foreach (AgglomerationPair aggPair in this.cellAgglomerator.AggInfo.AgglomerationPairs) { // AgglomerationPairs can contain combinations where jCellSource is on one MPI rank // and the corresponding target cell is on another MPI rank. These duplications have to be eleminated. if (aggPair.jCellSource < J) { // Assign source cell to the cluster of the corresponding target cell int clusterOfTargetCell = cellToClusterMap[aggPair.jCellTarget]; baMatrix[clusterOfTargetCell][aggPair.jCellSource] = true; // Delete source cell from other clusters for (int j = 0; j < numOfClusters; j++) { if (clusterOfTargetCell != j) { baMatrix[j][aggPair.jCellSource] = false; } } } } } // Generating the sub-grids List <SubGrid> clusters = new List <SubGrid>(counter); for (int i = 0; i < numOfClusters; i++) { // Generating only the sub-grids which are not empty if (noOfCellsPerCluster[i] != 0) { BitArray ba = baMatrix[i]; clusters.Add(new SubGrid(new CellMask(gridData, ba))); } } if (consoleOutput) { for (int i = 0; i < clusters.Count; i++) { Console.WriteLine("CreateClustering:\t id=" + i + " ->\t\telements=" + clusters[i].GlobalNoOfCells); } } return(new Clustering(clusters, subGrid)); }