/Users/huttone/Devel/sedflux-new/sedflux/trunk/ew/plume/plumecent.c

Go to the documentation of this file.
00001 //---
00002 //
00003 // This file is part of sedflux.
00004 //
00005 // sedflux is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation; either version 2 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // sedflux is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with sedflux; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 //
00019 //---
00020 
00021 /*
00022  * PlumeCent    Calculates the position; distance; and velocity along 
00023  *                      the deformed centerline for PLUME
00024  *
00025  *      Author:         M.D. Morehead
00026  *      Original:       April 1998
00027  *
00028  *
00029  *      Define:
00030  *              Li   = Inertial distance, u/f
00031  *              Licc = Inertial distance of the coastal current
00032  *              ccw  = coastal current width
00033  *              pra  = plume rotation angle
00034  *
00035  */
00036 #include "plumeinput.h"
00037 #include "plumevars.h"
00038 #include <utils/utils.h>
00039 
00040 /*
00041  *      Start of PlumeCent
00042  */
00043 int plumecent( Plume_enviro *env , Plume_grid *grid , Plume_options *opt )
00044 {
00045 #ifdef DBG
00046    FILE *fid1;  /* dbg file */
00047 #endif
00048    int ii, jj, cci, ll, lp, ll1, ll2, ll3, ll4, zclind, zmi;
00049    double Li, Licc, ccw, ccw2, dccw, ucc;
00050    double aa, AA, avo, nv, v1, v2, zm;
00051    double dyz[4], sin1, cos1, tst, dcl, pra;
00052    double **pct0, **pct1, **pct2, **pct3;
00053    Plume_river river = *(env->river);
00054    Plume_ocean ocean = *(env->ocean);
00055 
00056    // Straight Centerline
00057    if( opt->fjrd || opt->strt )
00058    {                                    // vo ~ 0
00059       for( ii=0 ; ii<grid->lx ; ii++ )
00060       {
00061          grid->pcent[ii][0] = grid->xval[ii];
00062          grid->pcent[ii][1] = 0;
00063          grid->pcent[ii][2] = grid->xval[ii];
00064       }
00065       grid->lc = grid->lx;
00066 
00067       // Calculate Centerline velocity from Albertsons Equations
00068       for( ii=0 ; ii<grid->lc ; ii++ )
00069       {
00070          if( grid->pcent[ii][2] < plg*river.b0 )   // zone of flow establishment
00071          {
00072             grid->pcent[ii][3] = river.u0;
00073          }
00074          else                                // zone of established flow
00075          {
00076             v1 = river.b0/(sqpi*C1*grid->pcent[ii][2]); // bo/(sqrt(pi)*C1*x)
00077             v2 = 0;                               // y/(sqrt(2)*C1*x)
00078             grid->pcent[ii][3] = river.u0*sqrt(v1)*exp(sq(-v2));
00079          }
00080       }
00081    }
00082    else
00083    {
00084       //---
00085       // Deform the centerline velocity with the alongshore current
00086       //
00087       // Deflected Jet centerline constants
00088       //---
00089       avo = fabs(ocean.vo);
00090       aa  = river.u0/avo;               // a = Wmo/Ue
00091       nv  = 0.37;                       // n = [ 0.375 0.380 0.370 0.385 ]
00092       AA  = 1.53 + 0.90*aa;
00093 
00094       //---
00095       // Determine subsample interval to barely guarentee the first x value
00096       //  take the equation: z1 = bo*AA*(y1(jj)/bo)^nv,
00097       //  invert it, set z1 = dx, find y1, and set dyz to this ...
00098       //  use mutliple values to reduce the total array size for small vo
00099       //---
00100       dyz[0] = 0.9*mn( river.b0*pow( grid->dx/(river.b0*AA) , 1/nv ) ,
00101                        grid->dy );
00102       dyz[1] = 0.9*mn(   river.b0*pow( (100.+grid->dx)/(river.b0*AA) , 1/nv )
00103                        - river.b0*pow(  100/(river.b0*AA) , 1/nv ) ,
00104                        grid->dy );
00105       dyz[2] = 0.9*mn(   river.b0*pow( (1000.+grid->dx)/(river.b0*AA) , 1/nv )
00106                        - river.b0*pow(  1000/(river.b0*AA) , 1/nv ) ,
00107                        grid->dy );
00108       dyz[3] = 0.9*mn(   river.b0*pow( (10000.+grid->dx)/(river.b0*AA) , 1/nv )
00109                        - river.b0*pow(  10000/(river.b0*AA) , 1/nv ) ,
00110                        grid->dy );
00111 
00112       // Initial Grid
00113       ll1 = ((int)((  100-   0)/dyz[0])) + 1;
00114       ll2 = ((int)(( 1000- 100)/dyz[1])) + 1;
00115       ll3 = ((int)((10000-1000)/dyz[2])) + 1;
00116       ll4 = ((int)((mx(1.3*grid->ymax,-1.3*grid->ymin)-10000)/dyz[3])) + 2;
00117       ll = ll1+ll2+ll3+ll4;
00118 
00119    #ifdef DBG
00120       fprintf(stderr,"  PlumeCent: Allocating pct matrices \n");
00121    #endif
00122       pct0 = new_dmatrix( ll        , 2 );
00123       pct1 = new_dmatrix( ll        , 2 );
00124       pct2 = new_dmatrix( ll        , 2 );
00125       pct3 = new_dmatrix( grid->lpc , 2 );
00126    #ifdef DBG
00127       fprintf(stderr,"          finished Allocation \n");
00128    #endif
00129 
00130       pct0[0][1] = 0;
00131       for( ii=1 ; ii<ll ; ii++ )
00132       {
00133          if( pct0[ii-1][1] < 100 )
00134             pct0[ii][1] = pct0[ii-1][1] + dyz[0];
00135          else if( pct0[ii-1][1] < 1000 )
00136             pct0[ii][1] = pct0[ii-1][1] + dyz[1];
00137          else if( pct0[ii-1][1] < 10000 )
00138             pct0[ii][1] = pct0[ii-1][1] + dyz[2];
00139          else
00140             pct0[ii][1] = pct0[ii-1][1] + dyz[3];
00141       }
00142       //---
00143       // First, Solve for the position in the + y direction
00144       //  later will map onto the xvals,yvals grid using pcent
00145       //  in the appropriate direction
00146       //
00147       // Find the jet position unaffected by Coriolis and Buoyancy
00148       //---
00149       for( ii=0 ; ii<ll ; ii++ )
00150          pct0[ii][0] = river.b0*AA*pow( pct0[ii][1]/river.b0 , nv );
00151 
00152       // Rotate by the river mouth angle (rma)
00153       sin1=sin(river.rma*degTOr);
00154       cos1=cos(river.rma*degTOr);
00155       for( ii=0 ; ii<ll ; ii++ )
00156       {
00157          pct1[ii][0] = -pct0[ii][1]*sin1 + pct0[ii][0]*cos1;
00158          pct1[ii][1] =  pct0[ii][1]*cos1 + pct0[ii][0]*sin1;
00159       }
00160 
00161       // if in the direction of Kelvin wave propagation (kwf == 1)
00162       if( opt->kwf )
00163       {
00164 
00165          // Find the Length of an inertial circle (Li: r = V/f ),
00166          //  calculate Li based on (uo+vo)/2
00167          Li     = 0.5*(river.u0+avo)/(2*omega*sin(env->lat*degTOr));
00168 
00169          // calculate coastal current width (ccw) based on the
00170          //  plume centerline velocity at the distance 10*Li
00171          ucc    = river.u0*sqrt(river.b0/(sqpi*C1*10*Li));
00172          Licc   = ucc/(2*omega*sin(env->lat*degTOr));
00173          ccw    = ocean.cc*Licc;
00174 
00175          // find the tangential distance to the start of coastal current
00176          //  assumes the coastal current starts at 2*Li downstream
00177          dccw   = sqrt( pow(2*Li,2) + pow(ccw,2) );
00178 
00179          // find the same distance to the unmodified centerline pts
00180          //  numerically minimize the quadratic equation z^2 - x^2 - y^2 = 0
00181          zclind = 0;
00182          tst = fabs( pow(dccw,2) - pow(pct1[0][0],2) - pow(pct1[0][1],2) );
00183          for ( ii=0 ; ii<ll ; ii++ )
00184          {
00185             if ( fabs( pow(dccw,2) - pow(pct1[ii][0],2) - pow(pct1[ii][1],2) )
00186                  < tst )
00187             {
00188                zclind = ii;
00189                tst = fabs(   pow(dccw,2)
00190                            - pow(pct1[ii][0],2)
00191                            - pow(pct1[ii][1],2) );
00192             }
00193          }
00194          dcl    = sqrt( pow(pct1[zclind][0],2) + pow(pct1[zclind][1],2) );
00195 
00196          //---
00197          // find the plume rotation angle to match the jet to the coastal
00198          //  current
00199          // pra = (angle to jet endpoint) - (angle to cc endpoint)
00200          //---
00201          pra    = rTOdeg*(atan2(pct1[zclind][0],pct1[zclind][1])-atan2(ccw,2*Li));
00202          //---
00203          // if the rotation angle is greater than the river mouth angle
00204          //   rotate the plume so the centerline meets the coastal current
00205          //   otherwise leave at rma
00206          //---
00207          if ( pra > 0 )
00208          {
00209             sin1 = sin(pra*degTOr);
00210             cos1 = cos(pra*degTOr);
00211          }
00212          else
00213          {
00214             sin1 = 0;
00215             cos1 = 1;
00216          }
00217          for( ii=0 ; ii<ll ; ii++ )
00218          {
00219             pct2[ii][0] = -pct1[ii][1]*sin1 + pct1[ii][0]*cos1;
00220             pct2[ii][1] =  pct1[ii][1]*cos1 + pct1[ii][0]*sin1;
00221          }
00222       }
00223       else
00224       {
00225          //---
00226          // if not in the direction of Kelvin wave propagation (already
00227          //  rotated by rma)
00228          //---
00229          for( ii=0 ; ii<ll ; ii++ )
00230          {
00231             pct2[ii][0] = pct1[ii][0];
00232             pct2[ii][1] = pct1[ii][1];
00233          }
00234       }
00235 
00236       //---
00237       // Interpolate the subsampled points onto the standard grid spacing
00238       //  only keeping unique points, and find the maximum
00239       //---
00240       pct3[0][0] = rnd(pct2[0][0]/grid->dx)*grid->dx;
00241       pct3[0][1] = rnd(pct2[0][1]/grid->dy)*grid->dy;
00242       zmi = 0;
00243       zm = pct3[0][0];
00244       lp = 1;
00245       for ( ii=1 ; ii<ll ; ii++ )
00246       {
00247          v1 = rnd(pct2[ii][0]/grid->dx)*grid->dx;
00248          v2 = rnd(pct2[ii][1]/grid->dy)*grid->dy;
00249          if ( v1 != pct3[lp-1][0] || v2 != pct3[lp-1][1] )
00250          {
00251             pct3[lp][0] = v1;
00252             pct3[lp][1] = v2;
00253             if ( v1 > zm )
00254             {
00255                zm  = v1;
00256                zmi = lp;
00257             }
00258             lp++;
00259             if ( lp > grid->lpc )
00260             {
00261                fprintf(stderr,"PlumeCENT Error (a): pct array is too small. \n");
00262                fprintf(stderr,"   lp > lpc \n");
00263                fprintf(stderr,"   increase lpc in PlumeArray.c\n");
00264                fprintf(stderr,"   lpc = %d \n", grid->lpc);
00265                fprintf(stderr,"   lp  > %d \n", lp);
00266                fprintf(stderr,"   ii  = %d \n", ii);
00267                fprintf(stderr,"   ll  = %d \n", ll);
00268                return 1;
00269             }
00270          }
00271       }
00272 
00273       //---
00274       // Adjust for location of coastal current (y > 2*Li)
00275       //---
00276       if ( opt->kwf != 0 )
00277       {
00278          // find the nearest grid point to the cc width
00279          ccw2 = rnd(ccw/grid->dx)*grid->dx;
00280 
00281          // if local max in centerline and returns to ccw
00282          if( zm > ccw2 && pct3[zmi][1] <= 2*Li )
00283          {
00284             ii = zmi;
00285             while( pct3[ii][0] > ccw2 )
00286                ii++;
00287             cci = ii;
00288          } 
00289          else if ( zm>ccw2 ) // ever increasing function but crosses centerline
00290          {
00291             ii = 0;
00292             while( pct3[ii][0] < ccw2 )
00293                ii++;
00294             cci = ii;
00295          }
00296          else
00297          {
00298             fprintf(stderr,"\n\n PlumeCent ERROR: program aborted \n");
00299             fprintf(stderr,"    Plume was over-rotated and never reached ccw \n");
00300             return 1;
00301          }
00302          //     set all centerline values greater than this to ccw
00303          ii = cci;
00304          while( ii < lp )
00305          {
00306             pct3[ii][0] = ccw2;
00307             ii++;
00308          }
00309       }
00310 
00311       //---
00312       // place into the pcent arrays
00313       //    [lx+ly,4]  -    deflected centerline information
00314       //    [:,0:1]    m    centerline position (x,y)
00315       //    [:,2]      m    distance from the river mouth, along the centerline
00316       //    [:,3]      m/s  Albertson Velocity at the centerline point
00317       //                     lc is actual end point
00318       //---
00319       if ( ocean.vo > 0 && opt->kwf == 0 )   // may exit top or side
00320       {
00321          if ( pct3[lp-1][0] > grid->xmax )   // check for exiting top
00322          {
00323             ii = lp-1;
00324             while( pct3[ii][0] > grid->xmax )
00325                ii--;
00326          }
00327          else
00328             ii = lp-1;
00329          if ( pct3[lp-1][1] > grid->ymax )   // check for exiting side
00330          {
00331             jj = lp-1;
00332             while( pct3[jj][1] > grid->ymax )
00333                jj--;
00334          }
00335          else
00336             jj = lp-1;
00337          grid->lc = mn(ii,jj)+1;
00338          for ( ii=0 ; ii<grid->lc ; ii++ )
00339          {
00340             grid->pcent[ii][0] = pct3[ii][0];
00341             grid->pcent[ii][1] = pct3[ii][1];
00342          }
00343       }
00344       else if ( ocean.vo>0 && opt->kwf!=0 ) // assume it will not exit the top
00345       {
00346          if( pct3[lp-1][1] < grid->ymax )
00347          {
00348             fprintf(stderr,"PlumeCent Error (b): not enough centerline grid points, \n");
00349             fprintf(stderr,"    the centerline does not exit the array.\n");
00350             fprintf(stderr,"    pct3[lp-1][1] < ymax \n");
00351             fprintf(stderr,"    Increase lpc in PlumeArray.c \n");
00352             fprintf(stderr,"    lpc = %d \n", grid->lpc);
00353             fprintf(stderr,"    lp  = %d \n", lp);
00354             fprintf(stderr,"    ymax  = %f \n", grid->ymax);
00355             fprintf(stderr,"    pct3[lp-1][1] = %g \n", pct3[lp-1][1]);
00356             return 1;
00357          }
00358          jj = lp-1;
00359          while ( pct3[jj][1] > grid->ymax )
00360             jj--;
00361          grid->lc = jj+1;
00362          for ( ii=0 ; ii<grid->lc ; ii++ )
00363          {
00364             grid->pcent[ii][0] = pct3[ii][0];
00365             grid->pcent[ii][1] = pct3[ii][1];
00366          }
00367       }
00368       else if ( ocean.vo < 0 && opt->kwf == 0 ) // may exit top or side
00369       {
00370          if( pct3[lp-1][0] > grid->xmax ) // check for exiting top
00371          {
00372             ii = lp-1;
00373             while ( pct3[ii][0] > grid->xmax )
00374                ii--;
00375          }
00376          else
00377             ii = lp-1;
00378          if ( -pct3[lp-1][1] < grid->ymin ) // check for exiting side
00379          {
00380             jj = lp-1;
00381             while( -pct3[jj][1] < grid->ymin )
00382                jj--;
00383          }
00384          else
00385             jj = lp-1;
00386          grid->lc = mn(ii,jj)+1;
00387          for ( ii=0 ; ii<grid->lc ; ii++ )
00388          {
00389             grid->pcent[ii][0] =  pct3[ii][0];
00390             grid->pcent[ii][1] = -pct3[ii][1];
00391          }
00392       }
00393       else   // assume it will not exit the top
00394       {
00395          if( -pct3[lp-1][1] > grid->ymin )
00396          {
00397             fprintf(stderr,"PlumeCent Error (c): not enough centerline grid points, \n");
00398             fprintf(stderr,"    the centerline does not exit the array.\n");
00399             fprintf(stderr,"    -pct3[lp-1][1] > ymin \n");
00400             fprintf(stderr,"    Increase lpc in PlumeArray.c \n");
00401             fprintf(stderr,"    lpc = %d \n", grid->lpc);
00402             fprintf(stderr,"    lp  = %d \n", lp);
00403             fprintf(stderr,"    ymin  = %f \n", grid->ymin);
00404             fprintf(stderr,"    -pct3[lp-1][1]  = %g \n", -pct3[lp-1][1]);
00405             return 1;
00406          }
00407          jj = lp-1;
00408 
00409          while ( -pct3[jj][1] < grid->ymin )
00410             jj--;
00411          grid->lc = jj+1;
00412          for ( ii=0 ; ii<grid->lc ; ii++ )
00413          {
00414             grid->pcent[ii][0] =  pct3[ii][0];
00415             grid->pcent[ii][1] = -pct3[ii][1];
00416          }
00417       } // end if() filling pcent[:][1:2] arrays
00418 
00419       //---
00420       // find the distance along the centerline and the velocity
00421       //---
00422       grid->pcent[0][2] = grid->xval[0];   // distance along centerline
00423       grid->pcent[0][3] = river.u0;  // Albertson Velocity
00424 
00425       for( ii=1 ; ii<grid->lc ; ii++ )
00426       {
00427          //---
00428          // distance along the plume
00429          // (last distance + distance to last point) 
00430          //---
00431          grid->pcent[ii][2] = grid->pcent[ii-1][2]
00432                             + sqrt(   sq(grid->pcent[ii][0]-grid->pcent[ii-1][0])
00433                                     + sq(grid->pcent[ii][1]-grid->pcent[ii-1][1]) );
00434 
00435          // centerline velocity along the plume 
00436          if ( grid->pcent[ii][2] < plg*river.b0 ) // 'zone of flow establishment'
00437             grid->pcent[ii][3] = river.u0;
00438          else                               // 'zone of established flow'
00439          {
00440             v1 = river.b0/(sqpi*C1*grid->pcent[ii][2]); // bo/(sqrt(pi)*C1*x)
00441             v2 = 0;                               // y/(sqrt(2)*C1*x)
00442             grid->pcent[ii][3] = river.u0*sqrt(v1)*exp(-sq(v2));
00443          }
00444       }
00445    
00446       // Free up allocated memory
00447       free_dmatrix( pct0 );
00448       free_dmatrix( pct1 );
00449       free_dmatrix( pct2 );
00450       free_dmatrix( pct3 );
00451    
00452    } // end ifelse( fjrd || strt )
00453    
00454    #ifdef DBG
00455       fid1 = fopen("pcnt.dat","w");
00456       for( ii=0 ; ii<grid->lc ; ii++ )
00457       {
00458          fprintf(fid1,"%g %g %g %g \n", grid->pcent[ii][0], grid->pcent[ii][1], grid->pcent[ii][2], grid->pcent[ii][3] );
00459       }
00460       fclose(fid1);
00461    #endif
00462    
00463    return 0;
00464    
00465 } // end of PlumeCent
00466    

Generated on Fri Jan 4 18:04:15 2008 for sedflux by  doxygen 1.5.2