/* input.c (simlib), 20.nov.2002, JH */ #include #include #include #include #include #include #include #include /* Local prototypes for raster map reading and array allocation */ static float ** read_float_raster_map(int rows, int cols, char *name, float unitconv); static double ** read_double_raster_map(int rows, int cols, char *name, double unitconv); static float ** create_float_matrix(int rows, int cols, float fill_value); static double ** create_double_matrix(int rows, int cols, double fill_value); static void copy_matrix_undef_double_to_float_values(int rows, int cols, double **source, float **target); static void copy_matrix_undef_float_values(int rows, int cols, float **source, float **target); /* ************************************************************** */ /* GRASS input procedures, allocations */ /* *************************************************************** */ /*! * \brief allocate memory, read input rasters, assign UNDEF to NODATA * * \return int */ /* ************************************************************************* */ /* Read all input maps and input values into memory ************************ */ int input_data(void) { int rows = my, cols = mx; /* my and mx are global variables */ double unitconv = 0.0000002; /* mm/hr to m/s */ int if_rain = 0; G_debug(1, "Running MAR 2011 version, started modifications on 20080211"); G_debug(1, "Reading input data"); /* Elevation and gradients are mandatory */ zz = read_float_raster_map(rows, cols, elevin, 1.0); v1 = read_double_raster_map(rows, cols, dxin, 1.0); v2 = read_double_raster_map(rows, cols, dyin, 1.0); /* Update elevation map */ copy_matrix_undef_double_to_float_values(rows, cols, v1, zz); copy_matrix_undef_double_to_float_values(rows, cols, v2, zz); /* Manning surface roughnes: read map or use a single value */ if(manin != NULL) { cchez = read_float_raster_map(rows, cols, manin, 1.0); } else if(manin_val >= 0.0) { /* If no value set its set to -999.99 */ cchez = create_float_matrix(rows, cols, manin_val); }else{ G_fatal_error(_("Raster map <%s> not found, and manin_val undefined, choose one to be allowed to process"), manin); } /* Rain: read rain map or use a single value for all cells */ if (rain != NULL) { si = read_double_raster_map(rows, cols, rain, unitconv); if_rain = 1; } else if(rain_val >= 0.0) { /* If no value set its set to -999.99 */ si = create_double_matrix(rows, cols, rain_val * unitconv); if_rain = 1; } else{ si = create_double_matrix(rows, cols, (double)UNDEF); if_rain = 0; } /* Update elevation map */ copy_matrix_undef_double_to_float_values(rows, cols, si, zz); /* Load infiltration and traps if rain is present */ if(if_rain == 1) { /* Infiltration: read map or use a single value */ if (infil != NULL) { inf = read_double_raster_map(rows, cols, infil, unitconv); } else if(infil_val >= 0.0) { /* If no value set its set to -999.99 */ inf = create_double_matrix(rows, cols, infil_val * unitconv); } else{ inf = create_double_matrix(rows, cols, (double)UNDEF); } /* Traps */ if (traps != NULL) trap = read_float_raster_map(rows, cols, traps, 1.0); else trap = create_float_matrix(rows, cols, (double)UNDEF); } if (detin != NULL) { dc = read_float_raster_map(rows, cols, detin, 1.0); copy_matrix_undef_float_values(rows, cols, dc, zz); } if (tranin != NULL) { ct = read_float_raster_map(rows, cols, tranin, 1.0); copy_matrix_undef_float_values(rows, cols, ct, zz); } if (tauin != NULL) { tau = read_float_raster_map(rows, cols, tauin, 1.0); copy_matrix_undef_float_values(rows, cols, tau, zz); } if (wdepth != NULL) { gama = read_double_raster_map(rows, cols, wdepth, 1.0); copy_matrix_undef_double_to_float_values(rows, cols, gama, zz); } /* Array for gradient checking */ slope = create_double_matrix(rows, cols, 0.0); /* Create the observation points and open the logfile */ create_observation_points(); return 1; } /* ************************************************************************* */ /* data preparations, sigma, shear, etc. */ int grad_check(void) { int k, l; double zx, zy, zd2, zd4, sinsl; double cc, cmul2; double sheer; double vsum = 0.; double vmax = 0.; double chsum = 0.; double zmin = 1.e12; double zmax = -1.e12; double zd2min = 1.e12; double zd2max = -1.e12; double smin = 1.e12; double smax = -1.e12; double infmin = 1.e12; double infmax = -1.e12; double sigmax = -1.e12; double cchezmax = -1.e12; double rhow = 1000.; double gacc = 9.81; double hh = 1.; double deltaw = 1.e12; sisum = 0.; infsum = 0.; cmul2 = rhow * gacc; for (k = 0; k < my; k++) { for (l = 0; l < mx; l++) { if (zz[k][l] != UNDEF) { zx = v1[k][l]; zy = v2[k][l]; zd2 = zx * zx + zy * zy; sinsl = sqrt(zd2) / sqrt(zd2 + 1); /* sin(terrain slope) */ /* Computing MIN */ zd2 = sqrt(zd2); zd2min = amin1(zd2min, zd2); /* Computing MAX */ zd2max = amax1(zd2max, zd2); zd4 = sqrt(zd2); /* ^.25 */ if (cchez[k][l] != 0.) { cchez[k][l] = 1. / cchez[k][l]; /* 1/n */ } else { G_fatal_error(_("Zero value in Mannings n")); } if (zd2 == 0.) { v1[k][l] = 0.; v2[k][l] = 0.; slope[k][l] = 0.; } else { if (wdepth) hh = pow(gama[k][l], 2. / 3.); /* hh = 1 if there is no water depth input */ v1[k][l] = (double)hh *cchez[k][l] * zx / zd4; v2[k][l] = (double)hh *cchez[k][l] * zy / zd4; slope[k][l] = sqrt(v1[k][l] * v1[k][l] + v2[k][l] * v2[k][l]); } if (wdepth) { sheer = (double)(cmul2 * gama[k][l] * sinsl); /* shear stress */ /* if critical shear stress >= shear then all zero */ if ((sheer <= tau[k][l]) || (ct[k][l] == 0.)) { si[k][l] = 0.; sigma[k][l] = 0.; } else { si[k][l] = (double)(dc[k][l] * (sheer - tau[k][l])); sigma[k][l] = (double)(dc[k][l] / ct[k][l]) * (sheer - tau[k][l]) / (pow(sheer, 1.5)); /* rill erosion=1.5, sheet = 1.1 */ } } sisum += si[k][l]; smin = amin1(smin, si[k][l]); smax = amax1(smax, si[k][l]); if (inf) { infsum += inf[k][l]; infmin = amin1(infmin, inf[k][l]); infmax = amax1(infmax, inf[k][l]); } vmax = amax1(vmax, slope[k][l]); vsum += slope[k][l]; chsum += cchez[k][l]; zmin = amin1(zmin, (double)zz[k][l]); zmax = amax1(zmax, (double)zz[k][l]); /* not clear were needed */ if (wdepth) sigmax = amax1(sigmax, sigma[k][l]); cchezmax = amax1(cchezmax, cchez[k][l]); /* saved sqrt(sinsl)*cchez to cchez array for output */ cchez[k][l] *= sqrt(sinsl); } /* DEFined area */ } } if (inf != NULL && smax < infmax) G_warning(_("Infiltration exceeds the rainfall rate everywhere! No overland flow.")); cc = (double)mx *my; si0 = sisum / cc; vmean = vsum / cc; chmean = chsum / cc; if (inf) infmean = infsum / cc; if (wdepth) deltaw = 0.8 / (sigmax * vmax); /*time step for sediment */ deltap = 0.25 * sqrt(stepx * stepy) / vmean; /*time step for water */ if (deltaw > deltap) timec = 4.; else timec = 1.25; miter = (int)(timesec / (deltap * timec)); /* number of iterations = number of cells to pass */ iterout = (int)(iterout / (deltap * timec)); /* number of cells to pass for time series output */ fprintf(stderr, "\n"); G_message(_("Min elevation \t= %.2f m\nMax elevation \t= %.2f m\n"), zmin, zmax); G_message(_("Mean Source Rate (rainf. excess or sediment) \t= %f m/s or kg/m2s \n"), si0); G_message(_("Mean flow velocity \t= %f m/s\n"), vmean); G_message(_("Mean Mannings \t= %f\n"), 1.0 / chmean); deltap = amin1(deltap, deltaw); G_message(_("Number of iterations \t= %d cells\n"), miter); G_message(_("Time step \t= %.2f s\n"), deltap); if (wdepth) { G_message(_("Sigmax \t= %f\nMax velocity \t= %f m/s\n"), sigmax, vmax); G_message(_("Time step used \t= %.2f s\n"), deltaw); } /* if (wdepth) deltap = 0.1; * deltap for sediment is ar. average deltap and deltaw */ /* if (wdepth) deltap = (deltaw+deltap)/2.; * deltap for sediment is ar. average deltap and deltaw */ /*! For each cell (k,l) compute the length s=(v1,v2) of the path * that the particle will travel per one time step * \f$ s(k,l)=v(k,l)*dt \f$, [m]=[m/s]*[s] * give warning if there is a cell that will lead to path longer than 2 cells * * if running erosion, compute sediment transport capacity for each cell si(k,l) * \f$ * T({\bf r})=K_t({\bf r}) \bigl[\tau({\bf r})\bigr]^p * =K_t({\bf r}) \bigl[\rho_w\, g h({\bf r}) \sin \beta ({\bf r}) \bigr]^p * \f$ * [kg/ms]=... */ for (k = 0; k < my; k++) { for (l = 0; l < mx; l++) { if (zz[k][l] != UNDEF) { v1[k][l] *= deltap; v2[k][l] *= deltap; /*if(v1[k][l]*v1[k][l]+v2[k][l]*v2[k][l] > cellsize, warning, napocitaj *ak viac ako 10%a*/ /* THIS IS CORRECT SOLUTION currently commented out */ if (inf) inf[k][l] *= timesec; if (wdepth) gama[k][l] = 0.; if (et) { if (sigma[k][l] == 0. || slope[k][l] == 0.) si[k][l] = 0.; else /* temp for transp. cap. erod */ si[k][l] = si[k][l] / (slope[k][l] * sigma[k][l]); } } /* DEFined area */ } } /*! compute transport capacity limted erosion/deposition et * as a divergence of sediment transport capacity * \f$ D_T({\bf r})= \nabla\cdot {\bf T}({\bf r}) * \f$ */ if (et) { erod(si); /* compute divergence of t.capc */ if (output_et() != 1) G_fatal_error(_("Unable to write et file")); } /*! compute the inversion operator and store it in sigma - note that after this * sigma does not store the first order reaction coefficient but the operator * WRITE the equation here */ if (wdepth) { for (k = 0; k < my; k++) { for (l = 0; l < mx; l++) { if (zz[k][l] != UNDEF) { /* get back from temp */ if (et) si[k][l] = si[k][l] * slope[k][l] * sigma[k][l]; if (sigma[k][l] != 0.) /* rate of weight loss - w=w*sigma , * vaha prechadzky po n-krokoch je sigma^n */ /*!!!!! not clear what's here :-\ !!!!!*/ sigma[k][l] = exp(-sigma[k][l] * deltap * slope[k][l]); /* if(sigma[k][l]<0.5) warning, napocitaj, * ak vacsie ako 50% skonci, zmensi deltap)*/ } } /*DEFined area */ } } return 1; } /* ************************************************************************* */ void copy_matrix_undef_double_to_float_values(int rows, int cols, double **source, float **target) { int col = 0, row = 0; for(row = 0; row < rows; row++) { for(col = 0; col < cols; col++) { if(source[row][col] == UNDEF) target[row][col] = UNDEF; } } } /* ************************************************************************* */ void copy_matrix_undef_float_values(int rows, int cols, float **source, float **target) { int col = 0, row = 0; for(row = 0; row < rows; row++) { for(col = 0; col < cols; col++) { if(source[row][col] == UNDEF) target[row][col] = UNDEF; } } } /* ************************************************************************* */ float ** create_float_matrix(int rows, int cols, float fill_value) { int col = 0, row = 0; float **matrix = NULL; G_verbose_message("Creating float matrix with value %g", fill_value); /* Allocate the float marix */ matrix = G_alloc_fmatrix(rows, cols); for(row = 0; row < rows; row++) { for(col = 0; col < cols; col++) { matrix[row][col] = fill_value; } } return matrix; } /* ************************************************************************* */ double ** create_double_matrix(int rows, int cols, double fill_value) { int col = 0, row = 0; double **matrix = NULL; G_verbose_message("Creating double matrix with value %g", fill_value); /* Allocate the float marix */ matrix = G_alloc_matrix(rows, cols); for(row = 0; row < rows; row++) { for(col = 0; col < cols; col++) { matrix[row][col] = fill_value; } } return matrix; } /* ************************************************************************* */ float ** read_float_raster_map(int rows, int cols, char *name, float unitconv) { FCELL *row_buff = NULL; int fd; int col = 0, row = 0, row_rev = 0; float **matrix = NULL; G_verbose_message("Reading float map %s into memory", name); /* Open raster map */ fd = Rast_open_old(name, ""); /* Allocate the row buffer */ row_buff = Rast_allocate_f_buf(); /* Allocate the float marix */ matrix = G_alloc_fmatrix(rows, cols); for(row = 0; row < rows; row++) { Rast_get_f_row(fd, row_buff, row); for(col = 0; col < cols; col++) { /* we fill the arrays from south to north */ row_rev = rows - row - 1; /* Check for null values */ if (!Rast_is_f_null_value(row_buff + col)) matrix[row_rev][col] = (float)(unitconv * row_buff[col]); else matrix[row_rev][col] = UNDEF; } } /* Free the row buffer */ if(row_buff) G_free(row_buff); Rast_close(fd); return matrix; } /* ************************************************************************* */ double ** read_double_raster_map(int rows, int cols, char *name, double unitconv) { DCELL *row_buff = NULL; int fd; int col = 0, row = 0, row_rev; double **matrix = NULL; G_verbose_message("Reading double map %s into memory", name); /* Open raster map */ fd = Rast_open_old(name, ""); /* Allocate the row buffer */ row_buff = Rast_allocate_d_buf(); /* Allocate the double marix */ matrix = G_alloc_matrix(rows, cols); for(row = 0; row < rows; row++) { Rast_get_d_row(fd, row_buff, row); for(col = 0; col < cols; col++) { /* we fill the arrays from south to north */ row_rev = rows - row - 1; /* Check for null values */ if (!Rast_is_d_null_value(row_buff + col)) matrix[row_rev][col] = (double)(unitconv * row_buff[col]); else matrix[row_rev][col] = UNDEF; } } /* Free the row buffer */ if(row_buff) G_free(row_buff); Rast_close(fd); return matrix; }