⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sponge.c

📁 波浪数值模拟
💻 C
字号:
/* * Copyright (c) 2001-2005 Falk Feddersen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * *//* sponge.c   Falk Feddersen */       #include <math.h>#include "sponge.h"double *WS1_X0_U;   /* the Upts x=0 boundary sponge terms for ws1 in funwave manual */double *WS2_X0_U;   /* the Upts x=0 boundary sponge terms for ws2 in funwave manual */double *WS3_X0_U;   /* the Upts x=0 boundary sponge terms for ws3 in funwave manual */double *WS1_X0_V;   /* the Vpts x=0 boundary sponge terms for ws1 in funwave manual */double *WS2_X0_V;   /* the Vpts x=0 boundary sponge terms for ws2 in funwave manual */double *WS3_X0_V;   /* the Vpts x=0 boundary sponge terms for ws3 in funwave manual */double *WS1_XL_U;   /* the Upts x=L boundary sponge terms for ws1 in funwave manual */double *WS2_XL_U;   /* the Upts x=L boundary sponge terms for ws2 in funwave manual */double *WS3_XL_U;   /* the Upts x=L boundary sponge terms for ws3 in funwave manual */double *WS1_XL_V;   /* the Vpts x=L boundary sponge terms for ws1 in funwave manual */double *WS2_XL_V;   /* the Vpts x=L boundary sponge terms for ws2 in funwave manual */double *WS3_XL_V;   /* the Vpts x=L boundary sponge terms for ws3 in funwave manual */switch_t  sponge_layer_flag;   // sponge layer either on/offint ix0_width;                // width of the sponge layer starting at x=0 (the shore)int ixL_width;               // width of the sponge layer starting at x=Lx (the far boundary)double cspg1;                 // factor that goes in front of Wspg1double cspg2;                 // factor that goes in front of Wspg1double cspg3;                 // factor that goes in front of Wspg1double frequency;             // this is the wave frequencydouble omega;void allocate_all_sponge_layer_arrays() {  /* allocate all the arrays */  WS1_X0_U = (double * ) g_malloc(sizeof(double)*ix0_width);  WS2_X0_U = (double * ) g_malloc(sizeof(double)*ix0_width);  WS3_X0_U = (double * ) g_malloc(sizeof(double)*ix0_width);  WS1_X0_V = (double * ) g_malloc(sizeof(double)*ix0_width);  WS2_X0_V = (double * ) g_malloc(sizeof(double)*ix0_width);  WS3_X0_V = (double * ) g_malloc(sizeof(double)*ix0_width);  WS1_XL_U = (double * ) g_malloc(sizeof(double)*ixL_width);  WS2_XL_U = (double * ) g_malloc(sizeof(double)*ixL_width);  WS3_XL_U = (double * ) g_malloc(sizeof(double)*ixL_width);  WS1_XL_V = (double * ) g_malloc(sizeof(double)*ixL_width);  WS2_XL_V = (double * ) g_malloc(sizeof(double)*ixL_width);  WS3_XL_V = (double * ) g_malloc(sizeof(double)*ixL_width);  //  SP_F_X0 = (double * ) g_malloc(sizeof(double)*ix0_width);      //  SP_F_XL = (double * ) g_malloc(sizeof(double)*ixL_width);    }void  init_sponge_layer(sponge_layer_info_t *SP, int nx, int ny){  int i;  double f_u, f_v;  double x_u, x_v, dx_u, dx_v, tmp;  double xwidth_x0, xwidth_xL;  double xs_x0, xl_x0;  double xs_xL, xl_xL;  sponge_layer_flag = SP->sponge_layer_flag;  if (sponge_layer_flag == OFF) /* if the flag is off then don't do anything! */    return;                          ix0_width = SP->ix0_width;  ixL_width = SP->ixL_width;  cspg1 = SP->cspg1;  cspg2 = SP->cspg2;  cspg3 = SP->cspg3;    omega = 2.0 * pi * SP->frequency;  allocate_all_sponge_layer_arrays();  /* set up x0 sponge stuff first */  xs_x0 = ix0_width*dx;  xwidth_x0 = ix0_width*dx;  xl_x0 = 0;  for (i=0;i<ix0_width;i++) {    x_u = (i+1)*dx;    x_v = (i+0.5)*dx;    dx_u = (x_u - xs_x0);    dx_v = (x_v - xs_x0);    tmp = exp(1)-1;    f_u = ( exp(  dx_u*dx_u / (xwidth_x0 * xwidth_x0) ) - 1.0 )/tmp;    WS1_X0_U[i] = cspg1*omega*f_u;    WS2_X0_U[i] = cspg2*omega*f_u;    WS3_X0_U[i] = cspg3*omega*f_u;    f_v = ( exp(  dx_v*dx_v / (xwidth_x0 * xwidth_x0) ) - 1.0 )/tmp;    WS1_X0_V[i] = cspg1*omega*f_v;    WS2_X0_V[i] = cspg2*omega*f_v;    WS3_X0_V[i] = cspg3*omega*f_v;  }  /* set up xL sponge stuff next */  xs_xL = ixL_width*dx;  xwidth_xL = ixL_width*dx;  xl_xL = 0;  for (i=0;i<ixL_width;i++) {    x_u = (i+1)*dx;    x_v = (i+0.5)*dx;    dx_u = (x_u - xs_xL);    dx_v = (x_v - xs_xL);    tmp = exp(1)-1;    f_u = ( exp(  dx_u*dx_u / (xwidth_xL * xwidth_xL) ) - 1.0 )/tmp;    WS1_XL_U[ixL_width-i-1] = cspg1*omega*f_u;  /* reverse the order of application */    WS2_XL_U[ixL_width-i-1] = cspg2*omega*f_u;    WS3_XL_U[ixL_width-i-1] = cspg3*omega*f_u;    f_v = ( exp(  dx_v*dx_v / (xwidth_xL * xwidth_xL) ) - 1.0 )/tmp;    WS1_XL_V[ixL_width-i-1] = cspg1*omega*f_v;    WS2_XL_V[ixL_width-i-1] = cspg2*omega*f_v;    WS3_XL_V[ixL_width-i-1] = cspg3*omega*f_v;  }  f_v=1.0;}void  deallocate_sponge_layer( ){  g_free(WS1_X0_U);  g_free(WS2_X0_U);  g_free(WS3_X0_U);  g_free(WS1_X0_V);  g_free(WS2_X0_V);  g_free(WS3_X0_V);  g_free(WS1_XL_U);  g_free(WS2_XL_U);  g_free(WS3_XL_U);  g_free(WS1_XL_V);  g_free(WS2_XL_V);  g_free(WS3_XL_V);  //  g_free(SP_F_X0);  //  g_free(SP_F_XL);    }void  rhs_uvmom_sponge_layer_add(field2D *UTSP, field2D *VTSP, const field2D *U, const field2D *V)     //                                 const field2D *LAP_U, const field2D *LAP_V){  int i,j;  int ixLstart_u, ixLstart_v;  const int M = UTSP->M;  const double *ux0d, *vx0d, *uxLd, *vxLd;  double *utspx0d, *utspxLd;  double *vtspx0d, *vtspxLd;  double ws1u, ws2u, ws3u;  double ws1v, ws2v, ws3v;  /* Zero: check to see if sponge layer is on - if not return */  if (sponge_layer_flag == OFF)    return;  /* First the shoreward sponge layer */  utspx0d = &(UTSP->data[M]);  vtspx0d = &(VTSP->data[M]);  ux0d  = &(U->data[M]);  vx0d  = &(V->data[M]);  for (i=0;i<ix0_width;i++) {    ws1u = -WS1_X0_U[i];    ws1v = -WS1_X0_V[i];    for (j=0;j<M;j++) {      *utspx0d++ += ws1u * *ux0d++;      *vtspx0d++ += ws1v * *vx0d++;    }  }  /* Next the seaward xL sponge layer */  ixLstart_u = U->N - ixL_width - 1;  ixLstart_v = V->N - ixL_width - 1;  utspxLd = &(UTSP->data[M*(ixLstart_u)]);   //   utspxLd = &(UTSP->data[M*(ixLstart_u-1)]);  vtspxLd = &(VTSP->data[M*(ixLstart_v)]);   //   vtspxLd = &(VTSP->data[M*(ixLstart_v-1)]);  uxLd  = &(U->data[M*ixLstart_u]);  vxLd  = &(V->data[M*ixLstart_v]);  for (i=0;i<ixL_width;i++) {    ws1u = -WS1_XL_U[i];    ws1v = -WS1_XL_V[i];    for (j=0;j<M;j++) {      *utspxLd++ += ws1u * *uxLd++;      *vtspxLd++ += ws1v * *vxLd++;    }  }  /* First do the seaward sponge layer */}/* report on bottom stress stability parameters by doing a linearlized rayliegh friction analysis *///#define SMAX(a,b) ( (a)>(b) ) ? (a) : (b) )void  sponge_layer_stability_report( double dt ){    // find the largest S_u, find smallest h     double S_sp1, S_sp2;  double max_Ws1_x0, max_Ws1_xL;   if ( sponge_layer_flag == OFF )    return;  max_Ws1_x0 = WS1_X0_U[0];  max_Ws1_xL = WS1_XL_U[ixL_width-1];  S_sp1 = fabs( max_Ws1_x0 *dt);     // < 0.96 (AB2)  S_sp2 = fabs( max_Ws1_xL *dt);     // < 0.96 (AB2)  fprintf(stderr,"Sponge Rayleigh Friction (x0,xL) # = (%g , %g) \n ",S_sp1, S_sp2);  /* note that this limit of 0.25 is arbitary based on some limited experience.     It is definitely different than what is used in shallow w/ AB2 time stepping (0.96) */  if (( S_sp1>0.25) || ( S_sp2>0.25))     fprintf(stderr,"** Warning: sponge layer may be Rayleigh Friction unstable, S_sp>0.25! \n");  else    fprintf(stderr,"\n");      }/* Calculates \lap(U) and \lap(V) from istart to iend over all j.  Requires teh LU and LV be   of the right dimensions.   Maybe multiply it by the sponge layer viscosity as well */void sponge_layer_laplacian_UV(field2D *LU, field2D *LV, const field2D *U, const field2D *V, int istart, double *ws2U, double *ws2V){  int i,j,im,M,MN;  int NLU;  double utmp0,utmp1,utmp2;  double vtmp0,vtmp1,vtmp2;  double *lud, *lvd, *lvd0, *lvd1, *lvd2;  double *ud, *udup, *uddn;  double *vd, *vdup, *vddn;  double nu_sponge_u;  double nu_sponge_v;  /* First check to make sure that the size of LU and LV are appropriate given istgart and iend */  M = LU->M;  NLU = LU->N;  MN = M-1;  lud = LU->data;  lvd = LV->data;  ud =  REF2(U, istart);  udup = REF2(U, istart+1);  uddn = REF2(U, istart-1);  vd =  REF2(V, istart);  vdup = REF2(V, istart+1);  vddn = REF2(V, istart-1);  for (i=0;i<NLU;i++) {    nu_sponge_u = *ws2U++;    // this is the viscosity     nu_sponge_v = *ws2V++;    // this is the viscosity     utmp0 = (*ud) * 2.0;  // here we do j=0    utmp1 =  *udup++ - utmp0 + *uddn++;    utmp2 = *(ud+1) - utmp0 + *(ud+MN);    *lud++ = nu_sponge_u * (idx2*utmp1 + idy2*utmp2);    vtmp0 = (*vd) * 2.0;  // here we do j=0    vtmp1 =  *vdup++ - vtmp0 + *vddn++;    vtmp2 = *(vd+1) - vtmp0 + *(vd+MN);    *lvd++ = nu_sponge_v * (idx2*vtmp1 + idy2*vtmp2);    vd++;      ud++;     for (j=1;j<M-1;j++) {      utmp0 = (*ud) * 2.0;      utmp1 =  *udup++ - utmp0 + *uddn++;      utmp2 = *(ud+1) - utmp0 + *(ud-1);      *lud++ = nu_sponge_u * (idx2*utmp1 + idy2*utmp2);      ud++;       vtmp0 = (*vd) * 2.0;      vtmp1 =  *vdup++ - vtmp0 + *vddn++;      vtmp2 = *(vd+1) - vtmp0 + *(vd-1);      *lvd++ = nu_sponge_v * (idx2*vtmp1 + idy2*vtmp2);      vd++;     }    utmp0 = (*ud) * 2.0;  // here we do j=ny-1    utmp1 =  *udup++ - utmp0 + *uddn++;    utmp2 = *(ud-MN) - utmp0 + *(ud-1);    *lud++ = nu_sponge_u * (idx2*utmp1 + idy2*utmp2);    ud++;      vtmp0 = (*vd) * 2.0;  // here we do j=ny-1    vtmp1 =  *vdup++ - vtmp0 + *vddn++;    vtmp2 = *(vd-MN) - vtmp0 + *(vd-1);    *lvd++ = nu_sponge_v * (idx2*vtmp1 + idy2*vtmp2);    vd++;   }  /* lastly we must do i=nx for the V laplacian! */  nu_sponge_v = *ws2V++;    // this is the viscosity   vtmp0 = (*vd) * 2.0;  // here we do j=0  vtmp1 =  *vdup++ - vtmp0 + *vddn++;  vtmp2 = *(vd+1) - vtmp0 + *(vd+MN);  *lvd++ = nu_sponge_v * (idx2*vtmp1 + idy2*vtmp2);  vd++;    for (j=1;j<M-1;j++) {    vtmp0 = (*vd) * 2.0;    vtmp1 =  *vdup++ - vtmp0 + *vddn++;    vtmp2 = *(vd+1) - vtmp0 + *(vd-1);    *lvd++ = nu_sponge_v * (idx2*vtmp1 + idy2*vtmp2);    vd++;      }  vtmp0 = (*vd) * 2.0;  // here we do j=ny-1  vtmp1 =  *vdup++ - vtmp0 + *vddn++;  vtmp2 = *(vd-MN) - vtmp0 + *(vd-1);  *lvd++ = (idx2*vtmp1 + idy2*vtmp2);  vd++; }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -