function MPI_COMM_WORLD = MatMPI_Comm_init(n_proc,machines)
% MatMPI_Comm_init  -  Creates generic communicator.
%
%   MPI_COMM_WORLD = MatMPI_Comm_init(n_proc,machines)
%

  % Get number of machines to launch on.
  n_machines = size(machines,2);
  n_m = max(n_machines,1);

  % Set default target machine.
  host = getenv('HOST');
  machine = host;

  % Initialize comm.
  MPI_COMM_WORLD.rank = -1;
  MPI_COMM_WORLD.size = n_proc;
  MPI_COMM_WORLD.save_message_flag = 0;
  MPI_COMM_WORLD.group = (1:n_proc)-1;
  MPI_COMM_WORLD.machine_id = zeros(1,n_proc);

  % Initialize machine database.
  machine_db.n_machine = n_m;			% Number of machines.
  machine_db.type = cell(1,n_m);		% Unix or Windows.
  machine_db.machine = cell(1,n_m);		% Machine names.
  machine_db.dir = cell(1,n_m);			% Communication directory.
  machine_db.matlab_command = cell(1,n_m);	% Matlab command.
  machine_db.remote_launch = cell(1,n_m);	% Remote launch command.
  machine_db.remote_flags = cell(1,n_m);	% Remote launch flags.
  machine_db.n_proc = zeros(1,n_m);		% # processes on this machine.
  machine_db.id_start = zeros(1,n_m);		% Start index.
  machine_db.id_stop = zeros(1,n_m);		% Stop index.

  % Start setting up machine id.
  for i_rank=0:n_proc-1
    i_machine = mod(i_rank,n_m) + 1;
    machine_db.n_proc(1,i_machine) = machine_db.n_proc(1,i_machine) + 1;
  end

  % Get possibly user settings.
  machine_db_settings = MatMPI_Comm_settings;

  % Set machine_db values.
  for i=1:n_m
    machine_db.type{1,i} = machine_db_settings.type;
    machine_db.machine{1,i} = host;
    machine_db.dir{1,i} = [pwd '/MatMPI'];
    machine_db.matlab_command{1,i} = machine_db_settings.matlab_command;
    machine_db.remote_launch{1,i} = machine_db_settings.remote_launch;
    machine_db.remote_flags{1,i} = machine_db_settings.remote_flags;
    if (i == 1) 
      machine_db.id_start(1,i) = 1;
      machine_db.id_stop(1,i) = machine_db.id_start(1,i) + machine_db.n_proc(1,i) -1;
    else
      machine_db.id_start(1,i) = machine_db.id_stop(1,i-1) + 1;
      machine_db.id_stop(1,i) = machine_db.id_start(1,i) + machine_db.n_proc(1,i) -1;
    end

    id_start = machine_db.id_start(1,i);
    id_stop = machine_db.id_stop(1,i);

    MPI_COMM_WORLD.machine_id(1,id_start:id_stop) = i;

    % Check if there is a machines list.
    if (n_machines > 0)
      machine = machines{i};
      machine_db.machine{1,i} = machine;

      % Check if there is a directory appended.
      dir_sep = findstr(machine,':');
      if (dir_sep)
        machine_piece = machine(1,1:dir_sep-1);
        dir_piece = machine(1,(dir_sep+1):end);
        machine_db.machine{1,i} = machine_piece;
        machine_db.dir{1,i} = dir_piece;
      end
    end
  end

  % Add machine_db to communicator.
  MPI_COMM_WORLD.machine_db = machine_db;

  % Write out.
  comm_mat_file = 'MatMPI/MPI_COMM_WORLD.mat';
  save(comm_mat_file,'MPI_COMM_WORLD');

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% MatlabMPI
% Dr. Jeremy Kepner
% MIT Lincoln Laboratory
% kepner@ll.mit.edu
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Copyright 2002 Massachusetts Institute of Technology
% 
% Permission is herby granted, without payment, to copy, modify, display
% and distribute this software and its documentation, if any, for any
% purpose, provided that the above copyright notices and the following
% three paragraphs appear in all copies of this software.  Use of this
% software constitutes acceptance of these terms and conditions.
%
% IN NO EVENT SHALL MIT BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
% SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
% THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF MIT HAS BEEN ADVISED OF THE
% POSSIBILITY OF SUCH DAMAGE.
% 
% MIT SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTIES INCLUDING,
% BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
% FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
%
% THIS SOFTWARE IS PROVIDED "AS IS," MIT HAS NO OBLIGATION TO PROVIDE
% MAINTENANCE, SUPPORT, UPDATE, ENHANCEMENTS, OR MODIFICATIONS.

