#! perl -w
#==============================================================================
# @(#) $Id: cfx5solve.pl 136402 2016-07-07 12:53:14Z cjstaple $
#------------------------------------------------------------------------------
##
## Name:
##
## cfx5solve
##
## Purpose:
##
## Run the ANSYS CFX Solver or the ANSYS CFX Solver Manager.
##
## If no Solver Input File is specified on the command line the
## ANSYS CFX Solver Manager will be started to allow you to select an ANSYS 
## CFX Solver Input File and then run the ANSYS CFX Solver. Otherwise the 
## ANSYS CFX Solver will be run directly unless the -interactive option is 
## also specified on the command line.
##
## Synopsis:
#S
#S cfx5solve -def <Solver Input File> [<options>]
#S
#S cfx5solve -mdef <multi-configuration Solver Input File> [<options>]
#S           [-config <configname> [<config options>]]...
#S
## []  denotes a discretionary option.
## |   separates mutually exclusive options.
## ... following an option indicates that it may be repeated
## <>  denotes that substitution of a suitable value is required.
##     All other options are keywords, some of which have a short form.
##
## Options:
## 
## Options to cfx5solve may be reordered where necessary. If an option 
## is specified multiple times (e.g. for the same configuration) the 
## option on the right will override those to its left.
##

# get the standard ANSYS CFX library directory

BEGIN {
  if ($0 =~ m!^([a-z]:)?[\\/]!i) {
    # it's an absolute path, use it as-is
    (my $nd=$0) =~ s!(perllib[\\/])?[^\\/]*$!!i;
    unshift @INC, "$nd/perllib";
  } else {
    # wrap this in an eval, and if it fails, pray ... for example,
    # this can fail on Windows if we're running off a share.
    eval {
      require FindBin;
      FindBin->import();
      unshift @INC, "$FindBin::Bin/perllib";
      push @INC, $FindBin::Bin;
    };
    warn $@ if $@;
  }
  if (defined $ENV{CFX_LOCAL_PERLLIB}) {
     unshift @INC, $ENV{CFX_LOCAL_PERLLIB};
  }

}

#
# Generate an unique session ID for the ANSYS help system.
#
if(! $ENV{ANSHELP_SESSION_ID})
{
	srand (time ^ $$ ^ unpack "%L*", rand());
	my $ANSHELP_SESSION_ID = "";
	for ($i = 1; $i <= 64; $i++)
	{
		$ANSHELP_SESSION_ID = $ANSHELP_SESSION_ID . sprintf("%x", int(rand(16)));
	}
	$ENV{ANSHELP_SESSION_ID} = $ANSHELP_SESSION_ID;
}

use CFX5::Init;
CFX5::Init::init();

use vars qw($CVSVersion);
sub BEGIN {
  $CVSVersion='@(#) $Id: cfx5solve.pl 136402 2016-07-07 12:53:14Z cjstaple $\n';
}

use strict;

use CFX5::Output qw(:all);
use CFX5::Config qw(%Config setconf export_conf query_conf append_to_libpath prepend_to_libpath check_gui_support);
use CFX5::PrintConfig;

use CFX5::CmdLine qw(:util parse_cmdline %StandardArgs %MandatoryArgs);

use CFX5::PathManip qw(join_file split_file fullpath basename dirname abspath change_cwd);
use CFX5::FileTests;
use CFX5::FileOps qw(append_to_file);
use CFX5::PkgLoader qw(cfx5_require);

use CFX5::ExitRoutines qw(:tidyup);

use CFX5::Commands qw(do_cmd do_cmd_quiet handle_rv parse_rv do_input_cmd);

use CFX5::Simulation;
use CFX5::Simulation::SimSettings;

use CFX5::CCLI qw(export_parser_conf);

use CFX5::Parallel::MPI;
use CFX5::CUEI;

#
# read the configuration
#
CFX5::Config::read_config();

#
# Now parse the command line.  We initialise a CFX5::Job object and
# set the settings directly on that, even if we're running the solver
# manager; this means that, in the future, we can pass any command
# line arguments onto the SM via CCL.
#
use vars qw($batch $sim $print_ccl $solvman_use_wish
            $clean_stdout @monitor $state_on_stdin $wid $control_port
            @lic_args @passdown_args $config %configsmopts);

# CD to the full path of the current directory to remove any symlinks
use Cwd qw(cwd);
change_cwd(cwd());

my %configccl;
my $default_configccl_is_single=undef;

#
#===============================================================================
# Command line option declaration guidelines
#===============================================================================
# - please put the base command line option first, followed by any
#   options that are aliased to it (indent these) 
#===============================================================================
#
my %cmdline_options=(
   
    #===========================================================================
    # Generic options and handlers to passdown to configurations 
    # All configuration or a specific config
    '-_optnoarg'  => sub { $sim->set_config_option($config, $_[0], 1); },
    '-_optarg+'   => sub { $sim->set_config_option($config, $_[0], $_[1]); },
    # Single config only
    '-_optscnoarg' => sub {
       if($sim->singleconfig()){ $sim->set_config_option($config, $_[0], 1); }
       else { _error("$_[0] is not valid for multiconfig cases"); }
    },
    '-_optscarg+' => sub {
       if($sim->singleconfig()){ $sim->set_config_option($config, $_[0], $_[1]); }
       else { _error("$_[0] is not valid for multiconfig cases"); }
    },
    # A specific config only
    '-_optacnoarg'=> sub {
       if($sim->singleconfig() or defined $config){
         $sim->set_config_option($config, $_[0], 1);
       }
       else {
         _error("$_[0] is not valid unless a configuration has been specified");
       }
    },
    '-_optacarg+' => sub {
       if($sim->singleconfig() or defined $config){
         if ($sim->have_config_option($config, $_[0])) {
           if ($sim->singleconfig()) {
             _warn("Option $_[0] or one of its aliases has been specified more than once. Only the last instance will take effect.");
           }
           else {
             _warn("Option $_[0] or one of its aliases has been specified more than once for configuration $config. Only the last instance will take effect.");
           }
         }
         $sim->set_config_option($config, $_[0], $_[1]);
       }
       else {
         _error("$_[0] is not valid unless a configuration has been specified");
       }
    },
    # Multifield options
    '-_optmfnoarg' => sub {
      if($sim->singleconfig()){
        $sim->set_config_option($config, $_[0], 1);
      }
      else {
        _error("ANSYS Multifield is not supported for multiconfig cases. Argument was $_[0]");
      }
    },
    '-_optmfarg_2-' => sub {
      if($sim->singleconfig()){
        $sim->set_config_option($config, $_[0], $_[1]);
      }
      else {
        _error("ANSYS Multifield is not supported for multiconfig cases. Argument was $_[0] $_[1]");
      }
    },
    '-_optmfarg+'  => sub {
      if($sim->singleconfig()){
        if ($sim->have_config_option($config, $_[0])) {
          _warn("Option $_[0] or one of its aliases has been specified more than once. Only the last instance will take effect.");
        }
        $sim->set_config_option($config, $_[0], $_[1]);
      }
      else {
        _error("ANSYS Multifield is not supported for multiconfig cases. Argument was $_[0] $_[1]");
      }
    },
    # CCL Parsing
    '-_parseccl' => sub {
       $sim->apply_ccl_auto($configccl{0}, $default_configccl_is_single);
    },
    '-_parse_configccl' => sub {
      $sim->apply_ccl_config($configccl{$config},$config);
    },
    
##-------------------------------------------------------------------------
## GENERAL
##-------------------------------------------------------------------------
##
#A -batch
##     Run the ANSYS CFX Solver in batch mode (i.e. without starting the
##     ANSYS CFX Solver Manager). 
    '-batch'              =>\$batch, 
##
#A -chdir <directory>
##     Set the working directory as specified.
    '-chdir+'             => sub {
      change_cwd($_[1])
        or _abort("Unable to change the working directory to $_[1]: $!");
    },
#
#U -custom-data-dir <path>
    '-custom-data-dir'    => sub {},
##
#A -check-only
##     When running in batch mode, this will cause cfx5solve to verify
##     its options, but exit before starting any processes, and is
##     mostly for use by the ANSYS CFX Solver Manager.
    '-check-only'         => sub { $sim->check_only(1) },
#
#U -check-for-gui
    '-check-for-gui'      => sub { $sim->check_for_gui(1) },
#
#U -check-print
#      Same as using -check-only and -print-ccl.
    '-check-print'        => sub { $sim->check_only(1); $print_ccl=1; },
#
#U  -control-port <port number for solver manager / WB communication>
    '-control-port+'      => \$control_port,
#
#U -debug-prompt
    '-debug-prompt'       => '-_optnoarg',
##
#U -debug-prompt-user
    '-debug-prompt-user'  => '-_optnoarg',
##
#A -display <display>
##     Use the X11 server <display> instead of the X11 server 
##     defined by the DISPLAY environment variable.
#
#U -file-comms <file>
    '-file-comms+'        => sub { CFX5::Output::CCL::ccl_file_comms(abspath($_[1])); },
##
#A -interactive
#A -int
#A -manager
##     Run the interactive ANSYS CFX Solver Manager to start a new run
##     and/or manage or monitor an existing run.
    '-interactive'        => '-manager',
      '-int'              => '-manager',
    '-manager'            => sub { $batch=0; },
#U -local
#U     Rather than using the central version of CFX-SolverManager, assume that
#U     the current directory is the root of a locally-built version
#U     and run from that.
   '-local'           => \$Config{CUE_ISLOCAL},
#U -local-root
#U     Rather than using the central version of CFX-SolverManager, assume that
#U     the specified directory is the root of a locally-built version
#U     and run from that.
   '-local-root+'   => sub {
       $Config{CUE_ISLOCAL}=1;
       conf_datadir(\$Config{CUE_ROOT}, "Local CUE root directory %%", @_);
   },
##
#A -monitor <file>
##     When starting the Solver Manager, monitor the run represented
##     by <file>, which may be an ANSYS CFX Results File or Output File.
    '-monitor+'           => \@monitor,
#
#U -monitor-on-stdin    
    '-monitor-on-stdin'   => sub{ $state_on_stdin='-monitor-on-stdin'; },
##
#A -output-summary-option <option>  
##     Specify the job summary format in the solver output file.
##     <option> may be set to:
##     0: minimal
##     1: terse format (default, no information per partition)
##     2: compact format (one line per partition)
##     3: verbose format (default prior to CFX-15.0)
    '-output-summary-option+'=> '-_optarg',
#
#U -print-ccl
    '-print-ccl'          =>\$print_ccl,
#
#U -send-state-on-stdin    
    '-send-state-on-stdin'=> sub{ $state_on_stdin='-state-on-stdin'; },
#
#U -stdout-comms    
#
#U  -wid <window ID in which to embed CFX-Pre window>
    '-wid+'               => \$wid,
##
#A -verbose
#A -v
##     Specifying this option may result in additional output being sent to 
##     the Unix "standard output" file (normally the screen).
##
##-------------------------------------------------------------------------
## CFX RUN SPECIFICATION
##-------------------------------------------------------------------------
##
#A -bak-elapsed-time <elapsed time frequency>
#A -baket <elapsed time frequency>
##     This will cause the ANSYS CFX Solver to write a backup file every 
##     <elapsed time frequency> minutes, hours, seconds, etc... Elapsed
##     time must be in quotes and have units in square brackets.
##     eg: -baket "10 [min]" or -baket "5 [hr]"
    '-bak-elapsed-time+'  => '-_optacarg',
      '-baket+'           => '-bak-elapsed-time',
##
#A -bg-ccl <file>
##     Reads Command Language from the named file, and uses it to
##     provide defaults for the current run.  If the file specifies a
##     definition file for the run, the command language contained in
##     that definition file will take precedence over that supplied.
##     See also -ccl.
#      NOTE: This option is handled earlier in this script because
#            it needs to be processed before other options.
##
#A -ccl <file>
##     Reads Command Language from the named file, and includes it in
##     the setup of the run.  If <file> is the single character '-',
##     the Command Language is read from the standard input (usually
##     the terminal).  If any settings are made in the Command
##     Language file which also occur on the command line to the left
##     of the -ccl switch, the settings in the file will take
##     precedence, as stated above.  This switch may be repeated to
##     include Command Language from more than one file.
##     Changes that affect the way the mesh is defined, or that affect the
##     way the physics CCL relates to the topology of the mesh stored
##     in the solver input file, cannot be made using the -ccl option.
##     For example, locators for applying physics cannot be modified using 
##     the -ccl option. Such changes can, however, be made in CFX-Pre.
#      NOTE: This option is handled earlier in this script because
#            it needs to be processed before other options.
##
#A -config <configuration name>
##     Apply subsequent options to the specified configuration.
    '-config+'            =>\$config,
##
#A -continue-from-file <file>
#A -cont-from-file <file>
##     Use initial values and continue the run history from the specified 
##     ANSYS CFX Results File.  The mesh from the Solver Input File is used 
##     unless the -use-mesh-from-iv option is also specified.
    '-continue-from-file+'=> '-_optacarg', 
      '-cont-from-file+'  => '-continue-from-file',
##
#A -continue-from-configuration <configuration name>
#A -cont-from-config <configuration name>
##     Use initial values and continue the run history from the most recent 
##     results for the specified configuration.  The mesh from the  
##     configuration's Solver Input File is used unless the -use-mesh-from-iv
##     option is also specified.
    '-continue-from-configuration+' => '-_optacarg',
      '-cont-from-config+'=> '-continue-from-configuration',
#
#U -debug-dummy-solver
    '-debug-dummy-solver' => '-_optacnoarg',
##
#A -definition <file>
#A -def <file> 
##     Use specified file as the Solver Input File for a single configuration
##     simulation.  Specifying an ANSYS CFX Results File (.res) here produces 
##     a restart.  See also "-mdef".
    '-def+'               => sub {
       $sim->singleconfig(1);
       $batch=1;
       $sim->singleconfig_deffile(fullpath($_[1]));
       $sim->initConfig(1, 0);
    },
      '-definition+'      => '-def',
##
#A -eg <file>
#A -example <file>
##     Run the ANSYS CFX Solver on one of the Example Definition
##     files provided with the product.  
    '-eg+'                => sub {
       my $example=$_[1];
       my $file=join_file($Config{CFX_EG_DIR}, $example.".def");
       if (CFX5::FileTests::datafile($file, "Example Solver Input File $file")) {
           $sim->singleconfig(1);
           $batch=1;
           $sim->singleconfig_deffile(fullpath($file));
           $sim->initConfig(1, 0);
      } else {
        _error("No Solver Input File exists for the $example example.");
      }
    },
      '-example+'         => '-eg',
##
#A -fullname <name>
##     Choose names for the Output File, ANSYS CFX Results File, and the temporary
##     directory based on <name> instead of the Solver Input File name.
##     No numerical suffix (e.g. _001) is added to the specified name.
    '-fullname+'          => sub {
       if( $sim->singleconfig() or defined $config) {
         $sim->set_config_option($config, '-fullname', $_[1]); 
       }
       else {
         $sim->fullname(fullpath($_[1]));
       }
    },
      '-fullpath+'        => '-fullname',
##
#A -initial <file> 
#A -ini <file> 
##     Use initial values from the specified ANSYS CFX Results File. The mesh 
##     and run history from the specified file is also used unless the 
##     -interpolate-iv option is also specified. This option has been deprecated
##     and should be replaced by "-initial-file" or "-continue-from-file"
##     as appropriate.
    '-initial+'           => '-_optacarg',
      '-ini+'             => '-initial',
##
#A -initial-configuration <configuration name> 
#A -ini-conf <configuration name> 
##     Use initial values and continue the run history from the most recent 
##     results for the specified configuration.  The mesh from the Solver Input File
##     is used unless the -use-mesh-from-iv option is also specified.
    '-initial-configuration+' => '-_optacarg',
      '-ini-conf+'        => '-initial-configuration',
##
#A -initial-file <file>
#A -ini-file <file>
##     Use initial values but discard the run history from the specified 
##     ANSYS CFX Results File.  The mesh from the Solver Input File is used 
##     unless the -use-mesh-from-iv option is also specified.
    '-initial-file+'      => '-_optacarg',
      '-ini-file+'        => '-initial-file',
##
#A -interpolate-iv
#A -interp-iv
##     Interpolate the solution from the initial values file, if one
##     is supplied (using the -initial option), onto the mesh in the
##     Solver Input File, rather than using the mesh from the initial
##     values file. This option has been deprecated and should be
##     replaced by "-initial-file" or "-continue-from-file" as appropriate.
    '-interpolate-iv'     => '-_optnoarg',
      '-interp-iv'        => '-interpolate-iv',
#
#U -interrupt-after <preparedef | partitioner | solver | refiner | Remeshing >
    '-interrupt-after+'   => '-_optarg', 
##
#A -maxet <elapsed time>
#A -max-elapsed-time <elapsed time>
##     Set the maximum elapsed time (wall clock time) that the ANSYS CFX
##     Solver will run.  Elapsed time must be in quotes and have correct 
##     units in square brackets (eg: -maxet "10 [min]" or -maxet "5 [hr]")
    '-max-elapsed-time+'  => '-_optacarg',
      '-maxet+'           => '-max-elapsed-time', 
##
#A -mdefinition <file>
#A -mdef <file> 
##     Use specified file as the Solver Input File for a multi-configuration
##     simulation.  Specifying a multi-configuration ANSYS CFX Results File
##     (.mres) here produces a restart.
    '-mdefinition+' => sub {
      $sim->singleconfig(0);
      $sim->mdeffile($_[1]);
      unless(error_pending()){
        $sim->read_mdef_ccl();
      }
    },
      '-mdef+'            => '-mdefinition',
##
#A -multiconfig
##     Treat the Solver Input File as a multi-configuration input file.
    '-multiconfig'        => sub { $sim->singleconfig(0); },
##
#A -name <name>
##     Choose names for the output file, ANSYS CFX Results File, and the temporary
##     directory based on the problem name <name> instead of the
##     Solver Input File name.
    '-name+'              => sub {
       if( $sim->singleconfig() or defined $config) {
         $sim->set_config_option($config, '-name', $_[1]); 
       }
       else {
         $sim->name($_[1]);
       }
    },
##
#A -use-mesh-from-iv
##     Use the mesh from the source initial values (i.e. file or configuration)
##     rather than from the Solver Input File.  This is only valid if a single 
##     initial values source is specified.
    '-use-mesh-from-iv'   => '-_optnoarg',
##
## ADVANCED RUN SPECIFICATION
##
#U -aas
##     Start the solver in aaS (as a Server) mode
    '-aas'   => sub { $sim->start_aas(1); },
##
#U -aas-keyfile
##     Specify an aaS keyfile
    '-aas-keyfile+'       => sub { 
      conf_datafile_w('CFX_AAS_KEY_FILE','ANSYS CFX aaS keyfile %%',@_);
    },
##
#A -indirect-startup
##     Run the solver using the run directory, output file, and ccl specified by
##     the -indirect-startup-path
    '-indirect-startup'   => sub { $sim->indirect_startup(1); },
##
#U -indirect-options <option1=value1 option2=value2 ...>
##     Add additional options to the %{indirect_args} macro used by
##     an indirect start method.
    '-indirect-options+'  => sub { $sim->indirect_options($_[1]); },
##
#A -job
##     Keep job file after an ANSYS CFX Solver run.  This file contains a 
##     brief summary of various solution values, and is most useful for
##     regression purposes.
    '-job'                => '-_optnoarg',
##
#A -job-part
#A -jobp
##     Keep job file after an ANSYS CFX Partitioner run.  This file contains a 
##     brief summary of various solution values, and is most useful for
##     regression purposes.
    '-job-part'           => '-_optnoarg',
      '-jobp'             => '-job-part',
##
#A -lpf <license preference file>
##     Specify a license preference file.
    '-lpf+'       => sub { 
      conf_datafile('ANSYSLI_LPF','ANSYS license preference file %%',@_);
    },
##
#A -norun
##     Preprocess the Solver Input File only;
##     Do not run the ANSYS CFX solver executable.
##     When used with a multi-configuration Solver Input File, this option will
##     produce complete Solver Input Files for the individual configurations.
##     When used with the "-config" option, only the specified configuration
##     is preprocessed.
#      When used with a single configuration Solver input File, this option will
#      execute the CCL2FLOW and CCLSETUP executables, and produce the "def" file
#      that is required by the solver executable. 
    '-norun'              => '-_optnoarg',
##
#A -preferred-license <license name>
#A -P <license name>
##     License used first by the ANSYS CFX Solver, given the availability of  
##     multiple useable licenses.
    '-preferred-license+' => '-_optarg',
      '-P+' => '-preferred-license',
##
#A -respect-suffix-history
##     Consider results files referenced by initial values files
##     when choosing the numerical suffix (e.g. _001) added to the run name.
    '-respect-suffix-history' => '-_optnoarg',
##
#A -save
##     Do not delete any temporary files after the run. Normally the standard
##     temporary files created by the ANSYS CFX Solver are deleted
##     automatically after each run.
    '-save'               => '-_optnoarg',
##
##-------------------------------------------------------------------------
## EXECUTION
##-------------------------------------------------------------------------
#
#U -first-half
#U -fh
#   Determine the maximum number of outer iterations or time steps for the run
#   and then execute only the first half of the run.
    '-first-half'         => '-_optnoarg',
      '-fh'               => '-first-half',
##
#A -priority <level>
#A -pri <level>
##     Set the run priority for the ANSYS CFX Solver.  <level> should
##     be one of:
##       CFX Levels          Nice increment     Windows Priority
##      Idle (0)                   19               Low
##      Low (1)                     7               BelowNormal
##      Standard (2)                0               Normal
##      High (3)                    0               AboveNormal
##     This applies to all processes in a parallel run.  A numeric 
##     setting is also accepted as shown in the CFX column.  The default
##     CFX setting is Standard (2), corresponding to a nice increment 
##     of 0 on UNIX platforms and a priority level of Normal on Windows.
    '-priority+'          => '-_optarg',
      '-pri+'             => '-priority',
#
#U -second-half
#U -sh
#   Determine the maximum number of outer iterations or time steps for the run
#   and then execute only the second half of the run.
    '-second-half'        => '-_optnoarg',
      '-sh'               => '-second-half',
##
#A -size <factor>
#A -S <factor>
#A -s <factor>
##     Change the memory estimates used by the ANSYS CFX Solver by a
##     factor of <factor>.  By default the memory estimates contained
##     in the Solver Input File are used.  Sometimes these are
##     inaccurate and this option needs to be used to increase the
##     memory allocated.
    '-size+'              => '-_optarg',
      '-S+'               => '-size',
      '-s+'               => '-size',
##
#A -size-cat <size>
#A -size-nr <size>
#A -size-ni <size>
#A -size-nd <size>
#A -size-nc <size>
#A -size-nl <size>
#A -scat <size>
#A -nr <size>
#A -ni <size>
#A -nd <size>
#A -nc <size>
#A -nl <size>
##     These options are for advanced users to change the memory allocation 
##     parameters for the ANSYS CFX Solver.  Usually, you should use
##     the -size option instead.  <size> is the desired memory
##     allocation in words, and may have K or M appended for kilo- or
##     mega-.  If the suffix is 'x', the number is treated as a
##     multiplier.
    '-size-cat+'          => '-_optarg',
      '-scat+'            => '-size-cat',
    '-size-nc+'           => '-_optarg',
      '-nc+'              => '-size-nc',
    '-size-nd+'           => '-_optarg',
      '-nd+'              => '-size-nd',
    '-size-ni+'           => '-_optarg',
      '-ni+'              => '-size-ni',
    '-size-nl+'           => '-_optarg',
      '-nl+'              => '-size-nl',
    '-size-nr+'           => '-_optarg',
      '-nr+'              => '-size-nr',
##
#A -size-mms <factor>
#A -smms <factor>
##     Change the initial MMS catalogue size estimate used by the
##     ANSYS CFX Solver by a factor of <factor>.  This option has been
##     deprecated and should be replaced by -size-cat.
    '-size-mms+'          => '-_optarg',
      '-smms+'            => '-size-mms',
##
#A -size-part-mms <factor>
#A -smmspar <factor>
##     Change the initial MMS catalogue size estimate used by the
##     ANSYS CFX Partitioner by a factor of <factor>.  This option has 
##     been deprecated and should be replaced by -size-part-cat.
    '-size-part-mms+'     => '-_optarg',
      '-smmspar+'         => '-size-part-mms',
##
#A -size-cclsetup <factor>
#A -sizeccl <factor>
##     Change the memory estimates used by the ANSYS CFX cclsetup executable
##     by a factor of <factor>.
    '-size-cclsetup+'     => '-_optarg',
      '-size-ccl+'        => '-size-cclsetup',
      '-sizeccl+'         => '-size-cclsetup',
##
#A -size-cclsetup-cat <size>
#A -size-cclsetup-nr <size>
#A -size-cclsetup-ni <size>
#A -size-cclsetup-nd <size>
#A -size-cclsetup-nc <size>
#A -size-cclsetup-nl <size>
#A -scatccl <size>
#A -nrccl <size>
#A -niccl <size>
#A -ndccl <size>
#A -ncccl <size>
#A -nlccl <size>
##     These options are the same as the -size-* options above, but give the
##     sizes needed for the ANSYS CFX CCL Setup executable.
    '-size-cclsetup-nc+'  => '-_optarg',
      '-size-ccl-nc+'     => '-size-cclsetup-nc',
      '-ncccl+'           => '-size-cclsetup-nc',
    '-size-cclsetup-nd+'  => '-_optarg',
      '-size-ccl-nd+'     => '-size-cclsetup-nd',
      '-ndccl+'           => '-size-cclsetup-nd',
    '-size-cclsetup-ni+'  => '-_optarg',
      '-size-ccl-ni+'     => '-size-cclsetup-ni',
      '-niccl+'           => '-size-cclsetup-ni',
    '-size-cclsetup-nl+'  => '-_optarg',
      '-size-ccl-nl+'     => '-size-cclsetup-nl',
      '-nlccl+'           => '-size-cclsetup-nl',
    '-size-cclsetup-nr+'  => '-_optarg',
      '-size-ccl-nr+'     => '-size-cclsetup-nr',
      '-nrccl+'           => '-size-cclsetup-nr',
    '-size-cclsetup-cat+' => '-_optarg',
      '-scatccl+'         => '-size-cclsetup-cat',
##
#A -size-interp <factor>
#A -sizeint <factor>
##     Change the memory estimates used by the ANSYS CFX Interpolator by a
##     factor of <factor>.
    '-size-interp+'       => '-_optarg',
      '-size-int+'        => '-size-interp',
      '-sizeint+'         => '-size-interp',
##
#A -size-interp-cat <size>
#A -size-interp-nr <size>
#A -size-interp-ni <size>
#A -size-interp-nd <size>
#A -size-interp-nc <size>
#A -size-interp-nl <size>
#A -scatint <size>
#A -nrint <size>
#A -niint <size>
#A -ndint <size>
#A -ncint <size>
#A -nlint <size>
##     These options are the same as the -size-* options above, but give the
##     sizes needed for the ANSYS CFX Interpolator.
    '-size-interp-nc+'    => '-_optarg',
      '-size-int-nc+'     => '-size-interp-nc',
      '-ncint+'           => '-size-interp-nc',
    '-size-interp-nd+'    => '-_optarg',
      '-size-int-nd+'     => '-size-interp-nd',
      '-ndint+'           => '-size-interp-nd',
    '-size-interp-ni+'    => '-_optarg',
      '-size-int-ni+'     => '-size-interp-ni',
      '-niint+'           => '-size-interp-ni',
    '-size-interp-nl+'    => '-_optarg',
      '-size-int-nl+'     => '-size-interp-nl',
      '-nlint+'           => '-size-interp-nl',
    '-size-interp-nr+'    => '-_optarg',
      '-size-int-nr+'     => '-size-interp-nr',
      '-nrint+'           => '-size-interp-nr',
    '-size-interp-cat+'   => '-_optarg',
      '-scatint+'         => '-size-interp-cat',
##
#A -size-part <factor>
#A -sizepart <factor>
#A -size-par <factor>
#A -sizepar <factor>
##     Change the memory estimates used by the ANSYS CFX Partitioner by a
##     factor of <factor>.
    '-size-part+'         => '-_optarg',
      '-sizepart+'        => '-size-part',
      '-size-par+'        => '-size-part',
      '-sizepar+'         => '-size-part',
##
#A -size-part-cat <size>
#A -size-part-nr <size>
#A -size-part-ni <size>
#A -size-part-nd <size>
#A -size-part-nc <size>
#A -size-part-nl <size>
#A -scatpar <size>
#A -nrpar <size>
#A -nipar <size>
#A -ndpar <size>
#A -ncpar <size>
#A -nlpar <size>
##     These options are the same as the -size-* options above, but give the
##     sizes needed for the ANSYS CFX Partitioner.
    '-size-part-cat+'     => '-_optarg',
      '-scatpar+'         => '-size-part-cat',
    '-size-part-nc+'      => '-_optarg',
      '-ncpar+'           => '-size-part-nc',
    '-size-part-nd+'      => '-_optarg',
      '-ndpar+'           => '-size-part-nd',
    '-size-part-ni+'      => '-_optarg',
      '-nipar+'           => '-size-part-ni',
    '-size-part-nl+'      => '-_optarg',
      '-nlpar+'           => '-size-part-nl',
    '-size-part-nr+'      => '-_optarg',
      '-nrpar+'           => '-size-part-nr',
##
#A -numa <option>
##     Set the option for NUMA memory containment
##     Valid options are:    
##        none (NUMA containment disabled)
##        auto (NUMA containment enabled) 
    '-numa+'    => '-_optarg',
##
#A -affinity
##     Set the option for process affinity control
##        implicit (affinity not set by the solver)
##        explicit (affinity explicitly set by the solver) 
    '-affinity+'    => '-_optarg',
##
##-------------------------------------------------------------------------
## PARALLEL AND PARTITIONING
##-------------------------------------------------------------------------
##
#A -parallel
#A -par
##     Run the ANSYS CFX Solver in parallel mode. This option can be combined
##     with the -part (-partition) option for a partitioning run.  If
##     the -part switch is not given, the -parfile-read switch must be used
##     to specify a valid partitioning information file.
    '-parallel'      => '-par',
      '-par'         => '-_optnoarg',
##
#A -parfile-read <parfile>
##     Set the name of an input partition file, used to set up
##     a partitioning or parallel run.
    '-parfile-read+'    => '-_optarg',
##
#A -parfile-save
##     When used with a parallel run, save the partitioning
##     information to a file with the same basename as the results
##     file, and the extension .par.
    '-parfile-save'     => '-_optnoarg',
##
#A -parfile-write <parfile>
##     Give the name of a partition file to write containing the
##     information from a partitioning run.
    '-parfile-write+'   => '-_optarg',
##
#A -partition <number of partitions>
#A -part <number of partitions>
##     Run the ANSYS CFX Solver in partitioning mode. This option should not
##     be used if an existing partition file is also specified.
    '-part+'            => '-_optarg',
      '-partition+'     => '-part',
##
#A -part-only <number of partitions>
##     Run the ANSYS CFX Solver in partitioning mode only, but do not run
##     the solver.
    '-part-only+'       => '-_optarg',
##
#A -part-coupled
##     Activate coupled partitioning mode for multidomain problems.
##     This is the default.
    '-part-coupled'     => '-_optnoarg',
##
#A -part-independent
##     Activate independent partitioning mode for multidomain problems.
##     This is not activated by default.
    '-part-independent' => '-_optnoarg',
##
#A -part-mode <mode>
##     Set the partitioning mode to use when running the partitioner.
##     Valid options are:
##        metis-kway  (MeTiS k-way)
##        metis-rec   (MeTiS Recursive Bisection)
##        simple      (Simple Assignment)
##        drcb        (Directional Recursive Coordinate Bisection)
##        orcb        (Optimized Recursive Coordinate Bisection)
##        rcb         (Recursive Coordinate Bisection)
##     Finer control over the partitioning method is available through
##     the Command Language.    
    '-part-mode+'    => '-_optarg',
##
#A -par-dist <host-list>
##     Set the comma-separated <host-list> in the same form as is
##     used in the Command Language definition.  This option does not
##     require the -partition switch, as one partition is run on each
##     host mentioned in the list.  To run multiple partitions on the
##     same host it may be listed multiple times, or an asterisk may
##     be used with the count, as in "wallaby*3,kangaroo*4" for a
##     7-partition run.
##
##     Host details are taken from the hostinfo.ccl file, if they are
##     there; otherwise, if possible, the required information will be
##     automatically detected.  <host> may be specified as
##     [<user>@]<hostname>[:<CFX_ROOT>] if the user name or the
##     ANSYS CFX installation root directory differ from the local host.
    '-par-dist+'      => '-_optarg',
##
#A -par-host-list <host1>[,<host2>[,...]]
##     When running in parallel, use the given host list.  See the
##     -par-dist switch for details of the host list.
    '-par-host-list+'=> '-_optarg',
##
#A -par-local
##     When running in parallel, use only the local host.  This will
##     override the -par-hist or -par-host-list switches.
    '-par-local'     => '-_optnoarg',
##
#A -serial
##     Explicitly specify that a serial run is required.  Normally
##     this is the default, but when restarting from a results file
##     from a parallel run, the new run will also be parallel by
##     default, and this switch can be used to override it.
    '-serial'        => '-_optnoarg',
##
#A -start-method <name>
##     Use the named start method to start the ANSYS CFX Solver.  This option
##     allows you to use different parallel methods, as listed in the
##     ANSYS CFX Solver Manager GUI or in the etc/start-methods.ccl file,  
##     instead of the defaults.  For parallel start methods, you must also 
##     provide the -part or -par-dist option.
    '-start-method+' => '-_optarg',
##
##-------------------------------------------------------------------------
## EXECUTABLE SELECTION
##-------------------------------------------------------------------------
##
## Single precision is the default for the ANSYS CFX Partitioner, Interpolator
## and Solver.  The -double and -single options set the default precision for 
## all stages but may be overridden for each stage. E.g. To use the double 
## precision solver and single precision interpolator use:
## -double -single-interp
##
## These options may also be used to override setting in a CFX Command 
## Language from previous runs. E.g If the previous run used a double 
## precision solver -solver-single would force the single precision solver 
## to be used. Note: -single/-double will not override existing setting that 
## have be defined for each step. 
## 
#A -ccl2flow <executable>
##     Run <executable> instead of the standard ANSYS CFX ccl2flow.
    '-ccl2flow+'      => '-_optarg',
##
#A -ccl2flow-double
##     Use the double precision ANSYS CFX ccl2flow executable.
    '-ccl2flow-double' => '-_optnoarg',
##
#A -ccl2flow-single
##     Use the single precision ANSYS CFX ccl2flow executable.
    '-ccl2flow-single' => '-_optnoarg',
##
#A -cclsetup <executable>
##     Run <executable> instead of the standard ANSYS CFX cclsetup.
    '-cclsetup+'      => '-_optarg',
##
#A -cclsetup-double
##     Use the double precision ANSYS CFX cclsetup executable.
    '-cclsetup-double' => '-_optnoarg',
##
#A -cclsetup-single
##     Use the single precision ANSYS CFX cclsetup executable.
    '-cclsetup-single' => '-_optnoarg',
##
#A -double
##     Default to the double-precision version of the ANSYS CFX Partitioner,
##     Interpolator and Solver.
    '-double' => '-_optnoarg', 
##
#A -large
##     Default to the large problem version of the ANSYS CFX Partitioner,
##     Interpolator and Solver.
    '-large' => '-_optnoarg',
##
#A -interpolator <executable>
##     Run <executable> instead of the standard ANSYS CFX Interpolator.
    "-interpolator+"      => '-_optarg',
##
#A -interp-double
##     Use the double precision ANSYS CFX Interpolator.
    "-interp-double" => '-_optnoarg',
##
#A -interp-single
##     Use the single precision ANSYS CFX Interpolator.
    "-interp-single"      => '-_optnoarg',
##
#A -interp-large
#      Run the large problem interpolator for problems too large for
#      the default executable.  This interpolator uses 64 bit integer
#      and logical variables so it will allocate more memory than the
#      default interpolator executable.
    '-interp-large'       => '-_optnoarg',
##
#A -partitioner <executable>
##     Run <executable> instead of the standard ANSYS CFX Partitioner.
    "-partitioner+"       => '-_optarg',
##
#A -part-double
##     Use the double precision ANSYS CFX Partitioner.
    "-part-double" => '-_optnoarg',
##
#A -part-single
##     Use the single precision ANSYS CFX Partitioner.
    '-part-single'        => '-_optnoarg',
##
#A -part-large
##     Run the large problem partitioner which can partition problems
##     up to 2^32-1 elements.  This partitioner uses 64 bit integer 
##     and logical variables so it will allocate more memory than the
##     default partitioning executable.
    '-part-large'       => '-_optnoarg',
##
#A -single
##     Default to the single precision version  of the ANSYS CFX Partitioner,
##     Interpolator and Solver.
    '-single'             => '-_optnoarg',
##
#A -solver [<os>=]<executable>[,<os>=<executable>[,...]]
#A -exec [<os>=]<executable>[,<os>=<executable>[,...]]
##     Run <executable> instead of the standard ANSYS CFX Solver on <os>.
##     If <os> is omitted the current os is assumed.
##     E.g -solver "linux-amd64/mysolver.exe,linux=linux/mysolver.exe"
    '-solver+'            => '-_optarg',
    '-exec+'              => '-solver',
##
#A -solver-double
##     Use the double precision ANSYS CFX Solver.
   '-solver-double'       => '-_optnoarg',
##
#A -solver-single
##     Use the single precision ANSYS CFX Solver.
   '-solver-single'       => '-_optnoarg',
##
#A -solver-large
#      Run the large problem solver for problems too large for
#      the default executable.  This interpolator uses 64 bit integer
#      and logical variables so it will allocate more memory than the
#      default solver executable.
    '-solver-large'       => '-_optnoarg',
##
##-------------------------------------------------------------------------
## ANSYS SYSTEM COUPLING
##-------------------------------------------------------------------------
##
##
#A -scport <port>
##     For a coupled CFX Solver/System Coupling run, specify the port
##     number for the ANSYS CFX Solver to establish a connection to. 
    '-scport+'     => '-_optarg',
##
#A -schost <host>
##     For a coupled CFX Solver/System Coupling run, specify the host 
##     name for the ANSYS CFX Solver to establish a connection to. 
    '-schost+'       => '-_optarg',
##
#A -scname <name>
##     For a coupled CFX Solver/System Coupling run, specify the name
##     that System Coupling has assigned to identify the CFX Solver
##     participant.
    '-scname+'       => '-_optarg',
##
#A -sclic <name>
##     For a coupled CFX Solver/System Coupling run, specify the 
##     licensing port and host name (port@host).
    '-sclic+'       => '-_optarg',
##
#A -scid <name>
##     For a coupled CFX Solver/System Coupling run, specify the
##     system coupling ID.
    '-scid+'        => '-_optarg',
##
##-------------------------------------------------------------------------
## ANSYS MULTIFIELD AND PROCESS COUPLING
##-------------------------------------------------------------------------
##
#A -ansys-arguments <arguments>
##     For an ANSYS Multi-field run, set any additional options for
##     the ANSYS Solver. 
    '-ansys-arguments-' => '-_optmfarg_2',
##
#A -ansys-input <file>
##     For an ANSYS Multi-field run, set the ANSYS input file to use. 
    '-ansys-input+'     => '-_optmfarg',
##
#A -ansys-input-is-complete
##     For an ANSYS Multi-field run, treat the ANSYS input file as being
##     complete. Do not pre-process using CCL2MF.
    '-ansys-input-is-complete' => '-_optmfnoarg',
##
#A -ansys-installation <directory>
##     For an ANSYS Multi-field run, set the ansys installation
##     directory if not installed in a standard location.
    '-ansys-installation+'     => '-_optmfarg',
##
#A -ansys-jobname <name>
##     For an ANSYS Multi-field run, set the jobname to use. Default is
##     ANSYS. For restarts, the jobname must be the same as the initial run.
    '-ansys-jobname+'   => '-_optmfarg',
##
#A -ansys-license <licensekey>
##     For an ANSYS Multi-field run, set the license that the ANSYS
##     Solver should use.
    '-ansys-license+'   => '-_optmfarg',
##
#A -ansys-restart <file>
##     For an ANSYS Multi-field run, set a restart database for the ANSYS
##     Solver to use.
    '-ansys-restart+'   => '-_optmfarg',
##
#A -cplg-host <port@host>
##     For a coupled solver run/ANSYS Multi-field run, specify the port number
##     and hostname for the ANSYS CFX Solver to establish a connection to. 
    '-cplg-host+'       => '-_optmfarg',
#
#U -cplg-master <name>
#      Indicates that this field solver should be the coupling master in a 
#      two-way coupled run, and gives this solver instance an alias/name.
    '-cplg-master+'     => '-_optmfarg',
#
#U -cplg-slave <name>
#      Indicates that this field solver should be the coupling slave in a 
#      two-way coupled run, and gives this solver instance an alias/name.
    '-cplg-slave+'      => '-cplg-master',
##
#A -mfx-run-mode <mode>
##     For an ANSYS Multi-field run, specify the run mode. Valid modes are:
##     "Start ANSYS and CFX"
##     "Start ANSYS only"
##     "Start CFX only"
##     "Process Input File only"
    '-mfx-run-mode+'    => '-_optmfarg',
);

# Command line option preparation
#
# * Error on any dis-allowed duplicate command line options
#
# * Reordering options:
#   -chdir must be first
#   -def must be second so that any ccl is overridden
#
#   To do this there is a hash mapping args to indices. If an option expects a
#   argument then it ends in + and the next index increments 2 instead 
#   of 1. This can later be mapped to a sorted array of options.
#
sub prepare_cmdline {
  my %configargs;
  my $curconfig="0";
  $configargs{$curconfig}=[];
  $configccl{$curconfig}=[];

  # Assign options to specified configurations
  while(@ARGV) {
    my $opt=shift @ARGV;
   
    # Process this before creating the Simulation object 
    if($opt eq "-custom-data-dir"){
       my $customdir=shift @ARGV;
       $Config{CFX_CUSTOM_DATA_DIR}=abspath($customdir);
    }
    elsif($opt eq "-stdout-comms") {
        CFX5::Output::CCL::stdout_ccl_comms();
        next
    }
    elsif($opt eq "-config"){
      $curconfig=shift @ARGV;
      $configargs{$curconfig}=[];
      push @{$configargs{$curconfig}}, "-config", $curconfig;
      next;
    }
    elsif($opt eq "-indirect-startup-path"){
      my $runpath=shift @ARGV;
      my @ccl;
      my $cclfile=join_file(fullpath($runpath).'.dir', "startup.ccl");
      if(not CFX5::FileTests::datafile($cclfile, "Indirect startup ccl file $cclfile")){
        _error("Indirect startup ccl file $cclfile does not exist");
        return;
      }
      my $scccl=$sim->check_read_ccl_option($cclfile, \@ccl);
      if( defined $default_configccl_is_single and not $default_configccl_is_single or $curconfig ne "0" ){
        _error("-indirect-startup-path is not supported for multiple configuration cases");
        return;
      }
      $default_configccl_is_single=1;
      if(@ccl){
        push @{$configccl{$curconfig}}, @ccl;
        $default_configccl_is_single=$scccl unless defined $default_configccl_is_single;
        push @{$configargs{$curconfig}}, "-_parseccl";
        push @{$configargs{$curconfig}}, "-fullname", $runpath;
        push @{$configargs{$curconfig}}, "-indirect-startup";
      }
      else {
        _error("Error reading ccl from $cclfile");
        return;
      }
      # Don't add it to the options to be processed
      next;
    }
    elsif($opt eq "-ccl" or $opt eq "-bg-ccl"){
      my $cclfile=shift @ARGV;
      my @ccl;
      my $scccl=$sim->check_read_ccl_option($cclfile, \@ccl);
      if(@ccl){
        push @{$configccl{$curconfig}}, @ccl;
        if( $curconfig eq "0" ){
          # Could be multi or single config, check later
          $default_configccl_is_single=$scccl unless defined $default_configccl_is_single;
          push @{$configargs{$curconfig}}, "-_parseccl";
        } else {
          # It's for a specific config
          push @{$configargs{$curconfig}}, "-_parse_configccl";
        }
      }
      # Don't add it to the options to be processed
      next;
    }
    push @{$configargs{$curconfig}}, $opt;
  }

  $default_configccl_is_single=1 unless defined $default_configccl_is_single;

  # Reordering rules simulation level (i.e. single config or global) and
  # configuration specific options
  my %sim_forward = (
                     "-chdir+" => 1,
                     "-multiconfig" => 3,
                     "-mdef+" => 4,
                     "-def+" => 6,
                     "-definition+" => 8,
                     "-eg+" => 10,
                     "-example+" => 12,
                     "-indirect-startup" => 13,
                     "-_parseccl" => 14,
                     "-start-method+" => 15,
                    );
  my %config_forward = (
                        "-config+" => 1,
                        "-start-method+" => 3,
                        "-_parse_configccl" => 5,
                       );

  # Rules for identifying command line options that must be unique
  my %sim_unique = ();
  my %config_unique = ();

  @ARGV=();
  
  my @configList ;
  push (@configList, '0') ;
  foreach my $i (keys %configargs){
    push (@configList, $i) unless $i eq '0'; 
  }

  for (my $ii=0; $ii<scalar(@configList); $ii++) {
    my $i = $configList[$ii] ;
    my $bring_forward;
    my $check_unique;
    my (@b4, %b4, @norm);

    # Pick the correct order and uniqueness hashes
    if($i eq '0'){
      $bring_forward=\%sim_forward;
      $check_unique=\%sim_unique;
    }
    else {
      $bring_forward=\%config_forward;
      $check_unique=\%config_unique;
    }
    
    while(@{$configargs{$i}}){
      my $opt=shift @{$configargs{$i}};
      
      my $dupOptMsg = "The option $opt (or long or short forms of it) may only be used only once" ;
      if ($i eq '0') {
        $dupOptMsg .= "." ;
      } else {
        $dupOptMsg .= " for the configuration $i." ;
      }      

      if(defined $cmdline_options{$opt} or
         defined $StandardArgs{$opt} or
         defined $MandatoryArgs{$opt} ){
        # It's a valid command line option, no args
       
        if(defined $check_unique->{$opt}){
          # Can only be used once
          if($check_unique->{$opt} > 0){
            # It's already been used
            _error($dupOptMsg);
            return 0;
          }
          $check_unique->{$opt}++;
        }

        if ($bring_forward->{$opt}) {
          # Needs to be reordered
          $b4{$bring_forward->{$opt}}=$opt;
        }
        else {
          # No reordering, put it at the end
          push @norm, $opt;
        }
      }
      elsif(defined $cmdline_options{$opt.'+'} or
            defined $StandardArgs{$opt.'+'} or
            defined $MandatoryArgs{$opt.'+'} ){
        # It's a valid command line option, takes an arg
        if(defined $check_unique->{$opt.'+'}){
          # Can only be used once
          if($check_unique->{$opt.'+'} > 0){
            # It's already been used
            _error($dupOptMsg);
            return 0;
          }
          $check_unique->{$opt.'+'}++;
        }

        unless( scalar @{$configargs{$i}}) {
          # Not more command line options but we expect a value
          _error("Missing value for command line option $opt");
          return 0;
        }

        if ($bring_forward->{$opt.'+'}) {
          # Needs to be reordered
          $b4{$bring_forward->{$opt.'+'}}=$opt;
          $b4{$bring_forward->{$opt.'+'}+1}=shift @{$configargs{$i}};
        }
        else {
          push @norm, $opt, shift @{$configargs{$i}};
        }
      }
      elsif(defined $cmdline_options{$opt.'-'} or
            defined $StandardArgs{$opt.'-'} or
            defined $MandatoryArgs{$opt.'-'}){
        # It's a valid command line option, takes an arg
        if(defined $check_unique->{$opt.'-'}){
          # Can only be used once
          if($check_unique->{$opt.'-'} > 0){
            # It's already been used
            _error($dupOptMsg);
            return 0;
          }
          $check_unique->{$opt.'-'}++;
        }

        unless( scalar @{$configargs{$i}}) {
          # Not more command line options but we expect a value
          _error("Missing value for command line option $opt");
          return 0;
        }

        if ($bring_forward->{$opt.'-'}) {
          # Needs to be reordered
          $b4{$bring_forward->{$opt.'-'}}=$opt;
          $b4{$bring_forward->{$opt.'-'}+1}=shift @{$configargs{$i}};
        }
        else {
          push @norm, $opt, shift @{$configargs{$i}};
        }
      }
      else {
        # It's not a valid command line option
        _error("Unknown command line option $opt");
        return 0;
      }
    }
 
    # Push the ordered options for this config back into ARGV.
    # Sort the b4 hash keys (which are the bring_forward values)
    # Map this back to the b4 values (which are the actual options)
    # An option's arg will be the bring_forward value of the option + 1
    push @ARGV, (map ( $b4{$_}, (sort {$a <=> $b} (keys %b4) ) ),@norm);
  } 
  return 1;
}

#------------------------------------------------------------------------------
#
# This section starts up the solver manager instead of the solver itself
# if the user has explicitly asked for the solver manager or if no
# ANSYS CFX definition file was specified on the command line.
#
sub start_solver_manager {
    my $sim=shift;

    my $job;
    if ($sim->singleconfig()) {
      $job = $sim->config_object();
    }
    else {
      $job = $sim;
    }

    #
    # Check we've got somewhere to display the Solver Manager GUI.
    #
    cfx5_require('CFX5::System');
    CFX5::System::assert_can_window();

    my @exportvars=qw(CFX_DATA_DIR CFX5ROOT CFX5BINDIR CFX_CMD_DIR
                      CFX_TOOLS_ROOT CFX_OS CFX5OS
                      LM_LICENSE_FILE CFX_LICENSE_FILE
                      ANSYS_COMMON_ROOT ANSYS_COMMON_IMAGES_DIR
                      CUE_DIR CFX5PERL);

    CFX5::System::lang_fixup();

    export_conf(@exportvars);

    export_parser_conf();

    CFX5::PrintConfig::show_vars_by_verbosity();

    my @args;

    if ($sim->singleconfig() and defined $sim->singleconfig_deffile()) {
       push @args, -def => $sim->singleconfig_deffile();
    }
    elsif (defined $sim->mdeffile()) {
       push @args, -def => $sim->mdeffile();
    }

    if (@monitor) {
      push @args, map { (-monitor => $_) } @monitor;
    }

    if (@lic_args) {
      push @args, @lic_args;
    }

    if (defined $wid) {
      push @args, -w => $wid;
    }

    if (defined $control_port) {
      push @args, -x => $control_port;
    }

    my $rv;
    if ($state_on_stdin) {
      push @args, $state_on_stdin;
      my @ccl=map { "$_\n" } $job->get_current_ccl();
      #@args=();
      $rv=do_input_cmd(\@ccl, $Config{CFX5_CUESM_EXEC}, @args);
    } else {
      $rv=parse_rv(do_cmd($Config{CFX5_CUESM_EXEC}, @args));
    }
    unless ($rv->is_success()) {
      _error("The ANSYS CFX Solver Manager", $rv->errstr());
    }

    return $rv->shell_rv();
}

#------------------------------------------------------------------------------
#
# Start of main script code

# Create Simulation object
$sim = new CFX5::Simulation();
$sim->text_command([$0,@ARGV]);

# Create a default config for validation
$sim->add_configuration(1, 0, "Default");
$sim->createConfig(1, 0);

exit_if_error();

prepare_cmdline();

exit_if_error();

parse_cmdline
  ( \@ARGV,
    'INCLUDE_STD',
    %cmdline_options);

$batch=0 unless defined $batch or defined $sim->mdeffile() or defined $sim->singleconfig_deffile();
if ($batch and $sim->singleconfig() and not defined $sim->singleconfig_deffile()) {
  my $conf_obj= $sim->config_object();
  _abort("You must specify a Solver Input File to run the ANSYS CFX Solver") unless defined ($conf_obj->deffile());
  $sim->singleconfig_deffile($conf_obj->deffile());
  $sim->initConfig(1, 0);
}

exit_if_error();

# Add the Framework bin directory to the PATH.
# Do this so that we can pick up the APIP library.
prepend_to_libpath($Config{APIP_INSTALL_ROOT});

CFX5::Parallel::MPI::export_conf();
CFX5::CUEI::export_sm_conf();

if (defined $batch and !$batch) {
  _error("GUIs are not supported on this platform") unless check_gui_support();
  exit_if_error();
  exit(start_solver_manager($sim));
} else {
  $sim->batch(1);
}

unless (defined $sim->mdeffile() or $sim->singleconfig() ) {
  exit(1) if ($sim->check_only());
  _abort("You must specify a Solver Input File to run the ANSYS CFX Solver ".join(' ', @ARGV));
}

# get a run number for multiconfig cases
unless ($sim->singleconfig() or defined $sim->fullname()) {
  $sim->choose_name();
}
exit_if_error();

#
# Update all execution control CCL, then validate as much as we can 
#
$sim->updateSimControlCCL() ; 
exit_if_error();
unless ($sim->Check()) {
  exit 1;
}

# dump the CCL we're using.  It should be correct by now.
if ($print_ccl) {
  my $job_ccl=$sim;
  $job_ccl = $sim->config_object() if $sim->singleconfig();
  my $outo=CFX5::Output::CCL::get_ccl_comms();
  if ($outo and my $fh=$outo->open()) {
    print $fh join("\n",$job_ccl->get_current_ccl(),'');
    $outo->close();
  } else {
    print join("\n",$job_ccl->get_current_ccl(),'');
  }
}

# we'll need this soon, so load it now -- it finds all the licensing
# information 
require CFX5::LIST;

#
# if this is a check-only run kicked off from the SM, finish at this
# point; we succeeded the check, so everything's OK.
#
exit_if_error();
exit(0) if ($sim->check_only() or $sim->check_for_gui());
CFX5::PrintConfig::show_vars_by_verbosity();

unless ($sim->singleconfig()) {
  $sim->start_outfile();
  sim_info("Running the ANSYS CFX Solver on job", basename($sim->fullname()));
}

my $ret = $sim->run();
exit_if_error();
if ($ret) {
  exit(0);
} else {
  exit(1);
}
