/Users/huttone/Devel/sedflux-new/sedflux/trunk/ew/flow/flow.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 #include <stdio.h>
00022 
00023 #include "flow.h"
00024 
00025 double *solve_excess_pore_pressure( double *psi , double *k , double *c , int n , double dz , double dt , double psi_top , double sed_rate )
00026 {
00027    double *l = eh_new( double , n );
00028    double *d = eh_new( double , n );
00029    double *u = eh_new( double , n );
00030    double *b = eh_new( double , n );
00031    int i;
00032 
00033    // given these new k and c, calculate the new entries for our
00034    // matrix equation that solves for psi.  here we must use psi
00035    // at the previous time step.
00036    get_matrix_coefficients( psi+1 , k+1     , c+1 , sed_rate , dz ,
00037                             dt    , psi_top , n-2 , 1.       , l  ,
00038                             d     , u       , b );
00039 
00040    // solve the tridiagonal system for the new psi.
00041    if ( !tridiag( l , d , u , b , psi+1 , n-2 ) )
00042    {
00043       eh_watch_dbl( d[0] );
00044       for ( i=0 ; i<n ; i++ )
00045       {
00046          eh_watch_dbl( psi[i] );
00047          psi[i] = psi_top;
00048       }
00049       perror( "tridiag" );
00050    }
00051 
00052    psi[0]   = psi[2];
00053    psi[n-1] = psi_top;
00054 
00055    eh_free( l );
00056    eh_free( d );
00057    eh_free( u );
00058    eh_free( b );
00059 
00060    return psi;
00061 }
00062 
00063 //BOP
00064 //
00065 // !ROUTINE: get_matrix_coefficients - calculate matrix coefficents for the unsaturated flow problem.
00066 //
00067 // !INTERFACE:
00068 //
00069 // void get_matrix_coefficients( double *psi , double *k , double *c ,
00070 //                               double r , double dz , double dt ,
00071 //                               int n , double f , double *l ,
00072 //                               double *d , double *u , double *b )
00073 //
00074 // !INPUT PARAMETERS:
00075 //
00076 // psi    the hydraulic head at the previous time step (cm).
00077 // k      the hydraulic conductivity at the next time step (cm/min).
00078 // c      the specific moisture capacity at the next time step (1/cm).
00079 // r      rain rate at the top of the sediment column (cm/min).
00080 // dz     the vertical node spacing (cm).
00081 // dt     the time step (min)
00082 // n      the lengh of the input/output vectors.
00083 // f      fraction between 0 and 1 to indicate the numerical method used.
00084 //        use f=0 for fully explicit, f=.5 for crank-nicholson, and f=1
00085 //        for fully implicit.
00086 // l      the lower diagonal entries of the system matrix (output).
00087 // d      the diagonal entries of the system matrix (output).
00088 // u      the upper diagonal entries of the system matrix (output).
00089 // b      the right hand side of the matrix equation (output).
00090 //
00091 // !DESCRIPTION:
00092 // form the matrices in our matrix equation to solve for the hydraulic
00093 // head distribution.  our matrix equation is,
00094 // $$ [ \rm A ] \{ \psi \} = \{ \rm b \} $$
00095 // the matrix $\rm A$ is the tridiagonal matrix,
00096 // $$ \left[ \matrix{
00097 // 1   & 0 \cr
00098 // l_2 & d_2    & u_2 \cr
00099 //    & \ddots & \ddots  & \ddots \cr
00100 //    &        & l_{n-1} & d_{n-1} & u_{n-1} \cr
00101 //    &        &         & -1      & 1
00102 // } \right] $$
00103 // where,
00104 // $$ \matrix{
00105 // l_i &= -\alpha \left( K_{i-1} + K_i \right) \cr
00106 // d_i &= \alpha \left( K_{i-1} + 2K_i + K_{i+1} \right) + 2 \gamma C_i\cr
00107 // u_i &= -\alpha \left( K_i + K_{i+1} \right)
00108 // }$$
00109 // the column vector, $\rm b$ is,
00110 // $$ \{ \rm b \} = \left\{ \matrix{ 
00111 // \psi_0 \cr
00112 // b_2\cr
00113 // \vdots \cr
00114 // b_{n-1} \cr 
00115 // \Delta z \left( {R\over K_n} - 1 \right)
00116 // }\right\} $$
00117 // where,
00118 // $$ b_i = \beta \left( K_{i-1} + K_i \right) \psi_{i-1}^k - \left( \beta \left( K_{i-1} + 2K_i + K_{i+1} \right) - 2\gamma C_i  \right) \psi_i^k + \beta \left( K_i + K_{i+1} \right) \psi_{i+1}^k + \Delta z \left( K_{i+1} - K_{i-1} \right) $$
00119 // where $\beta = 1-\alpha$, and $\gamma = { (\Delta z)^2 \over \Delta t}$.
00120 //
00121 // !REVISION HISTORY:
00122 // feb 2002 eric hutton initial version.
00123 //
00124 //EOP
00125 //BOC
00126 void get_matrix_coefficients( double *psi , double *k , double *c , double ds , double dz , double dt , double psi_top , int n , double f ,  double *l , double *d , double *u , double *b )
00127 {
00128    int i;
00129 
00130    d[0] = -f*2*k[0]/(dz*dz) - c[0]/dt;
00131    u[0] =  f*2*k[0]/(dz*dz);
00132    for ( i=1 ; i<n-1 ; i++ )
00133    {
00134       l[i] =  f/(dz*dz)*(.5*k[i-1]+k[i]-.5*k[i+1]);
00135       d[i] = -f/(dz*dz)*2*k[i] - c[i]/dt;
00136       u[i] =  f/(dz*dz)*(-.5*k[i-1]+k[i]+.5*k[i+1]);
00137    }
00138    l[n-1] =  f/(dz*dz)*(k[n-1]-.5*k[n]+.5*k[n-2]);
00139    d[n-1] = -f/(dz*dz)*2*k[n-1] - c[n-1]/dt;
00140 
00141    b[0] = -(1.-f)/(dz*dz)
00142         * (   psi[1]*(.5*k[-1]+k[0]-.5*k[1])
00143             - psi[0]  *(2*k[0])
00144             + psi[1]*(-.5*k[-1]+k[0]+.5*k[1]) ) 
00145         - psi[0]*c[0]/dt;
00146    for ( i=1 ; i<n-1 ; i++ )
00147    {
00148       b[i] = -(1.-f)/(dz*dz)
00149            * (   psi[i-1]*(.5*k[i-1]+k[i]-.5*k[i+1])
00150                - psi[i]  *(2*k[i])
00151                + psi[i+1]*(-.5*k[i-1] + k[i] + .5*k[i+1]) ) 
00152            - psi[i]*c[i]/dt;
00153    }
00154    b[n-1] = -(1.-f)/(dz*dz)
00155            * (   psi[n-2]*(.5*k[n-2]+k[n-1]-.5*k[n])
00156                - psi[n-1]  *(2*k[n-1])
00157                + psi_top*(-.5*k[n-2] + k[n-1] + .5*k[n]) ) 
00158            - psi[n-1]*c[n-1]/dt
00159            - f*psi_top/(dz*dz)*(k[n-1]+.5*k[n]-.5*k[n-2]);
00160 
00161 }
00162 //EOC
00163 
00164 double *solve_excess_pore_pressure_mg( double *psi , double *k , double *c , int n , double dz , double dt , double sed_rate )
00165 {
00166    int i;
00167    double *f = eh_new( double , n );
00168    double depth = dz*(n-1);
00169 
00170    for ( i=0 ; i<n ; i++ )
00171       f[i] = (-sed_rate/dt - psi[i]/dt);
00172 
00173    for ( i=0 ; i<2 ; i++ )
00174       fmg_1d( psi , k , f , n , depth , dt );
00175 
00176    eh_free( f );
00177 
00178    return psi;
00179 }
00180 
00181 double **solve_excess_pore_pressure_mg_2d( double **psi , double **kx , double **kz , double **c , int n , double dx , double dz , double dt , double *sed_rate )
00182 {
00183    int i, j;
00184    double **f = allocate_2d( n );
00185    double depth = dz*(n-1);
00186    double width = dx*(n-1);
00187 
00188    for ( i=0 ; i<n ; i++ )
00189       for ( j=0 ; j<n ; j++ )
00190          f[i][j] = (-sed_rate[i]/dt - psi[i][j]/dt);
00191 
00192    for ( i=0 ; i<5 ; i++ )
00193       fmg_2d( psi , kx , kz , f , n , width , depth , dt );
00194 
00195    eh_free( f[0] );
00196    eh_free( f    );
00197 
00198    return psi;
00199 }
00200 
00201 double ***solve_excess_pore_pressure_mg_3d( double ***psi , double ***kx , double ***kz , double ***c , int n , double dx , double dz , double dt , double **sed_rate )
00202 {
00203    int i, j, k;
00204    double ***f = allocate_3d( n );
00205    double depth = dz*(n-1);
00206    double width = dx*(n-1);
00207 
00208    for ( i=0 ; i<n ; i++ )
00209       for ( j=0 ; j<n ; j++ )
00210          for ( k=0 ; k<n ; k++ )
00211             f[i][j][k] = (-sed_rate[i][j]/dt - psi[i][j][k]/dt);
00212 
00213    for ( i=0 ; i<5 ; i++ )
00214       fmg_3d( psi , kx , kz , f , n , width , depth , dt );
00215 
00216    free_3d( f );
00217 
00218    return psi;
00219 }
00220 
00221 
00222 double *restrict_1d( double *u_2h , double *u_h , int n_h )
00223 {
00224    int i, i_2h;
00225    int n_2h = (n_h+1)/2.;
00226 
00227    for ( i_2h=1,i=2 ; i_2h<n_2h-1 ; i_2h++,i+=2 )
00228       u_2h[i_2h] = .5*u_h[i] + .25*(u_h[i-1] + u_h[i+1]);
00229 
00230    u_2h[0]      = u_h[0];
00231    u_2h[n_2h-1] = u_h[n_h-1];
00232 
00233    return u_2h;
00234 }
00235 
00236 double **restrict_2d( double **u_2h , double **u_h , int n_h )
00237 {
00238    int i, i_2h;
00239    int j, j_2h;
00240    int n_2h = (n_h+1)/2.;
00241 
00242    for ( i_2h=1,i=2 ; i_2h<n_2h-1 ; i_2h++,i+=2 )
00243       for ( j_2h=1,j=2 ; j_2h<n_2h-1 ; j_2h++,j+=2 )
00244          u_2h[i_2h][j_2h] = .5*u_h[i][j] + .125*(u_h[i-1][j] + u_h[i+1][j] + u_h[i][j-1] + u_h[i][j+1]);
00245 
00246    for ( j_2h=0,j=0 ; j_2h<n_2h ; j_2h++,j+=2 )
00247    {
00248       u_2h[0][j_2h]      = u_h[0][j];
00249       u_2h[n_2h-1][j_2h] = u_h[n_h-1][j];
00250    }
00251 
00252    for ( i_2h=0,i=0 ; i_2h<n_2h ; i_2h++,i+=2 )
00253    {
00254       u_2h[i_2h][0]      = u_h[i][0];
00255       u_2h[i_2h][n_2h-1] = u_h[i][n_h-1];
00256    }
00257 
00258    return u_2h;
00259 }
00260 
00261 double ***restrict_3d( double ***u_2h , double ***u_h , int n_h )
00262 {
00263    int i, i_2h;
00264    int j, j_2h;
00265    int k, k_2h;
00266    int n_2h = (n_h+1)/2.;
00267 
00268    for ( i_2h=1,i=2 ; i_2h<n_2h-1 ; i_2h++,i+=2 )
00269       for ( j_2h=1,j=2 ; j_2h<n_2h-1 ; j_2h++,j+=2 )
00270          for ( k_2h=1,k=2 ; k_2h<n_2h-1 ; k_2h++,k+=2 )
00271             u_2h[i_2h][j_2h][k_2h] = u_h[i][j][k]/2 
00272                                       + (   u_h[i-1][j][k] + u_h[i+1][j][k] 
00273                                           + u_h[i][j-1][k] + u_h[i][j+1][k] 
00274                                           + u_h[i][j][k-1] + u_h[i][j][k+1] )/12;
00275 
00276    for ( i_2h=0,i=0 ; i_2h<n_2h ; i_2h++,i+=2 )
00277    {
00278       for ( j_2h=0,j=0 ; j_2h<n_2h ; j_2h++,j+=2 )
00279       {
00280          u_2h[i_2h][j_2h][0]      = u_h[i][j][0];
00281          u_2h[i_2h][j_2h][n_2h-1] = u_h[i][j][n_h-1];
00282 
00283          u_2h[i_2h][n_2h-1][j_2h] = u_h[i][n_h-1][j];
00284          u_2h[i_2h][0][j_2h]      = u_h[i][0][j];
00285 
00286          u_2h[n_2h-1][i_2h][j_2h] = u_h[n_h-1][i][j];
00287          u_2h[0][i_2h][j_2h]      = u_h[0][i][j];
00288       }
00289    }
00290 
00291    return u_2h;
00292 }
00293 
00294 double *inter_1d( double *u_h , double *u_2h , int n_2h )
00295 {
00296    int i, i_h;
00297    int n_h=n_2h*2-1;
00298 
00299    for ( i_h=0,i=0 ; i_h<n_h ; i_h+=2,i++ )
00300       u_h[i_h] = u_2h[i];
00301 
00302    for ( i_h=1,i=0 ; i_h<n_h ; i_h+=2,i++ )
00303       u_h[i_h] = .5*(u_2h[i] + u_2h[i+1]);
00304 
00305    return u_h;
00306 }
00307 
00308 double **inter_2d( double **u_h , double **u_2h , int n_2h )
00309 {
00310    int i, i_h;
00311    int j, j_h;
00312    int n_h=n_2h*2-1;
00313 
00314    for ( i_h=0,i=0 ; i_h<n_h ; i_h+=2,i++ )
00315       for ( j_h=0,j=0 ; j_h<n_h ; j_h+=2,j++ )
00316          u_h[i_h][j_h] = u_2h[i][j];
00317 
00318    for ( i_h=1,i=0 ; i_h<n_h ; i_h+=2,i++ )
00319       for ( j_h=0,j=0 ; j_h<n_h ; j_h+=2,j++ )
00320          u_h[i_h][j_h] = .5*(u_2h[i][j] + u_2h[i+1][j]);
00321 
00322    for ( i=0 ; i<n_h ; i++ )
00323       for ( j=1 ; j<n_h ; j+=2 )
00324          u_h[i][j] = .5*(u_h[i][j-1] + u_h[i][j+1]);
00325 
00326    return u_h;
00327 }
00328 
00329 void print_matrix( double **a , int n );
00330 void print_matrix_3d( double ***a , int n );
00331 
00332 double ***inter_3d( double ***u_h , double ***u_2h , int n_2h )
00333 {
00334    int i, i_h;
00335    int j, j_h;
00336    int k, k_h;
00337    int n_h=n_2h*2-1;
00338 
00339    for ( i=0 ; i<n_h ; i++ )
00340       for ( j=0 ; j<n_h ; j++ )
00341          for ( k=0 ; k<n_h ; k++ )
00342             u_h[i][j][k] = -1;
00343 
00344    for ( i_h=0,i=0 ; i_h<n_h ; i_h+=2,i++ )
00345       for ( j_h=0,j=0 ; j_h<n_h ; j_h+=2,j++ )
00346          for ( k_h=0,k=0 ; k_h<n_h ; k_h+=2,k++ )
00347             u_h[i_h][j_h][k_h] = u_2h[i][j][k];
00348 
00349    for ( k_h=0,k=0 ; k_h<n_h ; k_h+=2,k++ )
00350    {
00351 
00352       for ( i_h=1,i=0 ; i_h<n_h ; i_h+=2,i++ )
00353          for ( j_h=0,j=0 ; j_h<n_h ; j_h+=2,j++ )
00354             u_h[i_h][j_h][k_h] = .5*(u_2h[i][j][k] + u_2h[i+1][j][k]);
00355 
00356       for ( i=0 ; i<n_h ; i++ )
00357          for ( j=1 ; j<n_h ; j+=2 )
00358             u_h[i][j][k_h] = .5*(u_h[i][j-1][k_h] + u_h[i][j+1][k_h]);
00359 
00360    }
00361 
00362    for ( i=0 ; i<n_h ; i++ )
00363       for ( j=0 ; j<n_h ; j++ )
00364          for ( k=1 ; k<n_h ; k+=2 )
00365             u_h[i][j][k] = .5*(u_h[i][j][k-1] + u_h[i][j][k+1]);
00366 
00367    return u_h;
00368 }
00369 
00370 double *relax_1d( double *u , double *k , double *f , int n , double dz , double dt )
00371 {
00372    int i;
00373    double h=1./(n-1)*dz;
00374    double h_2 = h*h;
00375    double u0 = u[n-1];
00376 
00377    for ( i=1 ; i<n-1 ; i++ )
00378       u[i] = ( (1/h_2)*( u[i-1]*k[i] + u[i+1]*k[i+1] ) - f[i] )*h_2/( k[i+1] + k[i] + h_2/dt );
00379 
00380    u[0]   = u[1];
00381    u[n-1] = u0;
00382 
00383    return u;
00384 }
00385 
00386 double **relax_2d( double **u , double **kx , double **kz , double **f , int n , double dx , double dz , double dt )
00387 {
00388    int i, j;
00389    double hx=1./(n-1)*dx;
00390    double hz=1./(n-1)*dz;
00391    double hx_2 = hx*hx;
00392    double hz_2 = hz*hz;
00393 
00394    for ( i=1 ; i<n-1 ; i++ )
00395       for ( j=1 ; j<n-1 ; j++ )
00396          u[i][j] = (  ( u[i-1][j]*kx[i][j] + u[i+1][j]*kx[i+1][j] )/hx_2
00397                     + ( u[i][j-1]*kz[i][j] + u[i][j+1]*kz[i][j+1] )/hz_2
00398                     - f[i][j] )
00399                   /( (kx[i][j]+kx[i+1][j])/hx_2 + (kz[i][j]+kz[i][j+1])/hz_2 + 1/dt);
00400 
00401 
00402    for ( i=0 ; i<n ; i++ )
00403    {
00404       u[0][i]   = u[1][i];
00405       u[n-1][i] = u[n-2][i];
00406       u[i][0]   = u[i][1];
00407 //      u[i][n-1] = u[i][n-2];
00408    }
00409 
00410    return u;
00411 }
00412 
00413 double ***relax_3d( double ***u , double ***kx , double ***kz , double ***f , int n , double dx , double dz , double dt )
00414 {
00415    int i, j, k;
00416    double hx=1./(n-1)*dx;
00417    double hz=1./(n-1)*dz;
00418    double hx_2 = hx*hx;
00419    double hz_2 = hz*hz;
00420 
00421    for ( i=1 ; i<n-1 ; i++ )
00422       for ( j=1 ; j<n-1 ; j++ )
00423          for ( k=1 ; k<n-1 ; k++ )
00424             u[i][j][k] = (  ( u[i-1][j][k]*kx[i][j][k] + u[i+1][j][k]*kx[i+1][j][k] )/hx_2
00425                           + ( u[i][j-1][k]*kx[i][j][k] + u[i][j+1][k]*kx[i][j+1][k] )/hx_2
00426                           + ( u[i][j][k-1]*kz[i][j][k] + u[i][j][k+1]*kz[i][j][k+1] )/hz_2
00427                           - f[i][j][k] )
00428                         /( (kx[i][j][k]+kx[i+1][j][k])/hx_2 + (kx[i][j][k]+kx[i][j+1][k])/hx_2 + (kz[i][j][k]+kz[i][j][k+1])/hz_2 + 1/dt);
00429 
00430    for ( i=0 ; i<n ; i++ )
00431       for ( j=0 ; j<n ; j++ )
00432       {
00433          u[0][i][j]   = u[1][i][j];
00434          u[n-1][i][j] = u[n-2][i][j];
00435 
00436          u[i][0][j]   = u[i][1][j];
00437          u[i][n-1][j] = u[i][n-2][j];
00438 
00439          u[i][j][0]   = u[i][j][1];
00440 //         u[i][j][n-1] = u[i][j][n-2];
00441       }
00442 
00443    return u;
00444 }
00445 
00446 double *residual_1d( double *res , double *u , double *k , double *f , int n , double dz , double dt )
00447 {
00448    int i;
00449    double h=1./(n-1)*dz;
00450    double h_2 = h*h;
00451 
00452    for ( i=1 ; i<n-1 ; i++ )
00453       res[i] = -( u[i-1]*k[i] + u[i+1]*k[i+1] - u[i]*(k[i+1] + k[i] + h_2/dt) )/h_2 + f[i];
00454 
00455    res[0]   = f[0];
00456    res[n-1] = 0;
00457 
00458    return res;
00459 }
00460 
00461 double **residual_2d( double **res , double **u , double **kx , double **kz , double **f , int n , double dx , double dz , double dt )
00462 {
00463    int i, j;
00464    double hx=1./(n-1)*dx;
00465    double hz=1./(n-1)*dz;
00466    double hx_2 = hx*hx;
00467    double hz_2 = hz*hz;
00468 
00469    for ( i=1 ; i<n-1 ; i++ )
00470       for ( j=1 ; j<n-1 ; j++ )
00471          res[i][j] = - ( u[i-1][j]*kx[i][j] + u[i+1][j]*kx[i+1][j] )/hx_2
00472                      - ( u[i][j-1]*kz[i][j] + u[i][j+1]*kz[i][j+1] )/hz_2
00473                      + u[i][j]*( kx[i][j]+kx[i+1][j] )/hx_2
00474                      + u[i][j]*( kz[i][j]+kz[i][j+1] )/hz_2
00475                      + u[i][j]/dt
00476                      + f[i][j];
00477 
00478    for ( i=0 ; i<n ; i++ )
00479    {
00480       res[0][i]   = f[0][i];
00481       res[n-1][i] = f[n-1][i];
00482       res[i][0]   = f[i][0];
00483       res[i][n-1] = 0;
00484    }
00485 
00486    return res;
00487 }
00488 
00489 double ***residual_3d( double ***res , double ***u , double ***kx , double ***kz , double ***f , int n , double dx , double dz , double dt )
00490 {
00491    int i, j, k;
00492    double hx=1./(n-1)*dx;
00493    double hz=1./(n-1)*dz;
00494    double hx_2 = hx*hx;
00495    double hz_2 = hz*hz;
00496 
00497    for ( i=1 ; i<n-1 ; i++ )
00498       for ( j=1 ; j<n-1 ; j++ )
00499          for ( j=1 ; j<n-1 ; j++ )
00500             res[i][j][k] = - ( u[i-1][j][k]*kx[i][j][k] + u[i+1][j][k]*kx[i+1][j][k] )/hx_2
00501                            - ( u[i][j-1][k]*kx[i][j][k] + u[i][j+1][k]*kx[i][j+1][k] )/hx_2
00502                            - ( u[i][j][k-1]*kz[i][j][k] + u[i][j][k+1]*kz[i][j][k+1] )/hz_2
00503                            + u[i][j][k]*( kx[i][j][k]+kx[i+1][j][k] )/hx_2
00504                            + u[i][j][k]*( kx[i][j][k]+kx[i][j+1][k] )/hx_2
00505                            + u[i][j][k]*( kz[i][j][k]+kz[i][j][k+1] )/hz_2
00506                            + u[i][j][k]/dt
00507                            + f[i][j][k];
00508 
00509    for ( i=0 ; i<n ; i++ )
00510       for ( j=0 ; j<n ; j++ )
00511       {
00512          res[0][i][j]   = f[0][i][j];
00513          res[n-1][i][j] = f[n-1][i][j];
00514 
00515          res[i][0][j]   = f[i][0][j];
00516          res[i][n-1][j] = f[i][n-1][j];
00517 
00518          res[i][j][0]   = f[i][j][0];
00519          res[i][j][n-1] = 0;
00520       }
00521 
00522    return res;
00523 }
00524 
00525 double *solve_1d( double *u , double *k , double *f , double dz , double dt )
00526 {
00527    double h=1./(3-1)*dz;
00528    double h_2 = h*h;
00529 
00530    u[1] = ( (1/h_2)*( u[0]*k[0] + u[2]*k[2] ) - f[1] )*h_2/( k[2] + k[1] + h_2/dt );
00531 
00532    return u;
00533 }
00534 
00535 double **solve_2d( double **u , double **kx , double **kz , double **f , double dx , double dz , double dt )
00536 {
00537    double hx=1./(3-1)*dx;
00538    double hz=1./(3-1)*dz;
00539    double hx_2 = hx*hx;
00540    double hz_2 = hz*hz;
00541    int i, j;
00542 
00543    i = 1;
00544    j = 1;
00545    u[i][j] = (  ( u[i-1][j]*kx[i][j] + u[i+1][j]*kx[i+1][j] )/hx_2
00546               + ( u[i][j-1]*kz[i][j] + u[i][j+1]*kz[i][j+1] )/hz_2
00547               - f[i][j] )
00548             /( (kx[i][j]+kx[i+1][j])/hx_2 + (kz[i][j]+kz[i][j+1])/hz_2 + 1/dt);
00549    return u;
00550 }
00551 
00552 double ***solve_3d( double ***u , double ***kx , double ***kz , double ***f , double dx , double dz , double dt )
00553 {
00554    double hx=1./(3-1)*dx;
00555    double hz=1./(3-1)*dz;
00556    double hx_2 = hx*hx;
00557    double hz_2 = hz*hz;
00558    int i, j, k;
00559 
00560    i = 1;
00561    j = 1;
00562    k = 1;
00563    u[i][j][k] = (  ( u[i-1][j][k]*kx[i][j][k] + u[i+1][j][k]*kx[i+1][j][k] )/hx_2
00564                  + ( u[i][j-1][k]*kx[i][j][k] + u[i][j+1][k]*kx[i][j+1][k] )/hx_2
00565                  + ( u[i][j][k-1]*kz[i][j][k] + u[i][j][k+1]*kz[i][j][k+1] )/hz_2
00566                  - f[i][j][k] )
00567                /( (kx[i][j][k]+kx[i+1][j][k])/hx_2 + (kx[i][j][k]+kx[i][j+1][k])/hx_2 + (kz[i][j][k]+kz[i][j][k+1])/hz_2 + 1/dt);
00568    return u;
00569 }
00570 
00571 double *add_inter_1d( double *u_h , double *u_2h , int n_2h )
00572 {
00573    int i, n_h=2*n_2h-1;
00574    double *r_h = eh_new( double , n_h );
00575 
00576    inter_1d( r_h , u_2h , n_2h );
00577 
00578    for ( i=0 ; i<n_h ; i++ )
00579       u_h[i] = u_h[i] + r_h[i];
00580 
00581    eh_free( r_h );
00582 
00583    return u_h;
00584 }
00585 
00586 double **add_inter_2d( double **u_h , double **u_2h , int n_2h )
00587 {
00588    int i, j, n_h=2*n_2h-1;
00589    double **r_h;
00590 
00591    r_h = allocate_2d( n_h );
00592 
00593    inter_2d( r_h , u_2h , n_2h );
00594 
00595    for ( i=0 ; i<n_h ; i++ )
00596       for ( j=0 ; j<n_h ; j++ )
00597          u_h[i][j] = u_h[i][j] + r_h[i][j];
00598 
00599    eh_free( r_h[0] );
00600    eh_free( r_h    );
00601 
00602    return u_h;
00603 }
00604 
00605 double ***add_inter_3d( double ***u_h , double ***u_2h , int n_2h )
00606 {
00607    int i, j, k, n_h=2*n_2h-1;
00608    double ***r_h;
00609 
00610    r_h = allocate_3d( n_h );
00611 
00612    inter_3d( r_h , u_2h , n_2h );
00613 
00614    for ( i=0 ; i<n_h ; i++ )
00615       for ( j=0 ; j<n_h ; j++ )
00616          for ( k=0 ; k<n_h ; k++ )
00617             u_h[i][j][k] = u_h[i][j][k] + r_h[i][j][k];
00618 
00619    free_3d( r_h );
00620 
00621    return u_h;
00622 }
00623 
00624 double *mgm_1d( double *u_h , double *k_h , double *f_h , int n_h , double dz , double dt )
00625 {
00626    int n_2h = (n_h+1)/2.;
00627    double *u_2h, *k_2h, *f_2h, *r_h;
00628 
00629    u_2h = eh_new0( double , n_2h );
00630    k_2h = eh_new ( double , n_2h );
00631    f_2h = eh_new ( double , n_2h );
00632    r_h  = eh_new ( double , n_h  );
00633 
00634    relax_1d( u_h , k_h , f_h , n_h , dz , dt );
00635    residual_1d( r_h , u_h , k_h , f_h , n_h , dz , dt );
00636 
00637    restrict_1d( f_2h , r_h , n_h );
00638    restrict_1d( k_2h , k_h , n_h );
00639 
00640    if ( n_2h > 3 )
00641       mgm_1d( u_2h , k_2h , f_2h , n_2h , dz , dt );
00642    else
00643       solve_1d( u_2h , k_2h , f_2h , dz , dt );
00644 
00645    add_inter_1d( u_h , u_2h , n_2h );
00646 
00647    relax_1d( u_h , k_h , f_h , n_h , dz , dt );
00648 
00649    eh_free( u_2h );
00650    eh_free( k_2h );
00651    eh_free( f_2h ); 
00652    eh_free( r_h  ); 
00653 
00654    return u_h;
00655 }
00656 
00657 #include <utils/utils.h>
00658 
00659 double **mgm_2d( double **u_h , double **kx_h , double **kz_h , double **f_h , int n_h , double dx , double dz , double dt )
00660 {
00661    int i, j, n_2h = (n_h+1)/2.;
00662    double **u_2h, **kx_2h, **kz_2h , **f_2h, **r_h;
00663 
00664    u_2h  = allocate_2d( n_2h );
00665    kx_2h = allocate_2d( n_2h );
00666    kz_2h = allocate_2d( n_2h );
00667    f_2h  = allocate_2d( n_2h );
00668    r_h   = allocate_2d( n_h  );
00669 
00670    for ( i=0 ; i<n_2h ; i++ )
00671       for ( j=0 ; j<n_2h ; j++ )
00672          u_2h[i][j] = 0;
00673 
00674    relax_2d( u_h , kx_h , kz_h , f_h , n_h , dx , dz , dt );
00675    residual_2d( r_h , u_h , kx_h , kz_h , f_h , n_h , dx , dz , dt );
00676 
00677    restrict_2d( f_2h , r_h , n_h );
00678    restrict_2d( kx_2h , kx_h , n_h );
00679    restrict_2d( kz_2h , kz_h , n_h );
00680 
00681    if ( n_2h > 3 )
00682       mgm_2d( u_2h , kx_2h , kz_2h , f_2h , n_2h , dx , dz , dt );
00683    else
00684       solve_2d( u_2h , kx_2h , kz_2h , f_2h , dx , dz , dt );
00685 
00686    add_inter_2d( u_h , u_2h , n_2h );
00687 
00688    relax_2d( u_h , kx_h , kz_h , f_h , n_h , dx , dz , dt );
00689 
00690    eh_free( u_2h[0]  );
00691    eh_free( kx_2h[0] );
00692    eh_free( kz_2h[0] );
00693    eh_free( f_2h[0]  ); 
00694    eh_free( r_h[0]   ); 
00695 
00696    eh_free( u_2h );
00697    eh_free( kx_2h );
00698    eh_free( kz_2h );
00699    eh_free( f_2h ); 
00700    eh_free( r_h  ); 
00701 
00702    return u_h;
00703 }
00704 
00705 double ***mgm_3d( double ***u_h , double ***kx_h , double ***kz_h , double ***f_h , int n_h , double dx , double dz , double dt )
00706 {
00707    int i, j, k, n_2h = (n_h+1)/2.;
00708    double ***u_2h, ***kx_2h, ***kz_2h , ***f_2h, ***r_h;
00709 
00710    u_2h  = allocate_3d( n_2h );
00711    kx_2h = allocate_3d( n_2h );
00712    kz_2h = allocate_3d( n_2h );
00713    f_2h  = allocate_3d( n_2h );
00714    r_h   = allocate_3d( n_h  );
00715 
00716    for ( i=0 ; i<n_2h ; i++ )
00717       for ( j=0 ; j<n_2h ; j++ )
00718          for ( k=0 ; k<n_2h ; k++ )
00719             u_2h[i][j][k] = 0;
00720 
00721    relax_3d( u_h , kx_h , kz_h , f_h , n_h , dx , dz , dt );
00722    residual_3d( r_h , u_h , kx_h , kz_h , f_h , n_h , dx , dz , dt );
00723 
00724    restrict_3d( f_2h , r_h , n_h );
00725    restrict_3d( kx_2h , kx_h , n_h );
00726    restrict_3d( kz_2h , kz_h , n_h );
00727 
00728    if ( n_2h > 3 )
00729       mgm_3d( u_2h , kx_2h , kz_2h , f_2h , n_2h , dx , dz , dt );
00730    else
00731       solve_3d( u_2h , kx_2h , kz_2h , f_2h , dx , dz , dt );
00732 
00733    add_inter_3d( u_h , u_2h , n_2h );
00734 
00735    relax_3d( u_h , kx_h , kz_h , f_h , n_h , dx , dz , dt );
00736 
00737    free_3d( u_2h );
00738    free_3d( kx_2h );
00739    free_3d( kz_2h );
00740    free_3d( f_2h ); 
00741    free_3d( r_h  ); 
00742 
00743    return u_h;
00744 }
00745 
00746 #include <utils/utils.h>
00747 
00748 double *fmg_1d( double *u_h , double *k_h , double *f_h , int n_h , double dz , double dt )
00749 {
00750    int i, n, n_grid = log2( n_h-1 );
00751    double **u = eh_new( double* , n_grid );
00752    double **k = eh_new( double* , n_grid );
00753    double **f = eh_new( double* , n_grid );
00754    double *u_2h = eh_new( double , n_h );
00755 
00756    u[n_grid-1] = u_h;
00757    k[n_grid-1] = k_h;
00758    f[n_grid-1] = f_h;
00759 
00760    n = n_h;
00761 
00762    for ( i=n_grid-2 ; i>=0 ; i-- )
00763    {
00764       n = (n+1)/2;
00765 
00766       u[i] = eh_new( double , n );
00767       k[i] = eh_new( double , n );
00768       f[i] = eh_new( double , n );
00769 
00770       restrict_1d( u[i] , u[i+1] , n*2-1 );
00771       restrict_1d( k[i] , k[i+1] , n*2-1 );
00772       restrict_1d( f[i] , f[i+1] , n*2-1 );
00773    }
00774 
00775    memcpy( u_2h , u[0] , sizeof(double)*n );
00776 
00777    for ( i=1 ; i<n_grid ; i++ )
00778    {
00779 
00780       inter_1d( u_h , u_2h , n );
00781       n = n*2-1;
00782 
00783       u_h[0]   = u_h[1];
00784       u_h[n-1] = u[i][n-1];
00785 
00786       mgm_1d( u_h , k[i] , f[i] , n , dz , dt );
00787 
00788       memcpy( u_2h , u_h , sizeof(double)*n );
00789 
00790    }
00791 
00792    return u_h;
00793 }
00794 
00795 
00796 double **fmg_2d( double **u_h , double **kx_h , double **kz_h , double **f_h , int n_h , double dx , double dz , double dt )
00797 {
00798    int i, j, l, n, n_grid = log2( n_h-1 );
00799    double ***u  = eh_new( double** , n_grid );
00800    double ***kx = eh_new( double** , n_grid );
00801    double ***kz = eh_new( double** , n_grid );
00802    double ***f  = eh_new( double** , n_grid );
00803    double **u_2h = allocate_2d( n_h );
00804 
00805    u[n_grid-1] = allocate_2d( n_h );
00806    memcpy( u[n_grid-1][0] , u_h[0] , sizeof(double)*n_h*n_h );
00807    kx[n_grid-1] = allocate_2d( n_h );
00808    memcpy( kx[n_grid-1][0] , kx_h[0] , sizeof(double)*n_h*n_h );
00809    kz[n_grid-1] = allocate_2d( n_h );
00810    memcpy( kz[n_grid-1][0] , kz_h[0] , sizeof(double)*n_h*n_h );
00811    f[n_grid-1] = allocate_2d( n_h );
00812    memcpy( f[n_grid-1][0] , f_h[0] , sizeof(double)*n_h*n_h );
00813 
00814    n = n_h;
00815 
00816    for ( i=n_grid-2 ; i>=0 ; i-- )
00817    {
00818       n = (n+1)/2;
00819 
00820       u[i]  = allocate_2d( n );
00821       kx[i] = allocate_2d( n );
00822       kz[i] = allocate_2d( n );
00823       f[i]  = allocate_2d( n );
00824 
00825       restrict_2d( u[i]  , u[i+1]  , n*2-1 );
00826       restrict_2d( kx[i] , kx[i+1] , n*2-1 );
00827       restrict_2d( kz[i] , kz[i+1] , n*2-1 );
00828       restrict_2d( f[i]  , f[i+1]  , n*2-1 );
00829    }
00830 
00831    for (j=0;j<n;j++)
00832       for (l=0;l<n;l++)
00833          u_2h[j][l] = u[0][j][l];
00834 
00835    for ( i=1 ; i<n_grid ; i++ )
00836    {
00837 
00838       inter_2d( u_h , u_2h , n );
00839       n = n*2-1;
00840 
00841       for (j=0;j<n;j++)
00842       {
00843          u_h[j][n-1] = u[i][j][n-1];
00844 
00845          u_h[0][j]   = u_h[1][j];
00846          u_h[n-1][j] = u_h[n-2][j];
00847          u_h[j][0]   = u_h[j][1];
00848       }
00849 
00850       mgm_2d( u_h , kx[i] , kz[i] , f[i] , n , dx , dz , dt );
00851 
00852       for (j=0;j<n;j++)
00853          for (l=0;l<n;l++)
00854             u_2h[j][l] = u_h[j][l];
00855 
00856    }
00857 
00858    for ( i=0 ; i<n_grid ; i++ )
00859    {
00860       free_2d( u[i]  );
00861       free_2d( kx[i] );
00862       free_2d( kz[i] );
00863       free_2d( f[i]  );
00864    }
00865 
00866    return u_h;
00867 }
00868 
00869 void print_matrix_3d( double ***a , int n );
00870 
00871 double ***fmg_3d( double ***u_h , double ***kx_h , double ***kz_h , double ***f_h , int n_h , double dx , double dz , double dt )
00872 {
00873    int i, j, k, l, m, n, n_grid = log2( n_h-1 );
00874    double ****u  = eh_new( double*** , n_grid );
00875    double ****kx = eh_new( double*** , n_grid );
00876    double ****kz = eh_new( double*** , n_grid );
00877    double ****f  = eh_new( double*** , n_grid );
00878    double ***u_2h = allocate_3d( n_h );
00879 
00880    u [n_grid-1] = allocate_3d( n_h );
00881    kx[n_grid-1] = allocate_3d( n_h );
00882    kz[n_grid-1] = allocate_3d( n_h );
00883    f [n_grid-1] = allocate_3d( n_h );
00884 
00885    for ( i=0 ; i<n_h ; i++ )
00886    {
00887       for ( j=0 ; j<n_h ; j++ )
00888       {
00889          for ( k=0 ; k<n_h ; k++ )
00890          {
00891             u [n_grid-1][i][j][k] = u_h [i][j][k];
00892             kx[n_grid-1][i][j][k] = kx_h[i][j][k];
00893             kz[n_grid-1][i][j][k] = kz_h[i][j][k];
00894             f [n_grid-1][i][j][k] = f_h [i][j][k];
00895          }
00896       }
00897    }
00898 
00899    n = n_h;
00900 
00901    for ( i=n_grid-2 ; i>=0 ; i-- )
00902    {
00903       n = (n+1)/2;
00904 
00905       u[i]  = allocate_3d( n );
00906       kx[i] = allocate_3d( n );
00907       kz[i] = allocate_3d( n );
00908       f[i]  = allocate_3d( n );
00909 
00910       restrict_3d( u[i]  , u[i+1]  , n*2-1 );
00911       restrict_3d( kx[i] , kx[i+1] , n*2-1 );
00912       restrict_3d( kz[i] , kz[i+1] , n*2-1 );
00913       restrict_3d( f[i]  , f[i+1]  , n*2-1 );
00914 
00915 //print_matrix_3d( u[i] , n );
00916    }
00917 
00918    for (j=0;j<n;j++)
00919       for (l=0;l<n;l++)
00920          for (m=0;m<n;m++)
00921             u_2h[j][l][m] = u[0][j][l][m];
00922 
00923    for ( i=1 ; i<n_grid ; i++ )
00924    {
00925 
00926 //print_matrix_3d( u_2h , n );
00927       inter_3d( u_h , u_2h , n );
00928       n = n*2-1;
00929 //print_matrix_3d( u_h , n );
00930       for ( l=0 ; l<n ; l++ )
00931          for ( m=0 ; m<n ; m++ )
00932          {
00933             u_h[0][l][m]   = u_h[1][l][m];
00934             u_h[n-1][l][m] = u_h[n-2][l][m];
00935 
00936             u_h[l][0][m]   = u_h[l][1][m];
00937             u_h[l][n-1][m] = u_h[l][n-2][m];
00938 
00939             u_h[l][m][0]   = u_h[l][m][1];
00940             u_h[l][m][n-1] = u[i][l][m][n-1];
00941          }
00942 
00943 
00944       mgm_3d( u_h , kx[i] , kz[i] , f[i] , n , dx , dz , dt );
00945 
00946       for (j=0;j<n;j++)
00947          for (l=0;l<n;l++)
00948             for (m=0;m<n;m++)
00949                u_2h[j][l][m] = u_h[j][l][m];
00950 
00951    }
00952 
00953    for ( i=0 ; i<n_grid ; i++ )
00954    {
00955       free_3d( u[i]  );
00956       free_3d( kx[i] );
00957       free_3d( kz[i] );
00958       free_3d( f[i]  );
00959    }
00960    free_3d( u_2h );
00961    eh_free( u  );
00962    eh_free( kx );
00963    eh_free( kz );
00964    eh_free( f  );
00965 
00966    return u_h;
00967 }
00968 
00969 double *allocate_1d( int n )
00970 {
00971    return eh_new( double , n );
00972 }
00973 
00974 double **allocate_2d( int n )
00975 {
00976    int i;
00977    double **ans;
00978    ans = eh_new( double* , n );
00979    ans[0] = eh_new( double , n*n );
00980    for ( i=1 ; i<n ; i++ )
00981       ans[i] = ans[i-1] + n;
00982    return ans;
00983 }
00984 
00985 double ***allocate_3d( int n )
00986 {
00987    int i, j;
00988    double ***ans;
00989 
00990    ans = eh_new( double** , n );
00991    ans[0] = eh_new( double* , n*n );
00992    ans[0][0] = eh_new( double , n*n*n );
00993 
00994    for ( i=1 ; i<n ; i++ )
00995    {
00996       ans[i] = ans[i-1] + n;
00997       ans[i][0] = ans[i-1][0] + n*n;
00998    }
00999 
01000    for ( i=0 ; i<n ; i++ )
01001       for ( j=1 ; j<n ; j++ )
01002          ans[i][j] = ans[i][j-1]+n;
01003   
01004 /*
01005    ans = eh_new( double** , n ); 
01006    for ( i=0 ; i<n ; i++ )
01007       ans[i] = eh_new( double* , n );
01008    for ( i=0 ; i<n ; i++ )
01009       for ( j=0 ; j<n ; j++ )
01010          ans[i][j] = eh_new( double , n );
01011 */
01012 
01013    return ans;
01014 }
01015 
01016 void free_2d( double **a )
01017 {
01018    eh_free( a[0] );
01019    eh_free( a );
01020 }
01021 
01022 void free_3d( double ***a )
01023 {
01024    eh_free( a[0][0] );
01025    eh_free( a[0] );
01026    eh_free( a );
01027 }
01028 
01029 void print_matrix( double **a , int n )
01030 {
01031    int i, j;
01032    for ( i=0 ; i<n ; i++ )
01033    {
01034       for ( j=0 ; j<n ; j++ )
01035          fprintf( stderr , "%f " , a[i][j] );
01036       fprintf( stderr , "\n" );
01037    }
01038 }
01039 
01040 void print_matrix_3d( double ***a , int n )
01041 {
01042    int i, j, k;
01043    for ( k=0 ; k<n ; k++ )
01044    {
01045       fprintf( stderr , "k=%d\n" , k );
01046       for ( j=0 ; j<n ; j++ )
01047       {
01048          for ( i=0 ; i<n ; i++ )
01049             fprintf( stderr , "%.2f " , a[i][j][k] );
01050          fprintf( stderr , "\n" );
01051       }
01052       fprintf( stderr , "\n\n");
01053    }
01054 
01055    fprintf( stderr , "\n\n" );
01056 }
01057 
01058 
01059 

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