#!/usr/bin/awk -f
# Calculation Standard Depth Data (T,S,Dst,dD) from Observed Data (T,S) 
# $Id: calcstd,v 1.16 1999/03/25 01:50:23 y_taka Exp $
#
# $Log: calcstd,v $
# Revision 1.16  1999/03/25 01:50:23  y_taka
# Bug fixed. (Forget clear 'ierr' in case of data depth is std layer)
#
# Revision 1.15  1999/03/16 11:15:48  y_taka
# add condition 'maxstd>j+limit' for data lack layer (Bug fixed)
#
# Revision 1.14  1999/03/16 10:12:17  y_taka
# Do not calculate STD data in case of many lack ( over 'limit' )
# layer between Observed data.
#
# Revision 1.13  1999/03/16 07:56:19  y_taka
# *** empty log message ***
#
# Revision 1.12  1998/02/05 01:08:47  y_taka
# Bug fixed when data lack of surface salinity
# consider surface temp using Bucket
#
# Revision 1.11  1997/10/22 04:55:03  y_taka
# bug fixed interpolation in case of only 2 available data.
#
# Revision 1.10  1997/10/20 09:35:11  y_taka
# bug fixed at interpolation part
#
# Revision 1.9  1997/10/20 03:03:30  y_taka
# Bug fixed for interporate (at max. dep)
#
# Revision 1.8  1997/10/20 02:45:44  y_taka
# Bug fixed for Dst out (%d omit the fraction)
#
# Revision 1.7  1997/10/07 01:22:55  y_taka
# bug fixed in case of data of lack ( column shift )
#
# Revision 1.6  1997/05/11  11:39:23  y_taka
# Bug fixed calculation of deltaD in case of Max.STD depth is 10 meters.
#
# Revision 1.5  1997/05/10 14:54:51  y_taka
# Bug fixed in case of OBS layer larger than STD layer
#
# Revision 1.4  1997/05/10 14:06:28  y_taka
# Bug fixed in case of OBS data only 2
#
# Revision 1.3  1997/05/10 13:19:54  y_taka
# Bug fixed in case of missing data
#
# Revision 1.2  1997/05/02 05:15:44  y_taka
# Consider Salinity expression (%6.3f / %5.2f)
#
# Revision 1.1  1997/05/02  01:03:20  y_taka
# Initial revision
#
#
BEGIN{ stddep="0 10 20 30 50 75 100 125 150 200 250 300 400 500"
       stddep=stddep " 600 700 800 900 1000 1200 1500 2000 2500"
       stddep=stddep " 3000 3500 4000 4500 5000 5500 6000 6500"
       maxstd=split(stddep, std, " ")
       A3500=astp(35.0,0.0,0.0)
      }
FNR==1{i=0
       j=0
       print
       next}
#----------------------------------
      {i++
       data[i]=$0
       if(i>2){
         depth=substr($0,17,4)
         if(depth!~/^ *$/){
           dep[j]=depth
           tmp[j]=substr($0,22,5)
           sal[j]=substr($0,28,6)
           j++
           }
        }
      }
/@$/{ datnum=j
      dataline=i
      for(i=0;i<datnum;i++){
        if(i in tmp){
          if(tmp[i]~/^ *- *$/) continue
          if(tmp[i]~/^[ 0-3][0-9]\.[0-9] $/){
            tmpsurf="%4.1f  "
          } else {
            tmpsurf="%5.2f "
          }
          break
        }
      }
      for(i=0;i<datnum;i++){
        if(i in sal){
          if(sal[i]~/^ *- *$/) continue
          if(sal[i]~/^[0-9][0-9]\.[0-9][0-9][0-9]$/){
            salfmt="%6.3f"
          } else {
            salfmt="%5.2f "
          }
          break
        }
      }
#       for(j=0;j<datnum;j++){
#         print dep[j],tmp[j],sal[j]
#       }
        ntmp=interpolate(datnum, dep, tmp, inttmp)
        nsal=interpolate(datnum, dep, sal, intsal)
        if(ntmp>nsal){
          nmx=ntmp
        } else {
          nmx=nsal
        }
#       print nmx
        deltast(nmx,inttmp,intsal,Dst)
        deltad(nmx,inttmp,intsal,deltaD)
        for( j in dep ){
          delete dep[j]
          delete tmp[j]
          delete sal[j]
        }
        i=0
        stn=substr(data[1],1,7)
        for(j=1;j<=dataline || i<nmx;j++){
          if(j>2){
            if(i<nmx){
              i++
              printf("%7s %85s", stn, substr(data[j],9,85))
              printf("%4d ", std[i])
              if( i in inttmp ){
                if(std[i]==0){
                  printf(tmpsurf, inttmp[i])
                } else {
                  printf("%5.2f ", inttmp[i])
                }
              } else {
                printf("  -   ")
              }
              if(i in intsal){
                printf(salfmt, intsal[i])
              } else {
                printf("   -  ")
              }
              if( i in Dst ){
                printf("     %4d ",Dst[i]+0.5)
              } else {
                printf("       -  ")
              }
              if( i in deltaD){
                printf("%5.3f",deltaD[i])
              } else {
                printf("  -  ")
              }
              if(i==nmx && j>=dataline){
                printf("@\n")
              } else {
                printf("=\n")
              }
            } else {
              printf("%7s %85s%32s", stn, substr(data[j],9,85),"")
              if(j==dataline){
                printf("@\n")
              } else {
                printf("=\n")
              }
            }
          } else {
            printf("%s\n",data[j])
          }
        }
        for( j in data ) delete data[j]
        for( j in inttmp ) delete inttmp[j] 
        for( j in intsal ) delete intsal[j] 
        for( j in Dst ) delete Dst[j] 
        for( j in deltaD ) delete deltaD[j] 
        i=0
        j=0
       }


function interpolate(datnum, dep, dat, intdat, i,j,amean,bmean,cmean,lp,maxdep)
{
  for( i in ddep ) delete ddep[i]
  for( i in ddat ) delete ddat[i]
  limit=5
  ierr=0
  j=0
  for(i=0;i<datnum;i++){
    if(dat[i]~/^ *\-?[0-9]*\.[0-9]* *$/){
      ddep[j]=dep[i]+0
      ddat[j]=dat[i]+0
      j++
    }
  }
  dnum=j
# for(i in ddat) print i,ddep[i],ddat[i]
  for(j=1;j<=maxstd;j++){
    if(ddep[0]>std[j]+0) continue
    lp=0
    for( i in keisu ){
      delete keisu[i]
      delete keisu1[i]
    }
    for(i=0;i<dnum;i++){
      if(std[j]+0==ddep[i]){
        intdat[j]=ddat[i]
        maxdep=j
        ierr=0
        break
      } 
      if(ddep[i]<std[j] && maxstd>j+limit && ddep[i+1]>std[j+limit]){
        ierr++
        break
      }
      if(ierr>0 && ddep[i]<std[j] && ddep[i]>std[j-1]) ierr=0
      if(std[j]+0<ddep[i]){
        if(ierr>0) break
        if(dnum>2){
         if(i>=2){
           squarefit(ddep[i-2],ddep[i-1],ddep[i],\
                     ddat[i-2],ddat[i-1],ddat[i],keisu)
           hamidashi(ddep[i-1],ddep[i],ddat[i-1],ddat[i],keisu)
           lp++
         }
         if(i<dnum-1){  # bug fixed 97/10/20
           squarefit(ddep[i-1],ddep[i],ddep[i+1],\
                     ddat[i-1],ddat[i],ddat[i+1],keisu1)
           hamidashi(ddep[i-1],ddep[i],ddat[i-1],ddat[i],keisu1)
           lp++
         }
#        for(k in keisu) print k,keisu[k],keisu1[k]
#        print j,intdat[j],ddep[i-1],ddep[i],ddat[i-1],ddat[i]
         amean=(keisu["a"]+keisu1["a"])/lp
         bmean=(keisu["b"]+keisu1["b"])/lp
         cmean=(keisu["c"]+keisu1["c"])/lp
         intdat[j]=(amean*std[j]+bmean)*std[j]+cmean
         maxdep=j
         break
        } else {
         intdat[j]=ddat[i]+(ddat[i-1]-ddat[i])/(dep[i-1]-ddep[i])*(std[j]-ddat[i])
        }
      }
    }
  }
  return maxdep
}

function squarefit(x0,x1,x2,y0,y1,y2,keisu,     w0,w1,w2)
{
  w0=y0/(x2-x0)/(x0-x1)
  w1=y1/(x0-x1)/(x1-x2)
  w2=y2/(x1-x2)/(x2-x0)
  keisu["a"]=-w0-w1-w2
  keisu["b"]=w0*(x1+x2)+w1*(x2+x0)+w2*(x0+x1)
  keisu["c"]=-w0*x1*x2-w1*x2*x0-w2*x0*x1
  return
}

function hamidashi(x1,x2,y1,y2,keisu,     e)
{
  if(keisu["a"]==0) return
  e=-keisu["b"]/keisu["a"]/2
  if((e-x1)*(e-x2)>=0 ) return
  if((e-x1)>=(x2-e)){
    keisu["a"]=(y1-y2)/(x1-x2)/(x1-x2)
    keisu["b"]=-2*keisu["a"]*x2
    keisu["c"]=y2+keisu["a"]*x2*x2
  } else {
    keisu["a"]=(y2-y1)/(x2-x1)/(x2-x1)
    keisu["b"]=-2*keisu["a"]*x1
    keisu["c"]=y1+keisu["a"]*x1*x1
  }
  return
}

function deltad(nmx,tmp,sal,deltaD,  delta)
{
  for(i=1;i<=nmx;i++){
    if( i in tmp && i in sal ){
      delta[i]=(astp(sal[i],tmp[i],std[i])-astp(35.0,0.,std[i]))*1.e4
    } else {
      nmx=i-1
      break
    }
  }
  deltaD[1]=0.0
  delsum=0.0
  if(nmx<=1) return
  if(nmx>2){
    for(i=2;i<=nmx;i++){
      lp=0
      for(k in keisu ) delete keisu[k]
      for(k in keisu1) delete keisu1[k]
      if(i<nmx){
         squarefit(std[i-1],std[i],std[i+1],\
                   delta[i-1],delta[i],delta[i+1],keisu)
         hamidashi(std[i-1],std[i],delta[i-1],delta[i],keisu)
         lp++
      }
      if(i>2){
         squarefit(std[i-2],std[i-1],std[i],\
                   delta[i-2],delta[i-1],delta[i],keisu1)
         hamidashi(std[i-1],std[i],delta[i-1],delta[i],keisu1)
         lp++
      }
      amean=(keisu["a"]+keisu1["a"])/lp
      bmean=(keisu["b"]+keisu1["b"])/lp
      cmean=(keisu["c"]+keisu1["c"])/lp

      delsum=delsum+(2.*(delta[i]+delta[i-1]+amean*std[i]*std[i-1]+cmean)\
              +bmean*(std[i]+std[i-1]))*(std[i]-std[i-1])/60.
      deltaD[i]=int(delsum*1000+0.5)/1000.
    }
  } else {
    deltaD[2]=int((delta[2]+delta[1])*(std[2]-std[1])/20.*1000+0.5)/1000.
  }
}

function deltast(nmx,tmp,sal,Dst,  i)
{
  for(i=1;i<=nmx;i++){
    if( (i in sal) && (i in tmp) )
      Dst[i]=(astp(sal[i],tmp[i],0.0)-A3500)*1.e8
  }
}

function astp(S,T,prs,  R1,R2,R3,RST0,AST0,E,BW,B,C,AW,A,U,V,KW,KST0,KSTP)
{
#        Input: Pressure in decibar
#               Temperature in degree C (ITS-90)
#               Salinity in Practical Salinity Scale 1978
#        Return value : Specifin Volume in m3/kg
   PR=prs/10.
   SR=sqrt(S)
#
#   compute density pure water at atmospheric pressure
#
   R1=((((6.536332e-9*T-1.120083e-6)*T+1.001685e-4)*T-9.095290e-3)*T\
       +6.793952e-2)*T+999.842594
   R2=(((5.3875e-9*T-8.2467e-7)*T+7.6438e-5)*T-4.0899e-3)*T+8.24493e-1
   R3=(-1.6546e-6*T+1.0227e-4)*T-5.72466e-3
   RST0=(4.8314e-4*S+R3*SR+R2)*S+R1
#
#   specific volume at atmospheric pressure
#
   AST0=1.0/RST0
   if(PR==0.0) return AST0
#
#   compute compression terms
#
   E=(9.1697e-10*T+2.0816e-8)*T-9.9348e-7
   BW=(5.2787e-8*T-6.12293e-6)*T+8.50935e-5
   B=BW+E*S
#
   C=(-1.6078e-6*T-1.0981e-5)*T+2.2838e-3
   AW=((-5.77905e-7*T+1.16092e-4)*T+1.43713e-3)*T+3.239908
   A=(1.91075e-4*SR+C)*S+AW
#
   U=(-5.3009e-4*T+1.6483e-2)*T+7.944e-2
   V=((-6.1670e-5*T+1.09987e-2)*T-0.603459)*T+54.6746
   KW=(((-5.155288e-5*T+1.360477e-2)*T-2.327105)*T+148.4206)*T+19652.21
   KST0=(U*SR+V)*S+KW
#
   KSTP=(B*PR+A)*PR+KST0
   return AST0*(1.0-PR/KSTP)
}

