Example #1
0
        }   // End getEigenvalue(double[,] SecondDerivMatrix)

        public void SetAllEigenvaluesIteratively(ClusteringSolution Solution)
        {
            if (Solution.DistributedExecutionMode)
            {
                Exception e = DAVectorUtility.SALSAError(" Illegal Eigenvalue and Parallelization Combination ");
                throw (e);
            }
            if (Program.SigmaMethod > 0)
            {
                Exception e = DAVectorUtility.SALSAError(" Illegal Eigenvalue and Sigma Method Combination " + Program.SigmaMethod.ToString());
                throw (e);
            }
            this.CurrentSolution        = Solution;
            this.CenterEigenvector      = this.CurrentSolution.Eigenvector_k_i;
            this.CenterEigenvalue       = this.CurrentSolution.Eigenvalue_k;
            this.InitVector             = new double[Program.ParameterVectorDimension];
            this.FirstTerm              = new double[this.CurrentSolution.Ncent_Global];
            this.CenterEigenstatus      = new int[this.CurrentSolution.Ncent_Global];
            this.CenterEigenconvergence = new int[this.CurrentSolution.Ncent_Global];

            Random random   = new Random();
            double InitNorm = 0.0;

            for (int VectorIndex = 0; VectorIndex < Program.ParameterVectorDimension; VectorIndex++)
            {
                InitVector[VectorIndex] = -0.5 + random.NextDouble();
                InitNorm += InitVector[VectorIndex] * InitVector[VectorIndex];
            }
            InitNorm = 1.0 / Math.Sqrt(InitNorm);
            for (int VectorIndex = 0; VectorIndex < Program.ParameterVectorDimension; VectorIndex++)
            {
                InitVector[VectorIndex] *= InitNorm;
            }

            //  Initialization Loop over Clusters
            int somethingtodo = 0;

            for (int ClusterIndex = 0; ClusterIndex < this.CurrentSolution.Ncent_Global; ClusterIndex++)
            {
                this.CenterEigenconvergence[ClusterIndex] = 0;
                this.CenterEigenstatus[ClusterIndex]      = 0;
                this.FirstTerm[ClusterIndex] = 0;
                if (this.CurrentSolution.Splittable_k_[ClusterIndex] != 1)
                {
                    continue;
                }
                ++somethingtodo;
                for (int VectorIndex = 0; VectorIndex < Program.ParameterVectorDimension; VectorIndex++)
                {
                    this.CenterEigenvector[ClusterIndex][VectorIndex] = InitVector[VectorIndex];
                }
            }   // End Loop over Clusters
            if (somethingtodo == 0)
            {
                return;
            }

            GlobalReductions.FindVectorDoubleSum FindClusterFirstTerm     = new GlobalReductions.FindVectorDoubleSum(DAVectorUtility.ThreadCount, this.CurrentSolution.Ncent_Global);
            GlobalReductions.FindDoubleSum       FindNumberScalarProducts = new GlobalReductions.FindDoubleSum(DAVectorUtility.ThreadCount);

            for (int NumPowerIterations = 0; NumPowerIterations < Program.PowerIterationLimit; NumPowerIterations++)
            {
                somethingtodo = 0;
                for (int ClusterIndex = 0; ClusterIndex < this.CurrentSolution.Ncent_Global; ClusterIndex++)
                {
                    if (this.CurrentSolution.LocalStatus[ClusterIndex] != 1)
                    {
                        continue;
                    }
                    if (this.CurrentSolution.Splittable_k_[ClusterIndex] != 1)
                    {
                        continue;
                    }
                    if (this.CenterEigenconvergence[ClusterIndex] == 0)
                    {
                        ++somethingtodo;
                    }
                }
                if (somethingtodo == 0)
                {
                    break;
                }

                GlobalReductions.FindVectorDoubleSum3 FindNewPowerVectors = new GlobalReductions.FindVectorDoubleSum3(DAVectorUtility.ThreadCount,
                                                                                                                      Program.ParameterVectorDimension, this.CurrentSolution.Ncent_Global);

                Parallel.For(0, Program.ParallelOptions.MaxDegreeOfParallelism, Program.ParallelOptions, (ThreadNo) =>
                {
                    FindNewPowerVectors.startthread(ThreadNo);
                    double[] PartVector = new double[Program.ParameterVectorDimension];

                    int indexlen   = DAVectorUtility.PointsperThread[ThreadNo];
                    int beginpoint = DAVectorUtility.StartPointperThread[ThreadNo] - DAVectorUtility.PointStart_Process;
                    for (int alpha = beginpoint; alpha < indexlen + beginpoint; alpha++)
                    {
                        int IndirectSize = this.CurrentSolution.NumClusters_alpha_[alpha];

                        for (int IndirectClusterIndex = 0; IndirectClusterIndex < IndirectSize; IndirectClusterIndex++)
                        {   // Loop over Clusters for this point
                            int RealClusterIndex   = -1;
                            int RemoteIndex        = -1;
                            int ActiveClusterIndex = -1;
                            VectorAnnealIterate.ClusterPointersforaPoint(alpha, IndirectClusterIndex, ref RealClusterIndex, ref ActiveClusterIndex, ref RemoteIndex);
                            if (this.CurrentSolution.Splittable_k_[RealClusterIndex] != 1)
                            {
                                continue;
                            }

                            double Mvalue = this.CurrentSolution.M_alpha_kpointer_[alpha][IndirectClusterIndex];
                            if (NumPowerIterations == 0)
                            {
                                FindClusterFirstTerm.addapoint(ThreadNo, Mvalue, RealClusterIndex);
                            }
                            double multiplier = 0.0;
                            for (int VectorIndex = 0; VectorIndex < Program.ParameterVectorDimension; VectorIndex++)
                            {
                                PartVector[VectorIndex] = this.CurrentSolution.Y_k_i_[RealClusterIndex][VectorIndex] - Program.PointPosition[alpha][VectorIndex];
                                multiplier += PartVector[VectorIndex] * CenterEigenvector[RealClusterIndex][VectorIndex];
                            }
                            FindNumberScalarProducts.addapoint(ThreadNo, 1.0);

                            double wgt = Mvalue * multiplier;
                            for (int VectorIndex = 0; VectorIndex < Program.ParameterVectorDimension; VectorIndex++)
                            {
                                PartVector[VectorIndex] *= wgt;
                            }
                            FindNewPowerVectors.addapoint(ThreadNo, PartVector, RealClusterIndex);
                        }
                    } // End Loop over points
                });   // End loop initialing Point dependent quantities

                FindNewPowerVectors.sumoverthreadsandmpi();
                for (int ClusterIndex = 0; ClusterIndex < this.CurrentSolution.Ncent_Global; ClusterIndex++)
                {
                    if (this.CurrentSolution.LocalStatus[ClusterIndex] != 1)
                    {
                        continue;
                    }
                    if ((this.CurrentSolution.Splittable_k_[ClusterIndex] != 1) || (this.CenterEigenconvergence[ClusterIndex] != 0))
                    {
                        continue;
                    }
                    double[] sums = new double[3];  // Old.New Old.Old New.New
                    for (int loop = 0; loop < 3; loop++)
                    {
                        sums[loop] = 0.0;
                    }
                    for (int VectorIndex = 0; VectorIndex < Program.ParameterVectorDimension; VectorIndex++)
                    {
                        int    TotalIndex = VectorIndex + ClusterIndex * Program.ParameterVectorDimension;
                        double newvalue   = FindNewPowerVectors.TotalVectorSum[TotalIndex];
                        double oldvalue   = CenterEigenvector[ClusterIndex][VectorIndex];
                        sums[0] += oldvalue * newvalue;
                        sums[1] += oldvalue * oldvalue;
                        sums[2] += newvalue * newvalue;
                        CenterEigenvector[ClusterIndex][VectorIndex] = newvalue;
                    }

                    //  Decide if finished and set eigenvalue
                    double CandidateEigenvalue = sums[0] / sums[1];
                    bool   LegalEigenvalue     = (CandidateEigenvalue > 0.0);
                    DAVectorUtility.SynchronizeMPIvariable(ref LegalEigenvalue);

                    //	Check if converged
                    //	Do this in one process ONLY
                    if ((NumPowerIterations > 5) && LegalEigenvalue)
                    { // Arbitrary choice for Number of Power Iterations Cut
                        int EigenvalueDone = 0;
                        if (DAVectorUtility.MPI_Rank == 0)
                        { // Decisions can only be made in one process
                            if (Math.Abs(CandidateEigenvalue - this.CenterEigenvalue[ClusterIndex]) > CandidateEigenvalue * Program.eigenvaluechange)
                            {
                                ++EigenvalueDone;
                            }
                            double delta = sums[2] - 2.0 * sums[0] * CandidateEigenvalue + sums[1] * CandidateEigenvalue * CandidateEigenvalue;   // (Ax- Eigenvalue*Axold)**2
                            if (Math.Abs(delta) > CandidateEigenvalue * CandidateEigenvalue * Program.eigenvectorchange)
                            {
                                ++EigenvalueDone;
                            }
                        }   // End Test on Convergence
                        DAVectorUtility.SynchronizeMPIvariable(ref EigenvalueDone);

                        if (EigenvalueDone == 0)
                        {
                            this.CenterEigenconvergence[ClusterIndex] = 1 + NumPowerIterations;
                        }
                    }
                    this.CenterEigenvalue[ClusterIndex] = CandidateEigenvalue;

                    //  Normalize current Power Vector to 1
                    double wgt = 1.0 / Math.Sqrt(sums[2]);
                    for (int VectorIndex = 0; VectorIndex < Program.ParameterVectorDimension; VectorIndex++)
                    {
                        CenterEigenvector[ClusterIndex][VectorIndex] *= wgt;
                    }
                } // End Loop over Clusters
            }     //  End Loop over NumPowerIterations

            FindClusterFirstTerm.sumoverthreadsandmpi();
            FindNumberScalarProducts.sumoverthreadsandmpi();
            Program.SumEigenSPCalcs += FindNumberScalarProducts.Total;

            for (int ClusterIndex = 0; ClusterIndex < this.CurrentSolution.Ncent_Global; ClusterIndex++)
            {
                this.CenterEigenstatus[ClusterIndex] = 0;
                if (this.CurrentSolution.LocalStatus[ClusterIndex] != 1)
                {
                    continue;
                }
                if ((this.CurrentSolution.Splittable_k_[ClusterIndex] != 1) || (this.CenterEigenconvergence[ClusterIndex] <= 0))
                {
                    continue;
                }
                this.CenterEigenstatus[ClusterIndex] = 1;
                this.FirstTerm[ClusterIndex]         = FindClusterFirstTerm.TotalVectorSum[ClusterIndex];
                double tmp = this.CenterEigenvalue[ClusterIndex] / this.CurrentSolution.Temperature;
                this.CenterEigenvalue[ClusterIndex] = this.FirstTerm[ClusterIndex] - tmp;
            }
        }   // End SetEigenvaluesIteratively(ClusteringSolution Solution)
Example #2
0
        }       // End getEigenvalues

        // Compute the crrelation matrix compared to PairwiseThread. Rest is same as PairwiseThread
        // PassIndicator = 0 Find MAXIMUM eigenvalue  LMAX[kk] in EACH Cluster sector kk
        // PassIndicator = 1 Find MINIMUM eigenvalue in each cluster sector by finding Maximum eigenvalue of (LMAX[kk]-Second Derivative Matrix)

        // Methodology = 1 -- Calculate Power Vector for all Clusters (one per Cluster) from Original Second Derivative Matrix
        // Methodology = 2 -- Calculate Power Vector for all Clusters (one per Cluster) from  modification of second derivative matrix to reflect replication
        //                    for cases like ContinuousClustering=true that cluster can be divided into two with M halved for each case
        // Methodology = 3 -- Calculate Power Vector for ONE Clusters "Clustertoprocess" (Specified in ClusterSelected) from proper modification of second derivative matrix to reflect replication
        //                          Assuming that Clustertoprocess has its M value doubled in previous EM Iteration
        //                  2 and 3 are same except 3 assumes explicit facor of 2 weight in Z in calculation; Methodology=2 assumes no factor of 2
        // Methodology = 4 -- Calculate ONE Power Vector for set of Clusters (Could be just one but specified in ClusterSelected and usually at least two) from proper modification of second derivative matrix to reflect replication
        //                          Assuming NO doubled M values
        // Set Dist.ClusterSelected for all cases ( all zeros if Methodology 1,2)
        // Set ClustertoSplitin Methodology 3 CONSISTENT with Dist.ClusterSelected[ClustertoSplit]=1 being only ONE value
        // Set Dist.PlaceforEigsforMultipleCluster in Methodology 4 to indicate where results stored

        void PairwiseThread_SecDrv(int Methodology, int PassIndicator, double[][] localMalpha_k_, double[] localA_k_, double[][] localBalpha_k_, double[] localC_k_, int localNcent)
        {
            double T             = Dist.RunningPWC.Temperature;
            int    cachelinesize = Program.cachelinesize;

            int[]    UsethisCluster = new int[localNcent];
            double[] AxPattern      = new double[localNcent];
            int      REMOVEZEROEigs = 0;

            if (Methodology == 4)
            {
                REMOVEZEROEigs = 1;
            }

            for (int ClusterIndex = 0; ClusterIndex < localNcent; ClusterIndex++)
            {
                AxPattern[ClusterIndex]      = 1.0;
                UsethisCluster[ClusterIndex] = Dist.ClusterSelected[ClusterIndex];
                if ((Methodology == 3) && (UsethisCluster[ClusterIndex] == 1))
                {
                    eigenconverged[ClusterIndex] = -1;
                }
                if (Methodology < 3)
                {
                    eigenconverged[ClusterIndex] = -1;
                    if ((PassIndicator == 1) && (vectorclass.Eigenvalues_Pass0[ClusterIndex] <= 0.0))
                    {
                        UsethisCluster[ClusterIndex] = 0;
                    }
                }
                if ((Methodology == 4) && (UsethisCluster[ClusterIndex] == 0))
                {
                    REMOVEZEROEigs = 0;
                }
            }
            if (Methodology == 4)
            {
                eigenconverged[Dist.PlaceforEigsforMultipleCluster] = -1;
                int usedclusters = 0;
                for (int ClusterIndex = 0; ClusterIndex < localNcent; ClusterIndex++)
                {
                    if (UsethisCluster[ClusterIndex] > 0)
                    {
                        ++usedclusters;
                    }
                }
                double vectormult    = 1.0;
                double oddmultiplier = 1.0;
                if (usedclusters > 1)
                {
                    int halfused = usedclusters / 2;
                    if (halfused * 2 == usedclusters)
                    {
                        vectormult = 1.0 / Math.Sqrt((double)usedclusters);
                    }
                    else
                    {
                        oddmultiplier = 1.0 + 1.0 / halfused;
                        vectormult    = 1.0 / Math.Sqrt(2.0 * halfused + 3.0 + 1.0 / halfused);
                    }
                }
                for (int ClusterIndex = 0; ClusterIndex < localNcent; ClusterIndex++)
                {
                    if (Dist.ClusterSelected[ClusterIndex] == 0)
                    {
                        AxPattern[ClusterIndex] = 0.0;
                    }
                    else
                    {
                        AxPattern[ClusterIndex] = vectormult;
                        vectormult = -vectormult;
                        if (vectormult > 0.0)
                        {
                            AxPattern[ClusterIndex] *= oddmultiplier;
                        }
                    }
                }
            }   // End Methodology = 4

            Parallel.For(0, Program.ParallelOptions.MaxDegreeOfParallelism, Program.ParallelOptions, (threadIndex) =>
            {
                //	Start Code initializing power vectors Ax oldAx
                int indexlen   = PWCUtility.PointsperThread[threadIndex];
                int beginpoint = PWCUtility.StartPointperThread[threadIndex] - PWCUtility.PointStart_Process;
                for (int ProcessPointIndex = beginpoint; ProcessPointIndex < indexlen + beginpoint; ProcessPointIndex++)
                {
                    for (int ClusterIndex = 0; ClusterIndex < localNcent; ClusterIndex++)
                    {
                        if (Dist.ClusterSelected[ClusterIndex] == 0)
                        {
                            continue;
                        }
                        Ax[ProcessPointIndex][ClusterIndex]    = initialvector[ProcessPointIndex] * AxPattern[ClusterIndex];
                        oldAx[ProcessPointIndex][ClusterIndex] = Ax[ProcessPointIndex][ClusterIndex];
                    }
                }
            });



            double Mfudge = 1.0;

            if (Methodology == 2)
            {
                Mfudge = 0.5;
            }
            bool Subtract_twiceDuplicatedCenter = false;

            if ((Methodology != 1) && (Methodology != 4))
            {
                Subtract_twiceDuplicatedCenter = true;
            }

            MPISecPacket fromafarMandB = new MPISecPacket(MaxlengthMandB);
            MPISecPacket toafarMandB   = new MPISecPacket(MaxlengthMandB);
            MPISecPacket myownMandB    = new MPISecPacket(MaxlengthMandB);

            double[] fromafarAxarray = null;
            double[] toafarAxarray   = null;
            double[] myownAxarray    = null;

            int oldMaxLength2 = int.MinValue;

            for (int NumPowerIterations = 0; NumPowerIterations < Program.PowerIterationLimit; NumPowerIterations++)
            {   // Loop over Power Iterations
                //	Check if any centers are still not converged
                int NumberofAVectorsUsed = 0;
                for (int ClusterIndex = 0; ClusterIndex < localNcent; ClusterIndex++)
                {
                    if (UsethisCluster[ClusterIndex] == 1)
                    {
                        ++NumberofAVectorsUsed;
                    }
                }
                if (NumberofAVectorsUsed == 0)
                {
                    break;
                }
                if ((Methodology == 4) && (vectorclass.eigenconverged[Dist.PlaceforEigsforMultipleCluster] > 0))
                {
                    break;
                }

                // Increment Global Count of Iterations
                ++Program.CountTotalPowerIterations;

                // Loop over MPI calls
                MPI.CompletedStatus MPISecStatus;
                int sendtag    = 0;
                int receivetag = 0;

                if (!MandBset)
                {
                    fromafarMandB.Clear();
                }

                toafarMandB.Clear();
                myownMandB.Clear();

                int Maxlength2 = NumberofAVectorsUsed * PWCUtility.PointCount_Largest;

                if (oldMaxLength2 != Maxlength2)
                {
                    fromafarAxarray = new double[Maxlength2];
                    toafarAxarray   = new double[Maxlength2];
                    myownAxarray    = new double[Maxlength2];
                    oldMaxLength2   = Maxlength2;
                }
                else
                {
                    Array.Clear(fromafarAxarray, 0, Maxlength2);
                    Array.Clear(toafarAxarray, 0, Maxlength2);
                    Array.Clear(myownAxarray, 0, Maxlength2);
                }

                myownMandB.FirstPoint     = PWCUtility.PointStart_Process;
                myownMandB.NumberofPoints = PWCUtility.PointCount_Process;
                if (PWCUtility.PointCount_Process < PWCUtility.PointCount_Largest)
                {
                    int Acount = 0;
                    for (int countC = 0; countC < localNcent; countC++)
                    {
                        int settozero = PWCUtility.PointCount_Process * localNcent + countC;
                        myownMandB.Marray[settozero] = 0.0;
                        myownMandB.Barray[settozero] = 0.0;
                        if (UsethisCluster[countC] == 0)
                        {
                            continue;
                        }
                        myownAxarray[PWCUtility.PointCount_Process * NumberofAVectorsUsed + Acount] = 0.0;
                        ++Acount;
                    }
                }
                int fromprocess = PWCUtility.MPI_Rank - 1;
                if (fromprocess < 0)
                {
                    fromprocess = PWCUtility.MPI_Size - 1;
                }
                int toprocess = PWCUtility.MPI_Rank + 1;
                if (toprocess > PWCUtility.MPI_Size - 1)
                {
                    toprocess = 0;
                }

                //	First communicationloop is local; then we have MPI_Size transfers of data in  a ring through processes
                for (int MPICommunicationSteps = 0; MPICommunicationSteps < PWCUtility.MPI_Size; MPICommunicationSteps++)
                {
                    if (MPICommunicationSteps == 1)
                    {
                        toafarMandB.FirstPoint     = PWCUtility.PointStart_Process;
                        toafarMandB.NumberofPoints = PWCUtility.PointCount_Process;
                        if (PWCUtility.PointCount_Process < PWCUtility.PointCount_Largest)
                        {
                            int Acount = 0;
                            for (int ClusterIndex = 0; ClusterIndex < localNcent; ClusterIndex++)
                            {
                                int bigindex = PWCUtility.PointCount_Process * localNcent + ClusterIndex;
                                toafarMandB.Marray[bigindex] = myownMandB.Marray[bigindex];
                                toafarMandB.Barray[bigindex] = myownMandB.Barray[bigindex];
                                if (UsethisCluster[ClusterIndex] == 0)
                                {
                                    continue;
                                }
                                toafarAxarray[PWCUtility.PointCount_Process * NumberofAVectorsUsed + Acount] = myownAxarray[PWCUtility.PointCount_Process * NumberofAVectorsUsed + Acount];
                                ++Acount;
                            }
                        }
                    }
                    if (MPICommunicationSteps > 1)
                    {
                        toafarMandB.FirstPoint     = fromafarMandB.FirstPoint;
                        toafarMandB.NumberofPoints = fromafarMandB.NumberofPoints;
                        if (PWCUtility.PointCount_Process < PWCUtility.PointCount_Largest)
                        {
                            int Acount = 0;
                            for (int ClusterIndex = 0; ClusterIndex < localNcent; ClusterIndex++)
                            {
                                int bigindex = PWCUtility.PointCount_Process * localNcent + ClusterIndex;
                                toafarMandB.Marray[bigindex] = fromafarMandB.Marray[bigindex];
                                toafarMandB.Barray[bigindex] = fromafarMandB.Barray[bigindex];
                                if (UsethisCluster[ClusterIndex] == 0)
                                {
                                    continue;
                                }
                                toafarAxarray[PWCUtility.PointCount_Process * NumberofAVectorsUsed + Acount] = fromafarAxarray[PWCUtility.PointCount_Process * NumberofAVectorsUsed + Acount];
                                ++Acount;
                            }
                        }
                    }
                    if (MPICommunicationSteps > 0)
                    {
                        PWCUtility.StartSubTimer(PWCUtility.MPISENDRECEIVEEigenTiming);
                        if (!MandBset)
                        {
                            PWCUtility.MPI_communicator.SendReceive <MPISecPacket>(toafarMandB, toprocess, sendtag, fromprocess, receivetag, out fromafarMandB, out MPISecStatus);
                            MPISecPacket.Membercopy(ref fromafarMandB, ref MandBRepository[MPICommunicationSteps]);
                        }
                        else
                        {
                            fromafarMandB = MandBRepository[MPICommunicationSteps];
                        }
                        PWCUtility.MPI_communicator.SendReceive <double>(toafarAxarray, toprocess, sendtag, fromprocess, receivetag, ref fromafarAxarray, out MPISecStatus);
                        PWCUtility.StopSubTimer(PWCUtility.MPISENDRECEIVEEigenTiming);
                    }

                    // Communication finished -- now update A vector
                    Parallel.For(0, Program.ParallelOptions.MaxDegreeOfParallelism, Program.ParallelOptions, (ThreadNo) =>
                    {
                        //	Start Code calculating power vectors Ax oldAx
                        double[] DiagonalTerm = new double[localNcent];

                        int indexlen   = PWCUtility.PointsperThread[ThreadNo];
                        int beginpoint = PWCUtility.StartPointperThread[ThreadNo] - PWCUtility.PointStart_Process;

                        for (int ProcessPointIndex = beginpoint; ProcessPointIndex < indexlen + beginpoint; ProcessPointIndex++)
                        {   // Loop over Home Indices
                            int betatotal, betastart;
                            if (MPICommunicationSteps == 0)
                            {
                                betatotal  = PWCUtility.PointCount_Process;
                                betastart  = PWCUtility.PointStart_Process;
                                int Acount = 0;
                                for (int ClusterIndex = 0; ClusterIndex < localNcent; ClusterIndex++)
                                {
                                    int bigindex = ProcessPointIndex * localNcent + ClusterIndex;
                                    myownMandB.Marray[bigindex]  = localMalpha_k_[ProcessPointIndex][ClusterIndex];
                                    myownMandB.Barray[bigindex]  = localBalpha_k_[ProcessPointIndex][ClusterIndex];
                                    toafarMandB.Marray[bigindex] = localMalpha_k_[ProcessPointIndex][ClusterIndex];
                                    toafarMandB.Barray[bigindex] = localBalpha_k_[ProcessPointIndex][ClusterIndex];
                                    if (UsethisCluster[ClusterIndex] == 0)
                                    {
                                        continue;
                                    }
                                    int Aindex = ProcessPointIndex * NumberofAVectorsUsed + Acount;
                                    ++Acount;
                                    toafarAxarray[Aindex] = oldAx[ProcessPointIndex][ClusterIndex];
                                    myownAxarray[Aindex]  = oldAx[ProcessPointIndex][ClusterIndex];
                                    vectorclass.Ax[ProcessPointIndex][ClusterIndex] = 0.0;
                                }
                            }
                            else
                            {
                                betatotal = fromafarMandB.NumberofPoints;
                                betastart = fromafarMandB.FirstPoint;
                                if (MPICommunicationSteps != (PWCUtility.MPI_Size - 1))
                                {
                                    int Acount = 0;
                                    for (int ClusterIndex = 0; ClusterIndex < localNcent; ClusterIndex++)
                                    {
                                        int bigindex = ProcessPointIndex * localNcent + ClusterIndex;
                                        toafarMandB.Marray[bigindex] = fromafarMandB.Marray[bigindex];
                                        toafarMandB.Barray[bigindex] = fromafarMandB.Barray[bigindex];
                                        if (UsethisCluster[ClusterIndex] == 0)
                                        {
                                            continue;
                                        }
                                        int Aindex = ProcessPointIndex * NumberofAVectorsUsed + Acount;
                                        ++Acount;
                                        toafarAxarray[Aindex] = fromafarAxarray[Aindex];
                                    }
                                }
                            }

                            for (int ClusterIndex = 0; ClusterIndex < localNcent; ClusterIndex++)
                            {
                                if (UsethisCluster[ClusterIndex] == 0)
                                {
                                    continue;
                                }
                                double tmp = localMalpha_k_[ProcessPointIndex][ClusterIndex] * Mfudge;
                                if (!Subtract_twiceDuplicatedCenter)
                                {
                                    tmp -= tmp * tmp;
                                }
                                // DiagonalTerm[ClusterIndex] = tmp / T;
                                DiagonalTerm[ClusterIndex] = tmp;
                            }

                            for (int betalocal = 0; betalocal < betatotal; betalocal++)
                            {
                                int betafull          = betastart + betalocal;
                                double dijforthiscase = PWCParallelism.getDistanceValue(ProcessPointIndex + PWCUtility.PointStart_Process, betafull);

                                bool PointIndicesEqual = (betafull == (ProcessPointIndex + PWCUtility.PointStart_Process));

                                for (int CenterVectorMu = 0; CenterVectorMu < localNcent; CenterVectorMu++)
                                {   // Start loop over Left Vector Cluster Index
                                    double MalphaMu = localMalpha_k_[ProcessPointIndex][CenterVectorMu];

                                    int AMucount = 0;
                                    if (UsethisCluster[CenterVectorMu] == 0)
                                    {
                                        continue;
                                    }
                                    AMucount++;
                                    for (int CenterVectorLambda = 0; CenterVectorLambda < localNcent; CenterVectorLambda++)
                                    {   // Start Loop over Right Vector Cluster Index
                                        int ALambdacount = 0;
                                        if (UsethisCluster[CenterVectorLambda] == 0)
                                        {
                                            continue;
                                        }
                                        int ALambdaindex = betalocal * NumberofAVectorsUsed + ALambdacount;
                                        ALambdacount++;
                                        if ((Methodology < 4) && (CenterVectorLambda != CenterVectorMu))
                                        {
                                            continue;
                                        }
                                        double MbetaLambda, AxbetaLambda;
                                        if (MPICommunicationSteps == 0)
                                        {
                                            MbetaLambda  = localMalpha_k_[betalocal][CenterVectorLambda];
                                            AxbetaLambda = oldAx[betalocal][CenterVectorLambda];
                                        }
                                        else
                                        {
                                            MbetaLambda  = fromafarMandB.Marray[betalocal * localNcent + CenterVectorLambda];
                                            AxbetaLambda = fromafarAxarray[ALambdaindex];
                                        }

                                        double FirstTerm = 0;
                                        if (PointIndicesEqual && (CenterVectorMu == CenterVectorLambda))
                                        {
                                            FirstTerm = DiagonalTerm[CenterVectorMu];
                                        }
                                        if ((Methodology == 4) && PointIndicesEqual && (CenterVectorMu != CenterVectorLambda))
                                        {
                                            FirstTerm = -MalphaMu * MbetaLambda;
                                            //  FirstTerm = -MalphaMu * MbetaLambda / T;
                                        }
                                        double tmp = 0.0;
                                        for (int CentersSummed = 0; CentersSummed < localNcent; CentersSummed++)
                                        {
                                            double BbetaCenterSummed, MbetaCenterSummed;
                                            if (MPICommunicationSteps == 0)
                                            {
                                                MbetaCenterSummed = localMalpha_k_[betalocal][CentersSummed];
                                                BbetaCenterSummed = localBalpha_k_[betalocal][CentersSummed];
                                            }
                                            else
                                            {
                                                MbetaCenterSummed = fromafarMandB.Marray[betalocal * localNcent + CentersSummed];
                                                BbetaCenterSummed = fromafarMandB.Barray[betalocal * localNcent + CentersSummed];
                                            }
                                            double MMmultiplier;
                                            double Mfudge_CenterCalculated = 1.0;
                                            if (Methodology <= 3)
                                            {
                                                if (CentersSummed == CenterVectorMu)
                                                {
                                                    Mfudge_CenterCalculated = Mfudge;
                                                    if (Subtract_twiceDuplicatedCenter)
                                                    {
                                                        MMmultiplier = 1.0;
                                                    }
                                                    else
                                                    {
                                                        MMmultiplier = (localMalpha_k_[ProcessPointIndex][CentersSummed] * Mfudge_CenterCalculated - 1.0)
                                                                       * (MbetaCenterSummed * Mfudge_CenterCalculated - 1.0);
                                                    }
                                                }
                                                else
                                                {
                                                    if (Subtract_twiceDuplicatedCenter)
                                                    {
                                                        MMmultiplier = 0.0;
                                                        continue;
                                                    }
                                                    else
                                                    {
                                                        MMmultiplier = localMalpha_k_[ProcessPointIndex][CentersSummed] * MbetaCenterSummed;
                                                    }
                                                }
                                            } // End case Methodology <= 3
                                            else
                                            { // Methodology = 4
                                                double DeltaSummedMu     = 0.0;
                                                double DeltaSummedLambda = 0.0;
                                                if (CentersSummed == CenterVectorMu)
                                                {
                                                    DeltaSummedMu = 1.0;
                                                }
                                                if (CentersSummed == CenterVectorLambda)
                                                {
                                                    DeltaSummedLambda = 1.0;
                                                }
                                                MMmultiplier = (localMalpha_k_[ProcessPointIndex][CentersSummed] - DeltaSummedMu) * (MbetaCenterSummed - DeltaSummedLambda);
                                            }

                                            tmp = tmp + (-2.0 * localA_k_[CentersSummed] - BbetaCenterSummed - localBalpha_k_[ProcessPointIndex][CentersSummed] + dijforthiscase) * MMmultiplier / (localC_k_[CentersSummed] * Mfudge_CenterCalculated);
                                        }       // End sum over Summed Centers in Second Derivative Matrix

                                        // double MatrixElement = FirstTerm + ((MalphaMu * MbetaLambda * Mfudge * Mfudge) / (T * T)) * tmp;
                                        double MatrixElement = FirstTerm + ((MalphaMu * MbetaLambda * Mfudge * Mfudge) / T) * tmp;

                                        if (PassIndicator == 1)
                                        {
                                            if (PointIndicesEqual && (CenterVectorMu == CenterVectorLambda))
                                            {
                                                int eigenposition = CenterVectorMu;
                                                if (Methodology == 4)
                                                {
                                                    eigenposition = Dist.PlaceforEigsforMultipleCluster;
                                                }
                                                MatrixElement = Eigenvalues_Pass0[eigenposition] - MatrixElement;
                                            }
                                            else
                                            {
                                                MatrixElement = -MatrixElement;
                                            }
                                        }

                                        vectorclass.Ax[ProcessPointIndex][CenterVectorMu] += MatrixElement * AxbetaLambda;
                                    } // End Loop over Right Matrix Center Indices Lambda
                                }     // End sum over centers (loop over Left Vector Index Mu) in major computation
                            }         // End sum over index beta
                        }             // End loop over index (alpha)
                    });               // End Delegate Code calculating power vectors Ax oldAx
                }                     // End communicationloop

                MandBset = true;
                GlobalReductions.FindVectorDoubleSum Find_sum_t0 = new GlobalReductions.FindVectorDoubleSum(PWCUtility.ThreadCount, localNcent);
                GlobalReductions.FindVectorDoubleSum Find_sum_t1 = new GlobalReductions.FindVectorDoubleSum(PWCUtility.ThreadCount, localNcent);
                GlobalReductions.FindVectorDoubleSum Find_sum_t2 = new GlobalReductions.FindVectorDoubleSum(PWCUtility.ThreadCount, localNcent);

                //	sum over threads to get Power Eigenvalues
                Parallel.For(0, Program.ParallelOptions.MaxDegreeOfParallelism, Program.ParallelOptions, (ThreadNo) =>
                {
                    double[] Accum_t0 = new double[localNcent];
                    double[] Accum_t1 = new double[localNcent];
                    double[] Accum_t2 = new double[localNcent];
                    for (int ClusterIndex = 0; ClusterIndex < localNcent; ClusterIndex++)
                    {
                        Accum_t0[ClusterIndex] = 0.0;
                        Accum_t1[ClusterIndex] = 0.0;
                        Accum_t2[ClusterIndex] = 0.0;
                    }

                    int indexlen   = PWCUtility.PointsperThread[ThreadNo];
                    int beginpoint = PWCUtility.StartPointperThread[ThreadNo] - PWCUtility.PointStart_Process;
                    for (int ProcessPointIndex = beginpoint; ProcessPointIndex < indexlen + beginpoint; ProcessPointIndex++)
                    {
                        double SubtractAverage = 0.0;
                        if (REMOVEZEROEigs == 1)
                        {   // All Clusters used in this case
                            for (int ClusterIndex = 0; ClusterIndex < localNcent; ClusterIndex++)
                            {
                                SubtractAverage += Ax[ProcessPointIndex][ClusterIndex];
                            }
                            SubtractAverage = SubtractAverage / localNcent;
                        }
                        for (int ClusterIndex = 0; ClusterIndex < localNcent; ClusterIndex++)
                        {
                            if (UsethisCluster[ClusterIndex] == 0)
                            {
                                continue;
                            }
                            double tmp = Ax[ProcessPointIndex][ClusterIndex] - SubtractAverage; // Remove null eigenvectors
                            Ax[ProcessPointIndex][ClusterIndex] = tmp;
                            double oldtmp           = oldAx[ProcessPointIndex][ClusterIndex];
                            Accum_t0[ClusterIndex] += tmp * oldtmp;
                            Accum_t1[ClusterIndex] += oldtmp * oldtmp;
                            Accum_t2[ClusterIndex] += tmp * tmp;
                        }
                    }
                    Find_sum_t0.addapoint(ThreadNo, Accum_t0);
                    Find_sum_t1.addapoint(ThreadNo, Accum_t1);
                    Find_sum_t2.addapoint(ThreadNo, Accum_t2);
                });

                Find_sum_t0.sumoverthreadsandmpi();
                Find_sum_t1.sumoverthreadsandmpi();
                Find_sum_t2.sumoverthreadsandmpi();

                double[] AxNormfactor  = new double[localNcent];
                int[]    ActiveAxvalue = new int[localNcent];
                for (int ClusterIndex = 0; ClusterIndex < localNcent; ClusterIndex++)
                {   // ClusterIndex loop checking eigenvalue and status determination for each cluster
                    ActiveAxvalue[ClusterIndex] = UsethisCluster[ClusterIndex];
                    if ((Methodology < 4) && (UsethisCluster[ClusterIndex] == 0))
                    {
                        continue;
                    }
                    if ((Methodology == 4) && (ClusterIndex != Dist.PlaceforEigsforMultipleCluster))
                    {
                        continue;
                    }
                    double[] globalsum_t012 = new double[3];
                    for (int eiglist = 0; eiglist < 3; eiglist++)
                    {
                        globalsum_t012[eiglist] = 0.0;
                    }

                    for (int ClusterSummed = 0; ClusterSummed < localNcent; ClusterSummed++)
                    {   // Cluster Summation for Methodology 4 (CenterSummed == ClusterIndex if Methodology < 4)
                        if ((Methodology < 4) && (ClusterSummed != ClusterIndex))
                        {
                            continue;
                        }

                        if (Methodology < 4)
                        {
                            globalsum_t012[0] = Find_sum_t0.TotalVectorSum[ClusterSummed];
                            globalsum_t012[1] = Find_sum_t1.TotalVectorSum[ClusterSummed];
                            globalsum_t012[2] = Find_sum_t2.TotalVectorSum[ClusterSummed];
                        }   //  End Cluster Summation for Methodology < 4
                        else
                        {
                            double[] globalsum_t012_temp = new double[3];
                            globalsum_t012_temp[0] = Find_sum_t0.TotalVectorSum[ClusterSummed];
                            globalsum_t012_temp[1] = Find_sum_t1.TotalVectorSum[ClusterSummed];
                            globalsum_t012_temp[2] = Find_sum_t2.TotalVectorSum[ClusterSummed];
                            for (int eiglist = 0; eiglist < 3; eiglist++)
                            {
                                globalsum_t012[eiglist] += globalsum_t012_temp[eiglist];
                            }
                        }   //  End Cluster Summation for Methodology 4
                    }

                    double eigenvalue = globalsum_t012[0] / globalsum_t012[1];
                    AxNormfactor[ClusterIndex] = 1.0 / Math.Sqrt(globalsum_t012[2]);

                    //	Check if converged
                    //	Do this in one process ONLY
                    if ((NumPowerIterations > 10) && (eigenvalue > 0.0))
                    { // Arbitrary choice for Number of Power Iterations Cut
                        int somethingtodo = 0;
                        if (PWCUtility.MPI_Rank == 0)
                        { // Decisions can only be made in one process
                            if (Math.Abs(eigenvalue - Eigenvalues_Current[ClusterIndex]) > eigenvalue * Program.eigenvaluechange)
                            {
                                ++somethingtodo;
                            }
                            double delta = globalsum_t012[2] - 2.0 * globalsum_t012[0] * eigenvalue + globalsum_t012[1] * eigenvalue * eigenvalue;   // (Ax- Eigenvalue*Axold)**2
                            if (Math.Abs(delta) > eigenvalue * eigenvalue * Program.eigenvectorchange)
                            {
                                ++somethingtodo;
                            }
                        }   // End Test on Convergence
                        PWCUtility.SynchronizeMPIvariable(ref somethingtodo);

                        if (somethingtodo == 0)
                        {
                            vectorclass.eigenconverged[ClusterIndex] = 1 + NumPowerIterations;
                            UsethisCluster[ClusterIndex]             = 0;
                        }
                    }
                    Eigenvalues_Current[ClusterIndex] = eigenvalue;
                }       // End ClusterIndex loop checking eigenvalue status determination for each cluster

                Parallel.For(0, Program.ParallelOptions.MaxDegreeOfParallelism, Program.ParallelOptions, (ThreadNo) =>
                {       //	Code to normalize Power Eigenvalues
                    int indexlen   = PWCUtility.PointsperThread[ThreadNo];
                    int beginpoint = PWCUtility.StartPointperThread[ThreadNo] - PWCUtility.PointStart_Process;
                    for (int PointIndex = beginpoint; PointIndex < indexlen + beginpoint; PointIndex++)
                    {
                        for (int ClusterIndex = 0; ClusterIndex < localNcent; ClusterIndex++)
                        {
                            double Normfactor;
                            if (Methodology == 4)
                            {
                                Normfactor = AxNormfactor[Dist.PlaceforEigsforMultipleCluster];
                            }
                            else
                            {
                                Normfactor = AxNormfactor[ClusterIndex];
                            }
                            if (ActiveAxvalue[ClusterIndex] == 0)
                            {
                                continue;
                            }
                            vectorclass.oldAx[PointIndex][ClusterIndex] = vectorclass.Ax[PointIndex][ClusterIndex] * Normfactor;
                        }
                    }
                });
            } // End NumPowerIterations loop over Power Iteration Method
            return;
        }     // End PairwiseThread_SecDrv
Example #3
0
        }   // End GetClusterRadius

        // Use LastClusterCenter if Size 0
        public static void FindClusterCenters(bool begin, int[] NearestCentertoPoint, double[] Distance_NearestCentertoPoint, double[][] LastClusterCenter)
        {   // Calculate Cluster Parameters
            GlobalReductions.FindVectorDoubleSum3 FindCenterVectorSums = new GlobalReductions.FindVectorDoubleSum3(DAVectorUtility.ThreadCount,
                                                                                                                   Kmeans.ParameterVectorDimension, Kmeans.Ncent_Global);
            GlobalReductions.FindVectorIntSum    FindCenterSizeSums = new GlobalReductions.FindVectorIntSum(DAVectorUtility.ThreadCount, Kmeans.Ncent_Global);
            GlobalReductions.FindVectorDoubleMax FindClusterRadius  = new GlobalReductions.FindVectorDoubleMax(DAVectorUtility.ThreadCount, Kmeans.Ncent_Global);
            GlobalReductions.FindVectorDoubleSum FindClusterWidth   = new GlobalReductions.FindVectorDoubleSum(DAVectorUtility.ThreadCount, Kmeans.Ncent_Global);
            ;
            Parallel.For(0, Kmeans._parallelOptions.MaxDegreeOfParallelism, Kmeans._parallelOptions, (ThreadIndex) =>
            {
                FindCenterVectorSums.startthread(ThreadIndex);
                FindCenterSizeSums.startthread(ThreadIndex);
                int indexlen   = DAVectorUtility.PointsperThread[ThreadIndex];
                int beginpoint = DAVectorUtility.StartPointperThread[ThreadIndex] - DAVectorUtility.PointStart_Process;
                for (int alpha = beginpoint; alpha < indexlen + beginpoint; alpha++)
                {
                    int ClusterIndex = NearestCentertoPoint[alpha];
                    if ((ClusterIndex >= Kmeans.Ncent_Global) || (ClusterIndex < 0))
                    {
                        Exception e = DAVectorUtility.SALSAError("Illegal Cluster Index " + ClusterIndex.ToString() + " Number " + Kmeans.Ncent_Global.ToString()
                                                                 + " Point " + (alpha + DAVectorUtility.PointStart_Process).ToString() + " Rank " + DAVectorUtility.MPI_Rank.ToString());
                        throw (e);
                    }
                    FindCenterVectorSums.addapoint(ThreadIndex, PointPosition[alpha], ClusterIndex);
                    FindCenterSizeSums.addapoint(ThreadIndex, 1, ClusterIndex);
                    if (!begin)
                    {
                        FindClusterRadius.addapoint(ThreadIndex, Distance_NearestCentertoPoint[alpha], ClusterIndex);
                        FindClusterWidth.addapoint(ThreadIndex, Distance_NearestCentertoPoint[alpha] * Distance_NearestCentertoPoint[alpha], ClusterIndex);
                    }
                } // End loop over Points
            });   // End Sum over Threads

            FindCenterVectorSums.sumoverthreadsandmpi();
            FindCenterSizeSums.sumoverthreadsandmpi();
            if (!begin)
            {
                FindClusterRadius.sumoverthreadsandmpi();
                FindClusterWidth.sumoverthreadsandmpi();
            }
            Kmeans.AverageRadius       = 0.0;
            Kmeans.AverageWidth        = 0.0;
            Kmeans.AverageCenterChange = 0.0;

            if (Kmeans.UseParallelismoverCenters)
            {   // Centers Parallel over Threads NOT nodes
                double[] AccumulateRadius       = new double[DAVectorUtility.ThreadCount];
                double[] AccumulateWidth        = new double[DAVectorUtility.ThreadCount];
                double[] AccumulateCenterChange = new double[DAVectorUtility.ThreadCount];
                for (int ThreadIndex = 0; ThreadIndex < DAVectorUtility.ThreadCount; ThreadIndex++)
                {
                    AccumulateRadius[ThreadIndex]       = 0.0;
                    AccumulateWidth[ThreadIndex]        = 0.0;
                    AccumulateCenterChange[ThreadIndex] = 0.0;
                }

                Parallel.For(0, Kmeans._parallelOptions.MaxDegreeOfParallelism, Kmeans._parallelOptions, (ThreadIndex) =>
                {
                    int indexlen   = KmeansTriangleInequality.LocalParallel_CentersperThread[ThreadIndex];
                    int beginpoint = KmeansTriangleInequality.LocalParallel_StartCenterperThread[ThreadIndex];
                    for (int CenterIndex = beginpoint; CenterIndex < indexlen + beginpoint; CenterIndex++)
                    {
                        Kmeans.ClusterSize[CenterIndex] = FindCenterSizeSums.TotalVectorSum[CenterIndex];

                        if (Kmeans.ClusterSize[CenterIndex] > 0)
                        {
                            double divisor = 1.0 / (double)Kmeans.ClusterSize[CenterIndex];
                            for (int VectorIndex = 0; VectorIndex < Kmeans.ParameterVectorDimension; VectorIndex++)
                            {
                                int totalindex = VectorIndex + CenterIndex * Kmeans.ParameterVectorDimension;
                                Kmeans.ClusterCenter[CenterIndex][VectorIndex] = FindCenterVectorSums.TotalVectorSum[totalindex] * divisor;
                            }

                            if (!begin)
                            {
                                Kmeans.ClusterRadius[CenterIndex]    = FindClusterRadius.TotalVectorMax[CenterIndex];
                                Kmeans.ClusterWidth[CenterIndex]     = FindClusterWidth.TotalVectorSum[CenterIndex];
                                AccumulateRadius[ThreadIndex]       += Kmeans.ClusterRadius[CenterIndex];
                                AccumulateWidth[ThreadIndex]        += Kmeans.ClusterWidth[CenterIndex];
                                AccumulateCenterChange[ThreadIndex] += DAVectorParallelism.getNOTSquaredUNScaledDistancebetweenVectors(Kmeans.ClusterCenter[CenterIndex], LastClusterCenter[CenterIndex]);
                            }
                        }
                        else
                        {   // Zero Size Cluster
                            if (begin)
                            {
                                Exception e = DAVectorUtility.SALSAError("Empty Input Cluster " + CenterIndex.ToString() + " Number " + Kmeans.Ncent_Global.ToString()
                                                                         + " Rank " + DAVectorUtility.MPI_Rank.ToString());
                                throw (e);
                            }
                            for (int VectorIndex = 0; VectorIndex < Kmeans.ParameterVectorDimension; VectorIndex++)
                            {
                                Kmeans.ClusterCenter[CenterIndex][VectorIndex] = LastClusterCenter[CenterIndex][VectorIndex];
                            }
                            Kmeans.ClusterRadius[CenterIndex] = 0.0;
                            Kmeans.ClusterWidth[CenterIndex]  = 0.0;
                        }
                    }
                }); // End Sum over Threads
                if (!begin)
                {
                    for (int ThreadIndex = 0; ThreadIndex < DAVectorUtility.ThreadCount; ThreadIndex++)
                    {
                        Kmeans.AverageRadius       += AccumulateRadius[ThreadIndex];
                        Kmeans.AverageWidth        += AccumulateWidth[ThreadIndex];
                        Kmeans.AverageCenterChange += AccumulateCenterChange[ThreadIndex];
                    }
                }
            }

            else
            {   // Centers Sequential
                for (int CenterIndex = 0; CenterIndex < Kmeans.Ncent_Global; CenterIndex++)
                {
                    Kmeans.ClusterSize[CenterIndex] = FindCenterSizeSums.TotalVectorSum[CenterIndex];

                    if (Kmeans.ClusterSize[CenterIndex] > 0)
                    {
                        double divisor = 1.0 / (double)Kmeans.ClusterSize[CenterIndex];
                        for (int VectorIndex = 0; VectorIndex < Kmeans.ParameterVectorDimension; VectorIndex++)
                        {
                            int totalindex = VectorIndex + CenterIndex * Kmeans.ParameterVectorDimension;
                            Kmeans.ClusterCenter[CenterIndex][VectorIndex] = FindCenterVectorSums.TotalVectorSum[totalindex] * divisor;
                        }

                        if (!begin)
                        {
                            Kmeans.ClusterRadius[CenterIndex] = FindClusterRadius.TotalVectorMax[CenterIndex];
                            Kmeans.ClusterWidth[CenterIndex]  = FindClusterWidth.TotalVectorSum[CenterIndex];
                            Kmeans.AverageRadius       += Kmeans.ClusterRadius[CenterIndex];
                            Kmeans.AverageWidth        += Kmeans.ClusterWidth[CenterIndex];
                            Kmeans.AverageCenterChange += DAVectorParallelism.getNOTSquaredUNScaledDistancebetweenVectors(Kmeans.ClusterCenter[CenterIndex], LastClusterCenter[CenterIndex]);
                        }
                    }
                    else
                    {
                        if (begin)
                        {
                            Exception e = DAVectorUtility.SALSAError("Empty Input Cluster " + CenterIndex.ToString() + " Number " + Kmeans.Ncent_Global.ToString()
                                                                     + " Rank " + DAVectorUtility.MPI_Rank.ToString());
                            throw (e);
                        }
                        Kmeans.ClusterRadius[CenterIndex] = 0.0;
                        Kmeans.ClusterWidth[CenterIndex]  = 0.0;
                        for (int VectorIndex = 0; VectorIndex < Kmeans.ParameterVectorDimension; VectorIndex++)
                        {
                            Kmeans.ClusterCenter[CenterIndex][VectorIndex] = LastClusterCenter[CenterIndex][VectorIndex];
                        }
                    }
                }   // End Sequential Center Loop
            }

            if (begin)
            {
                return;
            }
            Kmeans.AverageCenterChange = Kmeans.AverageCenterChange / Kmeans.Ncent_Global;
            Kmeans.AverageRadius       = Kmeans.AverageRadius / Kmeans.Ncent_Global;
            Kmeans.AverageWidth        = Kmeans.AverageWidth / DAVectorUtility.PointCount_Global;
            return;
        }   // End FindClusterCenters(int[] NearestCentertoPoint, double[][] LastClusterCenter)