/// <summary>
        /// Initializes a new instance of the <see cref="BaseGriddedCatchmentObjectiveEvaluator"/> class.
        /// </summary>
        /// <param name="globalDefinitionFileInfo">The global definition file info.</param>
        /// <param name="objectivesDefinitionFileInfo">The objectives definition file info.</param>
        /// <param name="rank">The rank of the process in the 'world'</param>
        /// <param name="size">World communicator size</param>
        /// <param name="worldCommunicator">The world communicator</param>
        protected BaseGriddedCatchmentObjectiveEvaluator(FileInfo globalDefinitionFileInfo, FileInfo objectivesDefinitionFileInfo, int rank, int size, IIntracommunicatorProxy worldCommunicator)
        {
            // funny smell: WorldRank and rank are the same thing, always. Should remove one.
            this.rank  = rank;
            this.size  = size;
            WorldRank  = GetWorldRank();
            IsFirstRun = true;

            if (IsMaster && GetWorldSize() < 2)
            {
                throw new ConfigurationException("At least 2 MPI processes are required to run this application.");
            }

            ObjectiveDefinitionFileName = objectivesDefinitionFileInfo.FullName;

            Log.DebugFormat("Rank {0}: Loading global definition", WorldRank);

            //Added by Bill Wang on 27/10/2014 to read split catchment-based calibration definition files
            if (globalDefinitionFileInfo.FullName.EndsWith(".csv", true, null))
            {
                StreamReader sr = null;
                GlobalDefinition = new GlobalDefinition();
                try
                {
                    sr = new StreamReader(globalDefinitionFileInfo.FullName);
                    sr.ReadLine(); //skip the header line
                    for (string line = sr.ReadLine(); line != null; line = sr.ReadLine())
                    {
                        FileInfo         catchmentFileInfo = new FileInfo(line.Split(new char[] { ',' })[1]);
                        GlobalDefinition catchmentDef      = SerializationHelper.XmlDeserialize <GlobalDefinition>(catchmentFileInfo);
                        foreach (var cat in catchmentDef.Catchments)
                        {
                            GlobalDefinition.AddCatchment(cat);
                        }
                    }
                }
                catch (Exception e)
                {
                    Log.Error(e.ToString());
                    throw e;
                }
                finally
                {
                    if (sr != null)
                    {
                        sr.Close();
                    }
                }
            }
            else
            {
                GlobalDefinition = SerializationHelper.XmlDeserialize <GlobalDefinition>(globalDefinitionFileInfo);
            }

            Log.DebugFormat("Rank {0}: global definition complete", WorldRank);

            world = worldCommunicator;
        }
        /// <summary>
        /// Creates the catchment communicators.
        /// </summary>
        /// <param name="workAllocator">The work allocator.</param>
        private void CreateCommunicators(IWorkAllocator workAllocator)
        {
            // create the communicators (creating communicators is a collective operation, all processes that belong to the new communicator
            // must participate in the call).
            // It is also important that all processes create the communicators in the same order to avoid deadlock
            // There is one communicator per catchment
            Log.DebugFormat("Rank {0}: Creating communicators", WorldRank);

            // we need to sort the list of catchments by catchment CatchmentId.
            // All processes must have the same catchment order or they can deadlock when creating communicators that span processes.
            GlobalDefinition.SortCatchmentsById();

            foreach (CatchmentDefinition catchment in GlobalDefinition)
            {
                Log.DebugFormat("Rank {0}: catchment {1} Creating communicator for {2} processes", WorldRank, catchment.Id, workAllocator.RanksByCatchment[catchment.Id].Count);
                IGroupProxy catchmentGroup = CreateGroup(workAllocator.RanksByCatchment[catchment.Id].ToArray());
                Log.DebugFormat("Rank {0}: Catchment group created, size = {1}", WorldRank, catchmentGroup.Size);
                IIntracommunicatorProxy catchmentCommunicator = CreateIntracommunicatorProxy(catchmentGroup);
                if (catchmentCommunicator != null)
                {
                    Log.DebugFormat("Rank {0}: Communicator created, rank = {1} size = {2}", WorldRank, catchmentCommunicator.GetRank(this.WorldRank), catchmentCommunicator.Size);
                }
                else
                {
                    Log.DebugFormat("Rank {0}: Communicator created, I am not a member", WorldRank);
                }

                // catchmentCommunicator will be null if the current rank is not a member of the catchmentGroup.
                // This is OK, as each rank only requires the communicators for catchments it is involved in.
                if (catchmentCommunicator != null)
                {
                    Debug.Assert(workAllocator.RanksByCatchment[catchment.Id].Contains(WorldRank));
                    communicatorsByCatchmentId.Add(catchment.Id, catchmentCommunicator);

#if CELL_WEIGHTED_SUMS
                    // If I am the catchment coordinator for at least one catchment, then I will need the dictionary of cached
                    // catchment statistics evaluators
                    if (catchmentCommunicator.GetRank(this.WorldRank) == 0)
                    {
                        Log.DebugFormat("Rank {0}: I am catchment coordinator. Creating stats evaluator cache.", WorldRank);

                        // count how often this process acts as catchment coordinator
                        CatchmentCoordinatorCount++;

                        // create the statistics evaluator cache
                        if (CatchmentStatisticsEvaluatorCache == null)
                        {
                            CatchmentStatisticsEvaluatorCache = new Dictionary <string, CatchmentStatisticsEvaluator <ICloneableSimulation, MpiSysConfig> >();
                        }
                    }
#endif
                }
                else
                {
                    Debug.Assert(!workAllocator.RanksByCatchment[catchment.Id].Contains(WorldRank));
                }
            }
        }
        protected Allocator(GlobalDefinition globalDefinition, IIntracommunicatorProxy communicator)
        {
            if (globalDefinition == null)
            {
                throw new ArgumentNullException("globalDefinition");
            }

            this.communicator = communicator;
            GlobalDef         = globalDefinition;
        }
 public BalancedCellCountAllocator(GlobalDefinition globalDefinition, IIntracommunicatorProxy communicator)
     : base(globalDefinition, communicator)
 {
 }