#!/usr/bin/env perl
#-----------------------------------------------------------------------------------------------
#
# configure
#
# This script sets up config_cache.xml (containing build-time parameters that
# affect the ocean namelist, such as what grid is being used and which ocean
# tracer modules are enabled) and also handles the pop decomposition.
#
# Needs to be passed $CASEROOT!

my $CASEROOT = shift;

# Global variables
my $SRCROOT, $CASEBUILD, $OBJROOT, $OCN_GRID, $OCN_TRACER_MODULES;
my $OCN_TRACER_MODULES_OPT, $POP_AUTO_DECOMP, $POP_BLCKX, $POP_BLCKY;
my $POP_MXBLCKS, $POP_TAVG_R8, $NTHRDS_OCN, $NINST_OCN, $OCN_ICE_FORCING;
my $NT, $ECOSYS_NT, $ZOOPLANKTON_CNT, $AUTOTROPH_CNT, $GRAZER_PREY_CNT;
my $USE_IAGE, $USE_CFC, $USE_ABIO, $USE_CISO, $USE_ECOSYS, $USE_MOBY;

set_environment();
auto_decomp();
determine_tracer_count();
set_cppdefs();
write_config_cache();

exit(0);

sub set_environment {
  # Read variables from env_mach_pes.xml and env_build.xml

  chdir "$CASEROOT";
  $SRCROOT                 = `./xmlquery SRCROOT               -value`;
  $CASEBUILD               = `./xmlquery CASEBUILD              -value`;
  $OBJROOT                 = `./xmlquery OBJROOT                -value`;
  $OCN_GRID                = `./xmlquery OCN_GRID               -value`;
  $OCN_TRACER_MODULES      = `./xmlquery OCN_TRACER_MODULES     -value`;
  $OCN_TRACER_MODULES_OPT  = `./xmlquery OCN_TRACER_MODULES_OPT -value`;
  $POP_AUTO_DECOMP         = `./xmlquery POP_AUTO_DECOMP        -value`;
  $POP_BLCKX               = `./xmlquery POP_BLCKX              -value`;
  $POP_BLCKY               = `./xmlquery POP_BLCKY              -value`;
  $POP_MXBLCKS             = `./xmlquery POP_MXBLCKS            -value`;
  $POP_TAVG_R8             = `./xmlquery POP_TAVG_R8            -value`;
  $NTASKS_OCN              = `./xmlquery NTASKS_OCN             -value`;
  $NTHRDS_OCN              = `./xmlquery NTHRDS_OCN             -value`;
  $NINST_OCN               = `./xmlquery NINST_OCN              -value`;
  $OCN_ICE_FORCING         = `./xmlquery OCN_ICE_FORCING        -value`;

}

sub auto_decomp {
  # If POP_AUTO_DECOMP eq "TRUE", set POP_BLCKX, etc

  # Is only run when POP_AUTO_DECOMP == TRUE
  if ($POP_AUTO_DECOMP ne 'true') {
    return;
  }

  my $ntasks = $NTASKS_OCN / $NINST_OCN;
  chdir "$CASEBUILD";
  my $config_args = `./generate_pop_decomp.pl -ccsmroot $SRCROOT -res $OCN_GRID -nproc $ntasks -thrds $NTHRDS_OCN -output all`;
  my @config = split(/\s/, $config_args);
  if ($config[0] >= 0) {
    chdir "$CASEROOT";
    $POP_BLCKX=$config[2];
    $sysmod = "./xmlchange POP_BLCKX=$POP_BLCKX";
    system($sysmod) == 0 or die "ERROR pop.buildnml: $sysmod failed: $?\n";

    $POP_BLCKY=$config[3];
    $sysmod = "./xmlchange POP_BLCKY=$POP_BLCKY";
    system($sysmod) == 0 or die "ERROR pop.buildnml: $sysmod failed: $?\n";

    $POP_MXBLCKS=$config[4];
    $sysmod = "./xmlchange POP_MXBLCKS=$POP_MXBLCKS";
    system($sysmod) == 0 or die "ERROR pop.buildnml: $sysmod failed: $?\n";

    $sysmod = "./xmlchange POP_DECOMPTYPE=$config[5]";
    system($sysmod) == 0 or die "ERROR pop.buildnml: $sysmod failed: $?\n";
    $sysmod = "./xmlchange POP_NX_BLOCKS=$config[6]";
    system($sysmod) == 0 or die "ERROR pop.buildnml: $sysmod failed: $?\n";
    $sysmod = "./xmlchange POP_NY_BLOCKS=$config[7]";
    system($sysmod) == 0 or die "ERROR pop.buildnml: $sysmod failed: $?\n";
  } else {
    die "ERROR pop.buildnml: pop decomp not set for $OCN_GRID on $ntasks x  $NTHRDS_OCN procs \n";
  }

}

sub determine_tracer_count {

  $ECOSYS_NT       = 27;
  $ZOOPLANKTON_CNT = 1;
  $AUTOTROPH_CNT   = 3;
  $GRAZER_PREY_CNT = 3;

  my @ocn_tracer_modules_opt = split(/\s/, $OCN_TRACER_MODULES_OPT);
  foreach my $module_opt ( @ocn_tracer_modules_opt ) {
    if ( `echo $module_opt | cut -f 1 -d =` eq "ECOSYS_NT" ) {
      $ECOSYS_NT = `echo $module_opt | cut -f 2 -d =`;
    }
    if ( `echo $module_opt | cut -f 1 -d =` eq "ZOOPLANKTON_CNT" ) {
      $ZOOPLANKTON_CNT = `echo $module_opt | cut -f 2 -d =`;
    }
    if ( `echo $module_opt | cut -f 1 -d =` eq "AUTOTROPH_CNT" ) {
      $AUTOTROPH_CNT = `echo $module_opt | cut -f 2 -d =`;
    }
    if ( `echo $module_opt | cut -f 1 -d =` eq "GRAZER_PREY_CNT" ) {
      $GRAZER_PREY_CNT = `echo $module_opt | cut -f 2 -d =`;
    }
  }

  $USE_IAGE   = "FALSE";
  $USE_CFC    = "FALSE";
  $USE_ABIO   = "FALSE";
  $USE_CISO   = "FALSE";
  $USE_ECOSYS = "FALSE";
  $USE_MOBY   = "FALSE";

  $NT = 2;
  my @ocn_tracer_modules = split(/\s/, $OCN_TRACER_MODULES);
  foreach my $module ( @ocn_tracer_modules )  {
    if ($module eq "iage" ) {
      $USE_IAGE = "TRUE";
      $NT       = $NT +  1;
    }

    if ($module eq "cfc" ) {
      $USE_CFC = "TRUE";
      $NT      = $NT +  2;
    }

    if ($module eq "abio_dic_dic14" ) {
      $USE_ABIO = "TRUE";
      $NT       = $NT +  2;
    }
    
    if ($module eq "ciso" ) {
      $USE_CISO = "TRUE";
      $NT       = $NT + 14;
    }
    
    if ($module eq "ecosys" ) {
      $USE_ECOSYS = "TRUE";
      $NT         = $NT + $ECOSYS_NT;
    }
    
    if ($module eq "moby" ) {
      $USE_MOBY = "TRUE";
      my $dir;
      if (-e "$CASEROOT/SourceMods/src.pop/${OCN_GRID}_data.ptracers") {
        $dir = "$CASEROOT/SourceMods/src.pop";
      } elsif (-e "$SRCROOT/components/pop/aux/moby/darwin/input/${OCN_GRID}_data.ptracers") {
        $dir = "$SRCROOT/components/pop/aux/moby/darwin/input";
      } else {
        die "ERROR pop.buildexe: cannot find moby tracers";
      }
      my $NT_MOBY = `grep PTRACERS_numInUse $dir/${OCN_GRID}_data.ptracers | cut -f 2 -d = | cut -f 1 -d","`;
      $NT       = $NT + $NT_MOBY;
    }
  }

}

sub set_cppdefs {

  my $cppdefs = "-DCCSMCOUPLED";
  $cppdefs = "$cppdefs -DBLCKX=$POP_BLCKX";
  $cppdefs = "$cppdefs -DBLCKY=$POP_BLCKY";
  $cppdefs = "$cppdefs -DMXBLCKS=$POP_MXBLCKS";
  $cppdefs = "$cppdefs -DNT=$NT ";
  if ("$OCN_GRID" =~ /tx0.1*/ ) {$cppdefs = "$cppdefs -D_HIRES";}
  if ("$OCN_ICE_FORCING" eq 'inactive' ) {$cppdefs = "$cppdefs -DZERO_SEA_ICE_REF_SAL";}
  if ("$POP_TAVG_R8" eq 'TRUE'         ) {$cppdefs = "$cppdefs -DTAVG_R8";}
  $cppdefs = "$cppdefs -DECOSYS_NT=$ECOSYS_NT";
  $cppdefs = "$cppdefs -DZOOPLANKTON_CNT=$ZOOPLANKTON_CNT";
  $cppdefs = "$cppdefs -DAUTOTROPH_CNT=$AUTOTROPH_CNT";
  $cppdefs = "$cppdefs -DGRAZER_PREY_CNT=$GRAZER_PREY_CNT";
    
  # write out cppdefs to env_build.xml
  # this will determine if need to rebuild at runtime - force user to call $CASE.buildexe
  chdir "$CASEROOT";
  my $sysmod = "./xmlchange -id POP_CPPDEFS -file env_build.xml -val=\'$cppdefs\'";
  system($sysmod) == 0 or die "ERROR pop.buildnml: $sysmod failed: $?\n";

  # write out cppdefs to POP_cppdefs.new
  # this will force gmake to rebuild when $CASE.buildexe is called

  open(file,">$OBJROOT/ocn/obj/POP_cppdefs.new") or die "Could not open file $OBJROOT/ocn/obj/POP_cppdefs.new to write";
  print file "$cppdefs \n";
  close(file);
    
}

sub write_config_cache {
  open(file,">${CASEBUILD}/popconf/config_cache.xml") or die "Could not open file ${CASEBUILD}/popconf/config_cache.xml to write";
  print file <<"EOF";
<?xml version="1.0"?>
<config_definition>
<entry id="ocn_grid"   value="$OCN_GRID">
<entry id="use_iage"   value="$USE_IAGE">
<entry id="use_cfc"    value="$USE_CFC">
<entry id="use_abio"   value="$USE_ABIO">
<entry id="use_ciso"   value="$USE_CISO">
<entry id="use_ecosys" value="$USE_ECOSYS">
<entry id="use_moby"   value="$USE_MOBY">
</config_definition>
EOF
  close(file);
#  if ($print>=2) { print "Wrote file $config_cache $eol"; }
  (-f "$CASEBUILD/popconf/config_cache.xml")  or  die <<"EOF";
** $ProgName - Cannot find configuration cache file: config_cache.xml\" **
EOF

}

