public final void sumOverThreadsAndMPI() {
      for (int ThreadNo = 0; ThreadNo < NumberofThreads; ThreadNo++) {
        if (IndexValue[ThreadNo] < 0) {
          continue;
        }

        TotalNumberofPoints += NumberofPoints[ThreadNo];
        if (MinMaxPointer != 0) {
          if ((TotalIndexValue >= 0) && (TotalMaxOrMin > MaxOrMinvalue[ThreadNo])) {
            continue;
          }
        } else {
          if ((TotalIndexValue >= 0) && (TotalMaxOrMin <= MaxOrMinvalue[ThreadNo])) {
            continue;
          }
        }

        TotalMaxOrMin = MaxOrMinvalue[ThreadNo];
        TotalIndexValue = IndexValue[ThreadNo];
      }
      if (SALSAUtility.MPI_Size > 1) {
        SALSAUtility.StartSubTimer(SALSAUtility.MPIREDUCETiming1);
        if (MinMaxPointer != 0) {
          // Note - MPI Call - Allreduce - MPIReducePlusIndex - max with index
          salsa.mpi.MPIReducePlusIndex result =
              SALSAUtility.mpiOps.allReduce(
                  new salsa.mpi.MPIReducePlusIndex(TotalIndexValue, TotalMaxOrMin),
                  salsa.mpi.MPIReducePlusIndex.Op.MAX_WITH_INDEX);
          TotalMaxOrMin = result.getValue();
          TotalIndexValue = result.getIndex();
        } else {
          // Note - MPI Call - Allreduce - MPIReducePlusIndex - min with index
          salsa.mpi.MPIReducePlusIndex result =
              SALSAUtility.mpiOps.allReduce(
                  new salsa.mpi.MPIReducePlusIndex(TotalIndexValue, TotalMaxOrMin),
                  salsa.mpi.MPIReducePlusIndex.Op.MIN_WITH_INDEX);
          TotalMaxOrMin = result.getValue();
          TotalIndexValue = result.getIndex();
        }
        // Note - MPI Call - Allreduce - double - sum
        TotalNumberofPoints = SALSAUtility.mpiOps.allReduce(TotalNumberofPoints, MPI.SUM);
        SALSAUtility.StopSubTimer(SALSAUtility.MPIREDUCETiming1);
      }
    }
    public final void sumOverThreadsAndMPI() {

      for (int storeloop = 0; storeloop < Numbertofind; storeloop++) {
        TotalMinValue[storeloop] = -1.0;
        TotalIndexValue[storeloop] = -1;
      }
      TotalWorst = -1;
      for (int ThreadNo = 0; ThreadNo < NumberofThreads; ThreadNo++) {
        TotalNumberofPoints += NumberofPoints[ThreadNo];
        for (int storeloop = 0; storeloop < Numbertofind; storeloop++) {
          if (IndexValuebythread[ThreadNo][storeloop] < 0) {
            continue; // End this thread
          }
          tangible.RefObject<Integer> tempRef_TotalWorst = new tangible.RefObject<>(TotalWorst);
          FindMinimumSet(
              MinValuebythread[ThreadNo][storeloop],
              IndexValuebythread[ThreadNo][storeloop],
              tempRef_TotalWorst,
              TotalMinValue,
              TotalIndexValue,
              Numbertofind);
          TotalWorst = tempRef_TotalWorst.argValue;
        }
      }
      if (SALSAUtility.MPI_Size > 1) {
        SALSAUtility.StartSubTimer(SALSAUtility.MPIREDUCETiming1);
        // Note - MPI Call - Allreduce - double - sum
        TotalNumberofPoints = SALSAUtility.mpiOps.allReduce(TotalNumberofPoints, MPI.SUM);
        SALSAUtility.StopSubTimer(SALSAUtility.MPIREDUCETiming1);
      }
      // Sort in absolute order and accumulate over processes. This takes Numbertofindsteps
      for (int OrderLoop = 0; OrderLoop < Numbertofind; OrderLoop++) {
        int localindex = -1; // unset
        double localvalue = -1.0;
        int loopused = -1;
        for (int internalloop = 0; internalloop < Numbertofind; internalloop++) { // Find minimum
          if (TotalIndexValue[internalloop] < 0) {
            continue;
          }
          if ((localindex < 0) || (TotalMinValue[internalloop] < localvalue)) {
            localindex = TotalIndexValue[internalloop];
            localvalue = TotalMinValue[internalloop];
            loopused = internalloop;
          }
        }
        int oldlocalindex = localindex;
        if (SALSAUtility.MPI_Size > 1) {
          SALSAUtility.StartSubTimer(SALSAUtility.MPIREDUCETiming1);
          // Note - MPI Call - Allreduce - MPIReducePlusIndex - min with index
          salsa.mpi.MPIReducePlusIndex result =
              SALSAUtility.mpiOps.allReduce(
                  new salsa.mpi.MPIReducePlusIndex(localindex, localvalue),
                  salsa.mpi.MPIReducePlusIndex.Op.MIN_WITH_INDEX);
          localvalue = result.getValue();
          localindex = result.getIndex();
          SALSAUtility.StopSubTimer(SALSAUtility.MPIREDUCETiming1);
        }

        OrderedMinValue[OrderLoop] = localvalue;
        OrderedIndexValue[OrderLoop] = localindex;
        if ((oldlocalindex >= 0) && (OrderedIndexValue[OrderLoop] == oldlocalindex)) {
          TotalIndexValue[loopused] = -1;
          TotalMinValue[loopused] = -1.0;
        }
      } // Loop over Order Loop
    }