#!/usr/bin/env ruby

=begin

=gpcat

並列計算で分割出力されたファイルを空間方向に接続する. 
指定されたディレクトリ以下の time* というディレクトリに対して再帰的に実行. 

==USAGE

  % arare-mpiadd --dir Directory


==OPTIONS

      --help   : print this message. 
      --dir    : directory name (required).

==HISTORY

  2009/04/23  K Sugiyama (created)

=end

require "numru/netcdf"
require "numru/dcl"
require "numru/ggraph"
require "getoptlong"
include NumRu

###
###引数処理
###
parser = GetoptLong.new
parser.set_options(
                   ###    global option   ###
                   ['--dir',  "-d", GetoptLong::REQUIRED_ARGUMENT],
                   ["--help", "-h", GetoptLong::NO_ARGUMENT ],
                   ["--time", "-t", GetoptLong::NO_ARGUMENT ]
                   )
begin
  parser.each_option do |name, arg|
    eval "$OPT_#{name.sub(/^--/, '').gsub(/-/, '_')} = '#{arg}'" 
  end
    rescue
  exit(1)
end

if $OPT_HELP then
  help
  exit(0)
end  

###
### 初期設定
###
coords = ["x", "y", "z", "t", "s", "t_nv", "t_bnds"] # 軸の設定
dir = "#{$OPT_dir}"           # トップディレクトリ
subdir = "time*"


###
### 空間方向に接続する. MPI 並列されていることが前提. 
###
Dir.glob("#{dir}/#{subdir}").each{ |subdir|
  p "TOPDIR: #{dir}, SUBDIR: #{subdir}"

  # ファイル名を保管する配列を用意する. 
  ncfiles = Array.new 
  mpi1 = Array.new
  mpi2 = Array.new
  mpi3 = Array.new
  
  # ファイル名を取得
  Dir::glob("#{subdir}/*").each{ |file|
    next unless  /.*\.nc/ =~ file 
    next if /restart/  =~ file      # リスタートファイルは対象外.
    next if /Zprof/    =~ file      # 解析ファイルは対象外.
    next if /Analysis/ =~ file      # 解析ファイルは対象外.
    next if /Energy/   =~ file      # 解析ファイルは対象外.
    next if /CAPE/     =~ file      # 解析ファイルは対象外.
    
    # 並列計算の場合は node* を外して保管
    file2 = File::basename(file) 
#    p file2
#    if /^([a-z,A-Z]+)_(\w*[a-z,A-Z]+)_rank(\d\d\d\d\d\d).nc$/=~ file2
    if /^([a-z,A-Z,1-9]+)_(.+)_rank(\d\d\d\d\d\d).nc$/=~ file2
      mpi1.push("#{$1}")
      mpi3.push("#{$2}")
      mpi2.push("#{$3}")
    else
      ncfiles.push(file2)
    end
  }
  
  # 重複を切る.
  mpi1.uniq!
  mpi2.uniq!
  mpi3.uniq!

  p mpi1, mpi2, mpi3

  # 取得したファイル名を元に空間的に接続する
  mpi3.each{ |mpivar|
    p mpivar

    # ファイルを用意.
    output = "#{dir}/#{subdir}/#{mpi1[0]}-all_#{mpivar}.nc"
    next if FileTest.exist?(output)
    outncfile = NetCDF.create(output)    

    # ノード 0 で存在する変数を調べる.
    ncfile = "#{dir}/#{subdir}/#{mpi1[0]}_#{mpivar}_rank000000.nc"  
    GDir.top = '/'
    gdir = GDir.new(File.expand_path(ncfile))
    
    # 変数をチェック
    gdir.list_data_v.each{|gd| 
      vars = gd.split(/\t/)
      p vars
      next if coords.index(vars[0]) # 軸定義の場合は除外.

      if (/x/ =~ vars[1])
        gphyss   = Array.new
        mpifiles = Dir.glob("#{dir}/#{subdir}/#{mpi1[0]}_#{mpivar}_rank*")
        mpifiles.sort!
        p mpifiles
        p vars[0]
        
        gphys = GPhys::IO.open(mpifiles, "#{vars[0]}")
        GPhys::IO.write( outncfile, gphys )          # Output GPhys variable
        
      else
        gphyss = Array.new
        mpi2.each{ |mpinum|           
          gturl = "#{dir}/#{subdir}/#{mpi1[0]}_#{mpivar}_rank#{mpinum}.nc@#{vars[0]}"
          p "#{mpinum.to_i}/#{mpi2.size}, #{gturl}"
          gphys = GPhys::IO.open_gturl(gturl)
          gphys = gphys.mean('x') if /x\=/ =~ vars[1]  # x 軸が存在する場合
          gphyss.push(gphys)
        }        
        gphys2 = 0.0 # test
        gphyss.each{ |gp| gphys2 = gphys2 + gp}
        gphys2 = gphys2 / mpi2.size
        GPhys::IO.write( outncfile, gphys2 )          # Output GPhys variable
      end
    }      
    outncfile.close
  }
}
