diff options
author | allen <allen@6a38eb6e-646e-4a02-a296-d141613ad6c4> | 2001-01-17 12:40:06 +0000 |
---|---|---|
committer | allen <allen@6a38eb6e-646e-4a02-a296-d141613ad6c4> | 2001-01-17 12:40:06 +0000 |
commit | 67d025a8986ad4c97825981b98ab6f808ee5539d (patch) | |
tree | 0c00393f907a091a7e23be77f6cfe8b2357e74cf /src/ScalarBoundary.c | |
parent | a77bdfe08cb3994eb46a82bf54c484bf364188d0 (diff) |
Added directional scalar boundary conditions, see documentation.tex for details
of the interface. These will be extended to the other boundary conditions.
git-svn-id: http://svn.cactuscode.org/arrangements/CactusBase/Boundary/trunk@128 6a38eb6e-646e-4a02-a296-d141613ad6c4
Diffstat (limited to 'src/ScalarBoundary.c')
-rw-r--r-- | src/ScalarBoundary.c | 552 |
1 files changed, 408 insertions, 144 deletions
diff --git a/src/ScalarBoundary.c b/src/ScalarBoundary.c index 3c0fa6f..d39c28b 100644 --- a/src/ScalarBoundary.c +++ b/src/ScalarBoundary.c @@ -20,37 +20,38 @@ #include "BoundarySymmetries.h" #include "Boundary.h" +#define DEBUG_BOUNDARY + /* Internal routine prototypes */ static int BndApplyScalar1Di(cGH *GH, - int gdim, - int *doBC, + int doBC, int *lssh, - int *stencil, - CCTK_REAL var0, + int *stencil_size, + CCTK_REAL scalar_val, CCTK_REAL *var); static int BndApplyScalar2Di(cGH *GH, - int gdim, - int *doBC, + int doBC, int *lssh, int *stencil_size, - CCTK_REAL var0, + CCTK_REAL scalar_val, CCTK_REAL *var); static int BndApplyScalar3Di(cGH *GH, - int gdim, - int *doBC, + int doBC, int *lssh, int *stencil_size, - CCTK_REAL var0, + CCTK_REAL scalar_val, CCTK_REAL *var); static int ApplyBndScalar(cGH *GH, - int *stencil, - CCTK_REAL var0, + int stencil, + int *stencil_array, + CCTK_REAL scalar_val, int first_var, - int num_vars); + int num_vars, + int dir); /* Local variables */ @@ -61,6 +62,43 @@ static int ApplyBndScalar(cGH *GH, ********************************************************************/ /*@@ + @routine BndScalarDirVI + @date Tue Jan 16 2001 + @author Gabrielle Allen + @desc + Apply scalar boundaries by variable index in given direction + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ + +int BndScalarDirVI(cGH *GH, + int stencil_size, + int dir, + CCTK_REAL scalar_val, + int vi) +{ + return ApplyBndScalar(GH,stencil_size,NULL,scalar_val,vi,1,dir); +} + +void CCTK_FCALL CCTK_FNAME(BndScalarDirVI) + (int *ierr, + cGH *GH, + int *stencil_size, + int *dir, + CCTK_REAL *scalar_val, + int *vi) +{ + *ierr=BndScalarDirVI(GH, *stencil_size, *dir, *scalar_val, *vi); + return; +} + + + /*@@ @routine BndScalarVI @date Thu Mar 2 11:07:11 2000 @author Gerd Lanfermann @@ -76,21 +114,64 @@ static int ApplyBndScalar(cGH *GH, @@*/ int BndScalarVI(cGH *GH, - int *stencil, - CCTK_REAL var0, + int *stencil_size, + CCTK_REAL scalar_val, int vi) { - return ApplyBndScalar(GH,stencil,var0,vi,1); + return ApplyBndScalar(GH,-1,stencil_size,scalar_val,vi,1,0); } void CCTK_FCALL CCTK_FNAME(BndScalarVI) (int *ierr, cGH *GH, int *stencil_size, - CCTK_REAL *var0, + CCTK_REAL *scalar_val, int *vi) { - *ierr=BndScalarVI(GH, stencil_size, *var0, *vi); + *ierr=BndScalarVI(GH, stencil_size, *scalar_val, *vi); + return; +} + + + + /*@@ + @routine BndScalarDirGI + @date Tue Jan 16 2001 + @author Gabrielle Allen + @desc + Apply scalar boundaries by group index in given direction + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ + +int BndScalarDirGI(cGH *GH, + int stencil_size, + int dir, + CCTK_REAL scalar_val, + int gi) +{ + int numvars, first_vi; + + first_vi = CCTK_FirstVarIndexI(gi); + numvars = CCTK_NumVarsInGroupI(gi); + + return ApplyBndScalar(GH,stencil_size,NULL,scalar_val,first_vi,numvars,dir); +} + +void CCTK_FCALL CCTK_FNAME(BndScalarDirGI) + (int *ierr, + cGH *GH, + int *stencil_size, + int *dir, + CCTK_REAL *scalar_val, + int *gi) +{ + *ierr=BndScalarDirGI(GH, *stencil_size, *dir, *scalar_val, *gi); return; } @@ -101,7 +182,7 @@ void CCTK_FCALL CCTK_FNAME(BndScalarVI) @date Thu Mar 2 11:07:11 2000 @author Gerd Lanfermann @desc - Apply constant boundaries by group index + Apply scalar boundaries by group index @enddesc @calls @calledby @@ -112,8 +193,8 @@ void CCTK_FCALL CCTK_FNAME(BndScalarVI) @@*/ int BndScalarGI(cGH *GH, - int *stencil, - CCTK_REAL var0, + int *stencil_size, + CCTK_REAL scalar_val, int gi) { int numvars, first_vi; @@ -121,28 +202,85 @@ int BndScalarGI(cGH *GH, first_vi = CCTK_FirstVarIndexI(gi); numvars = CCTK_NumVarsInGroupI(gi); - return ApplyBndScalar(GH,stencil,var0,first_vi,numvars); + return ApplyBndScalar(GH,-1,stencil_size,scalar_val,first_vi,numvars,0); } void CCTK_FCALL CCTK_FNAME(BndScalarGI) (int *ierr, cGH *GH, int *stencil_size, - CCTK_REAL *var0, + CCTK_REAL *scalar_val, int *gi) { - *ierr=BndScalarGI(GH, stencil_size, *var0, *gi); + *ierr=BndScalarGI(GH, stencil_size, *scalar_val, *gi); return; } /*@@ + @routine BndScalarDirGN + @date Tue Jan 16 2001 + @author Gabrielle Allen + @desc + Apply scalar boundaries by group name in given direction + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ + +int BndScalarDirGN(cGH *GH, + int stencil_size, + int dir, + CCTK_REAL scalar_val, + const char *impgn) +{ + int retval; + int gi; + + gi = CCTK_GroupIndex(impgn); + + if(gi > -1) + { + retval = BndScalarDirGI(GH, stencil_size, dir, scalar_val, gi); + } + else + { + CCTK_VWarn(2,__LINE__,__FILE__,"Boundary", + "BndScalarDirGN: Cannot find group index for %s",impgn); + retval = -1; + } + + return retval; + +} + +void CCTK_FCALL CCTK_FNAME(BndScalarDirGN) + (int *ierr, + cGH *GH, + int *stencil_size, + int *dir, + CCTK_REAL *scalar_val, + ONE_FORTSTRING_ARG) +{ + ONE_FORTSTRING_CREATE(impgn) + *ierr=BndScalarDirGN(GH, *stencil_size, *dir, *scalar_val, impgn); + free(impgn); + return; +} + + + + /*@@ @routine BndScalarGN @date Thu Mar 2 11:07:11 2000 @author Gerd Lanfermann @desc - Apply constant boundaries by group name + Apply scalar boundaries by group name @enddesc @calls @calledby @@ -154,7 +292,7 @@ void CCTK_FCALL CCTK_FNAME(BndScalarGI) int BndScalarGN(cGH *GH, int *stencil_size, - CCTK_REAL var0, + CCTK_REAL scalar_val, const char *impgn) { int retval; @@ -164,7 +302,7 @@ int BndScalarGN(cGH *GH, if(gi > -1) { - retval = BndScalarGI(GH, stencil_size, var0, gi); + retval = BndScalarGI(GH, stencil_size, scalar_val, gi); } else { @@ -181,11 +319,11 @@ void CCTK_FCALL CCTK_FNAME(BndScalarGN) (int *ierr, cGH *GH, int *stencil_size, - CCTK_REAL *var0, + CCTK_REAL *scalar_val, ONE_FORTSTRING_ARG) { ONE_FORTSTRING_CREATE(impgn) - *ierr=BndScalarGN(GH, stencil_size, *var0, impgn); + *ierr=BndScalarGN(GH, stencil_size, *scalar_val, impgn); free(impgn); return; } @@ -193,11 +331,67 @@ void CCTK_FCALL CCTK_FNAME(BndScalarGN) /*@@ + @routine BndScalarDirVN + @date Tue Jan 16 2001 + @author Gabrielle Allen + @desc + Apply scalar boundaries by variable name in given direction + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ + +int BndScalarDirVN(cGH *GH, + int stencil_size, + int dir, + CCTK_REAL scalar_val, + const char *impvn) +{ + int vi; + int retval; + + vi = CCTK_VarIndex(impvn); + + if (vi>-1) + { + retval = BndScalarDirVI(GH, stencil_size, dir, scalar_val, vi); + } + else + { + CCTK_VWarn(2,__LINE__,__FILE__,"Boundary", + "BndScalarDirVN: Cannot find variable index for %s ",impvn); + retval = -1; + } + + return retval; +} + +void CCTK_FCALL CCTK_FNAME(BndScalarDirVN) + (int *ierr, + cGH *GH, + int *stencil_size, + int *dir, + CCTK_REAL *scalar_val, + ONE_FORTSTRING_ARG) +{ + ONE_FORTSTRING_CREATE(impvn) + *ierr = BndScalarDirVN(GH, *stencil_size, *dir, *scalar_val, impvn); + free(impvn); + return; +} + + + + /*@@ @routine BndScalarVN @date Thu Mar 2 11:07:11 2000 @author Gerd Lanfermann @desc - Apply constant boundaries by variable name + Apply scalar boundaries by variable name @enddesc @calls @calledby @@ -209,7 +403,7 @@ void CCTK_FCALL CCTK_FNAME(BndScalarGN) int BndScalarVN(cGH *GH, int *stencil_size, - CCTK_REAL var0, + CCTK_REAL scalar_val, const char *impvn) { int vi; @@ -219,7 +413,7 @@ int BndScalarVN(cGH *GH, if (vi>-1) { - retval = BndScalarVI(GH, stencil_size, var0, vi); + retval = BndScalarVI(GH, stencil_size, scalar_val, vi); } else { @@ -235,11 +429,11 @@ void CCTK_FCALL CCTK_FNAME(BndScalarVN) (int *ierr, cGH *GH, int *stencil_size, - CCTK_REAL *var0, + CCTK_REAL *scalar_val, ONE_FORTSTRING_ARG) { ONE_FORTSTRING_CREATE(impvn) - *ierr = BndScalarVN(GH, stencil_size, *var0, impvn); + *ierr = BndScalarVN(GH, stencil_size, *scalar_val, impvn); free(impvn); return; } @@ -249,6 +443,7 @@ void CCTK_FCALL CCTK_FNAME(BndScalarVN) /******************************************************************** ********************* Local Routines ************************* ********************************************************************/ + /*@@ @routine ApplyBndScalar @date Tue Jul 18 18:10:33 2000 @@ -265,20 +460,38 @@ void CCTK_FCALL CCTK_FNAME(BndScalarVN) @@*/ static int ApplyBndScalar(cGH *GH, - int *stencil, - CCTK_REAL var0, + int stencil, + int *stencil_array, + CCTK_REAL scalar_val, int first_var, - int num_vars) + int num_vars, + int dir) { int symmetry_handle; /* handle for the optional symmetry structure */ int vi, gi, dim; + int coord; int idim; int berr,ierr; - int *doBC, *dstag; + int dirloop1,dirloop2; + int doBC, count; + int *dstag; int *lssh; + int *sw; int timelevel; /* timelevel that condition applied on */ SymmetryGHex *sGHex; +#ifdef DEBUG_BOUNDARY + printf("Input arguments for ApplyBndScalar:\n"); + printf("GH = %x\n",GH); + printf("stencil = %d\n",stencil); + printf("stencil_array = %x\n",stencil_array); + printf("scalar_val = %f\n",scalar_val); + printf("first_var = %d\n",first_var); + printf("num_vars = %d\n",num_vars); + printf("dir = %d\n",dir); + printf("-----------------------------------\n"); +#endif + /* See if we have a symmetry array */ symmetry_handle = CCTK_GHExtensionHandle("Symmetry"); if (symmetry_handle < 0) @@ -293,8 +506,32 @@ static int ApplyBndScalar(cGH *GH, /* Get group dimension */ dim = CCTK_GroupDimFromVarI(first_var); + /* Set up stencil width array if needed */ + if (stencil_array) + { + sw = stencil_array; + } + else + { + int i; + sw = (int *)malloc(dim*sizeof(int)); + for (i=0;i<dim;i++) + { + sw[i] = 0; + } + if (dir > 0) + { + sw[dir-1] = stencil; + coord = dir-1; + } + else + { + sw[-dir-1] = stencil; + coord = -dir-1; + } + } + /* allocate arrays */ - doBC = (int *)malloc((2*dim)*sizeof(int)); dstag = (int *)malloc(dim*sizeof(int)); lssh = (int *)malloc(dim*sizeof(int)); @@ -304,100 +541,117 @@ static int ApplyBndScalar(cGH *GH, /* get the current timelevel */ timelevel = CCTK_NumTimeLevelsFromVarI (first_var) - 1; - /* if (timelevel > 0) - timelevel--;*/ - + /* Treat all boundaries or just one? */ + if (dir>0) + { + dirloop1 = 2*(dir-1)+1; + dirloop2 = dirloop1+1; + } + else if (dir<0) + { + dirloop1 = 2*(-dir-1); + dirloop2 = dirloop1+1; + } + else + { + dirloop1 = 0; + dirloop2 = 2*dim; + } + for (vi=first_var; vi<first_var+num_vars; vi++) { - /* Apply condition if: + boundary is not a symmetry boundary (no symmetry or unset(=unsed)) + boundary is a physical boundary + have enough grid points */ - if (sGHex) + + for (idim=0;idim<dim;idim++) { - for (idim=0;idim<dim;idim++) - { - doBC[idim*2] = (((sGHex->GFSym[vi][idim*2]==GFSYM_NOSYM)|| - (sGHex->GFSym[vi][idim*2]==GFSYM_UNSET)) && - GH->cctk_lsh[idim]>1 && GH->cctk_bbox[idim*2]); - doBC[idim*2+1] = (((sGHex->GFSym[vi][idim*2+1]==GFSYM_NOSYM)|| - (sGHex->GFSym[vi][idim*2+1]==GFSYM_UNSET)) && - GH->cctk_lsh[idim]>1 && GH->cctk_bbox[idim*2+1]); lssh[idim] = (int)GH->cctk_lssh[CCTK_LSSH_IDX(dstag[idim],idim)]; - } } - else + + for (count=dirloop1;count<dirloop2;count++) { - for (idim=0;idim<dim;idim++) + if (sGHex) { - doBC[idim*2] = (GH->cctk_lsh[idim]>1 && GH->cctk_bbox[idim*2]); - doBC[idim*2+1] = (GH->cctk_lsh[idim]>1 && GH->cctk_bbox[idim*2+1]); - lssh[idim] = (int)GH->cctk_lssh[CCTK_LSSH_IDX(dstag[idim],idim)]; - } - } + doBC = ( + ( (sGHex->GFSym[vi][count]==GFSYM_NOSYM) || + (sGHex->GFSym[vi][count]==GFSYM_UNSET) ) && + GH->cctk_lsh[coord]>1 && GH->cctk_bbox[count]) ? + count : -1; + } + else + { + doBC = (GH->cctk_lsh[coord]>1 && GH->cctk_bbox[count]) ? + count : -1 ; + } - - switch (dim) - { - case 1: - berr = BndApplyScalar1Di(GH, - dim, - doBC, - lssh, - stencil, - var0, - GH->data[vi][timelevel]); - break; - case 2: - berr = BndApplyScalar2Di(GH, - dim, - doBC, - lssh, - stencil, - var0, - GH->data[vi][timelevel]); - break; - case 3: - berr = BndApplyScalar3Di(GH, - dim, - doBC, - lssh, - stencil, - var0, - GH->data[vi][timelevel]); - break; - default : - berr = -1; - CCTK_VWarn(1,__LINE__,__FILE__,"Boundary", - "No scalar boudnary for dim>3: grid variable '%s'", - CCTK_VarName(vi)); + if (doBC >=0) + { + switch (dim) + { + case 1: + berr = BndApplyScalar1Di(GH, + doBC, + lssh, + sw, + scalar_val, + GH->data[vi][timelevel]); + break; + case 2: + berr = BndApplyScalar2Di(GH, + doBC, + lssh, + sw, + scalar_val, + GH->data[vi][timelevel]); + break; + case 3: + berr = BndApplyScalar3Di(GH, + doBC, + lssh, + sw, + scalar_val, + GH->data[vi][timelevel]); + break; + default : + berr = -1; + CCTK_VWarn(1,__LINE__,__FILE__,"Boundary", + "No scalar boundary for dim>3: grid variable '%s'", + CCTK_VarName(vi)); + } + } } berr = (berr>-1) ? 0 : -1; } free(dstag); - free(doBC); free(lssh); - + + if (!stencil_array) + { + free(sw); + } + return ierr; } + + /*@@ @routine BndApplyScalar3Di @date Thu Mar 2 11:08:49 2000 @author Gerd Lanfermann @desc - Apply the constant boundary condition for 3d variables - -internal routine + Apply the scalar boundary condition for 3d variables @enddesc @calls - @calledby BndScalarGI, BndScalarVI, BndScalarVN, BndScalarGN, + @calledby @history @endhistory @@ -405,17 +659,19 @@ static int ApplyBndScalar(cGH *GH, @@*/ static int BndApplyScalar3Di(cGH *GH, - int gdim, - int *doBC, - int *lsh, + int doBC, + int *lsh, int *stencil_size, - CCTK_REAL var0, + CCTK_REAL scalar_val, CCTK_REAL *var) { int i,j,k,sw; - if (doBC[0] == 1) + if (doBC == 0) { +#ifdef DEBUG_BOUNDARY + printf("Applying scalar boundary %f (lower x)\n",scalar_val); +#endif for (k=0;k<lsh[2];k++) { for (j=0;j<lsh[1];j++) @@ -423,13 +679,16 @@ static int BndApplyScalar3Di(cGH *GH, for (sw=0;sw<stencil_size[0];sw++) { var[CCTK_GFINDEX3D(GH,sw,j,k)] - = var0; + = scalar_val; } } } } - if (doBC[1] == 1) + else if (doBC == 1) { +#ifdef DEBUG_BOUNDARY + printf("Applying scalar boundary %f (upper x)\n",scalar_val); +#endif for (k=0;k<lsh[2];k++) { for (j=0;j<lsh[1];j++) @@ -437,14 +696,16 @@ static int BndApplyScalar3Di(cGH *GH, for (sw=0;sw<stencil_size[0];sw++) { var[CCTK_GFINDEX3D(GH,lsh[0]-sw-1,j,k)] - = var0; + = scalar_val; } } } } - - if (doBC[2] == 1) + else if (doBC == 2) { +#ifdef DEBUG_BOUNDARY + printf("Applying scalar boundary %d (lower y)\n",scalar_val); +#endif for (k=0;k<lsh[2];k++) { for (i=0;i<lsh[0];i++) @@ -452,14 +713,16 @@ static int BndApplyScalar3Di(cGH *GH, for (sw=0;sw<stencil_size[1];sw++) { var[CCTK_GFINDEX3D(GH,i,sw,k)] - = var0; + = scalar_val; } } } } - - if (doBC[3] == 1) + else if (doBC == 3) { +#ifdef DEBUG_BOUNDARY + printf("Applying scalar boundary %f (upper y)\n",scalar_val); +#endif for (k=0;k<lsh[2];k++) { for (i=0;i<lsh[0];i++) @@ -467,14 +730,16 @@ static int BndApplyScalar3Di(cGH *GH, for (sw=0;sw<stencil_size[1];sw++) { var[CCTK_GFINDEX3D(GH,i,lsh[1]-sw-1,k)] - = var0; + = scalar_val; } } } } - - if (doBC[4] == 1) + else if (doBC == 4) { +#ifdef DEBUG_BOUNDARY + printf("Applying scalar boundary %f (lower z)\n",scalar_val); +#endif for (j=0;j<lsh[1];j++) { for (i=0;i<lsh[0];i++) @@ -482,14 +747,16 @@ static int BndApplyScalar3Di(cGH *GH, for (sw=0;sw<stencil_size[2];sw++) { var[CCTK_GFINDEX3D(GH,i,j,sw)] - = var0; + = scalar_val; } } } } - - if (doBC[5] == 1) + else if (doBC == 5) { +#ifdef DEBUG_BOUNDARY + printf("Applying scalar boundary %f (upper z)\n",scalar_val); +#endif for (j=0;j<lsh[1];j++) { for (i=0;i<lsh[0];i++) @@ -497,7 +764,7 @@ static int BndApplyScalar3Di(cGH *GH, for (sw=0;sw<stencil_size[2];sw++) { var[CCTK_GFINDEX3D(GH,i,j,lsh[2]-sw-1)] - = var0; + = scalar_val; } } } @@ -512,8 +779,7 @@ static int BndApplyScalar3Di(cGH *GH, @date Thu Mar 2 11:08:49 2000 @author Gerd Lanfermann @desc - Apply the constant boundary condition for 2d variables - -internal routine + Apply the scalar boundary condition for 2d variables @enddesc @history @@ -522,63 +788,62 @@ static int BndApplyScalar3Di(cGH *GH, @@*/ static int BndApplyScalar2Di(cGH *GH, - int gdim, - int *doBC, + int doBC, int *lsh, int *stencil_size, - CCTK_REAL var0, + CCTK_REAL scalar_val, CCTK_REAL *var) { int i,j,sw; /* lower x */ - if (doBC[0] == 1) + if (doBC == 0) { for (j=0;j<lsh[1];j++) { for (sw=0;sw<stencil_size[0];sw++) { var[CCTK_GFINDEX2D(GH,sw,j)] - = var0; + = scalar_val; } } } /* upper x */ - if (doBC[1] == 1) + else if (doBC == 1) { for (j=0;j<lsh[1];j++) { for (sw=0;sw<stencil_size[0];sw++) { var[CCTK_GFINDEX2D(GH,lsh[0]-sw-1,j)] - = var0; + = scalar_val; } } } /* lower y */ - if (doBC[2] == 1) + else if (doBC == 2) { for (i=0;i<lsh[0];i++) { for (sw=0;sw<stencil_size[1];sw++) { var[CCTK_GFINDEX2D(GH,i,sw)] - = var0; + = scalar_val; } } } /* upper y */ - if (doBC[3] == 1) + else if (doBC == 3) { for (i=0;i<lsh[0];i++) { for (sw=0;sw<stencil_size[1];sw++) { var[CCTK_GFINDEX2D(GH,i,lsh[1]-sw-1)] - = var0; + = scalar_val; } } } @@ -592,7 +857,7 @@ static int BndApplyScalar2Di(cGH *GH, @date Thu Mar 2 11:08:49 2000 @author Gerd Lanfermann @desc - Apply the constant boundary condition for 1d variables + Apply the scalar boundary condition for 1d variables -internal routine @enddesc @history @@ -602,32 +867,31 @@ static int BndApplyScalar2Di(cGH *GH, @@*/ static int BndApplyScalar1Di(cGH *GH, - int gdim, - int *doBC, + int doBC, int *lsh, - int *stencil, - CCTK_REAL var0, + int *stencil_size, + CCTK_REAL scalar_val, CCTK_REAL *var) { int sw; /* lower x */ - if (doBC[0] == 1) + if (doBC == 0) { - for (sw=0;sw<stencil[0];sw++) + for (sw=0;sw<stencil_size[0];sw++) { var[CCTK_GFINDEX1D(GH,sw)] - = var0; + = scalar_val; } } /* upper x */ - if (doBC[1] == 1) + else if (doBC == 1) { - for (sw=0;sw<stencil[0];sw++) + for (sw=0;sw<stencil_size[0];sw++) { var[CCTK_GFINDEX1D(GH,GH->cctk_lsh[0]-sw-1)] - = var0; + = scalar_val; } } return(0); |