|
PISM, A Parallel Ice Sheet Model
stable v0.5
|
00001 // Copyright (C) 2004--2011 Torsten Albrecht and Constantine Khroulev 00002 // 00003 // This file is part of PISM. 00004 // 00005 // PISM is free software; you can redistribute it and/or modify it under the 00006 // terms of the GNU General Public License as published by the Free Software 00007 // Foundation; either version 2 of the License, or (at your option) any later 00008 // version. 00009 // 00010 // PISM is distributed in the hope that it will be useful, but WITHOUT ANY 00011 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00012 // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 00013 // details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with PISM; if not, write to the Free Software 00017 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00018 00019 #include <cmath> 00020 #include <petscdmda.h> 00021 00022 #include "iceModel.hh" 00023 #include "Mask.hh" 00024 #include "PISMOcean.hh" 00025 00027 00028 00031 00053 PetscErrorCode IceModel::killIceBergs() { 00054 PetscErrorCode ierr; 00055 00056 ierr = findIceBergCandidates(); CHKERRQ(ierr); 00057 ierr = identifyNotAnIceBerg(); CHKERRQ(ierr); 00058 ierr = killIdentifiedIceBergs(); CHKERRQ(ierr); 00059 ierr = killEasyIceBergs(); CHKERRQ(ierr); 00060 return 0; 00061 } 00062 00063 00069 PetscErrorCode IceModel::findIceBergCandidates() { 00070 PetscErrorCode ierr; 00071 ierr = verbPrintf(4, grid.com, "######### findIceBergCandidates() start\n"); CHKERRQ(ierr); 00072 00073 const PetscInt Mx = grid.Mx, My = grid.My; 00074 00075 PetscReal sea_level; 00076 if (ocean != NULL) { 00077 ierr = ocean->sea_level_elevation(sea_level); CHKERRQ(ierr); 00078 } else { SETERRQ(grid.com, 2, "PISM ERROR: ocean == NULL"); } 00079 00080 double ocean_rho = config.get("sea_water_density"), 00081 ice_rho = config.get("ice_density"); 00082 00083 ierr = vH.begin_access(); CHKERRQ(ierr); 00084 ierr = vMask.begin_access(); CHKERRQ(ierr); 00085 ierr = vIcebergMask.begin_access(); CHKERRQ(ierr); 00086 ierr = vbed.begin_access(); CHKERRQ(ierr); 00087 for (PetscInt i = grid.xs; i < grid.xs + grid.xm; ++i) { 00088 for (PetscInt j = grid.ys; j < grid.ys + grid.ym; ++j) { 00089 00090 const PetscScalar hgrounded = vbed(i, j) + vH(i, j), 00091 hfloating = sea_level + (1.0 - ice_rho / ocean_rho) * vH(i, j); 00092 00093 //cut of border of computational domain 00094 if (hgrounded < hfloating && (i <= 0 || i >= Mx - 1 || j <= 0 || j >= My - 1)) { 00095 vH(i, j) = 0.0; 00096 vIcebergMask(i, j) = ICEBERGMASK_STOP_OCEAN; 00097 vMask(i, j) = MASK_ICE_FREE_OCEAN; 00098 } else { 00099 vIcebergMask(i, j) = ICEBERGMASK_NOT_SET; 00100 } 00101 } 00102 } 00103 ierr = vH.end_access(); CHKERRQ(ierr); 00104 ierr = vMask.end_access(); CHKERRQ(ierr); 00105 ierr = vIcebergMask.end_access(); CHKERRQ(ierr); 00106 ierr = vbed.end_access(); CHKERRQ(ierr); 00107 00108 ierr = vMask.beginGhostComm(); CHKERRQ(ierr); 00109 ierr = vMask.endGhostComm(); CHKERRQ(ierr); 00110 00111 ierr = vIcebergMask.beginGhostComm(); CHKERRQ(ierr); 00112 ierr = vIcebergMask.endGhostComm(); CHKERRQ(ierr); 00113 00114 // set all floating points to ICEBERGMASK_ICEBERG_CAND 00115 MaskQuery M(vMask); 00116 ierr = vMask.begin_access(); CHKERRQ(ierr); 00117 ierr = vIcebergMask.begin_access(); CHKERRQ(ierr); 00118 for (PetscInt i = grid.xs; i < grid.xs + grid.xm; ++i) { 00119 for (PetscInt j = grid.ys; j < grid.ys + grid.ym; ++j) { 00120 if (vIcebergMask(i, j) == ICEBERGMASK_NOT_SET) { 00121 if (M.floating_ice(i, j)) { 00122 vIcebergMask(i, j) = ICEBERGMASK_ICEBERG_CAND; 00123 } 00124 } 00125 } 00126 } 00127 ierr = vIcebergMask.end_access(); CHKERRQ(ierr); 00128 00129 ierr = vIcebergMask.beginGhostComm(); CHKERRQ(ierr); 00130 ierr = vIcebergMask.endGhostComm(); CHKERRQ(ierr); 00131 00132 // set borders of shelves/icebergs to ICEBERGMASK_STOP_ATTACHED or ICEBERGMASK_STOP_OCEAN respectively. 00133 ierr = vIcebergMask.begin_access(); CHKERRQ(ierr); 00134 for (PetscInt i = grid.xs; i < grid.xs + grid.xm; ++i) { 00135 for (PetscInt j = grid.ys; j < grid.ys + grid.ym; ++j) { 00136 00137 if (vIcebergMask(i, j) == ICEBERGMASK_NOT_SET) { 00138 00139 planeStar<int> mask = vIcebergMask.int_star(i, j); 00140 00141 bool neighbor_is_candidate = ( mask.e == ICEBERGMASK_ICEBERG_CAND || 00142 mask.w == ICEBERGMASK_ICEBERG_CAND || 00143 mask.n == ICEBERGMASK_ICEBERG_CAND || 00144 mask.s == ICEBERGMASK_ICEBERG_CAND || 00145 // checks below should not be needed 00146 vIcebergMask(i + 1, j + 1) == ICEBERGMASK_ICEBERG_CAND || 00147 vIcebergMask(i + 1, j - 1) == ICEBERGMASK_ICEBERG_CAND || 00148 vIcebergMask(i - 1, j + 1) == ICEBERGMASK_ICEBERG_CAND || 00149 vIcebergMask(i - 1, j - 1) == ICEBERGMASK_ICEBERG_CAND); 00150 00151 if (M.grounded(i, j) && neighbor_is_candidate) 00152 vIcebergMask(i, j) = ICEBERGMASK_STOP_ATTACHED; 00153 else if (M.ice_free_ocean(i, j) && neighbor_is_candidate) 00154 vIcebergMask(i, j) = ICEBERGMASK_STOP_OCEAN; 00155 } 00156 } 00157 } 00158 ierr = vMask.end_access(); CHKERRQ(ierr); 00159 ierr = vIcebergMask.end_access(); CHKERRQ(ierr); 00160 00161 ierr = vIcebergMask.beginGhostComm(); CHKERRQ(ierr); 00162 ierr = vIcebergMask.endGhostComm(); CHKERRQ(ierr); 00163 return 0; 00164 } 00165 00166 00167 PetscErrorCode IceModel::identifyNotAnIceBerg() { 00168 PetscErrorCode ierr; 00169 00170 ierr = verbPrintf(4, grid.com, "######### identifyNotAnIceBerg() start\n"); CHKERRQ(ierr); 00171 00172 // this communication of ghost values is done here to make sure that asking 00173 // about neighbouring values in this routine doesn't lead to inconsistencies 00174 // in parallel computation, if the neighbour belongs to another processor 00175 // domain. 00176 // FIXME: this is probably redundant 00177 ierr = vIcebergMask.beginGhostComm(); CHKERRQ(ierr); 00178 ierr = vIcebergMask.endGhostComm(); CHKERRQ(ierr); 00179 00180 bool done = false; 00181 PetscInt loopcount = 0; 00182 while(! done){ 00183 00184 done = true; 00185 00186 ierr = vIcebergMask.begin_access(); CHKERRQ(ierr); 00187 for (PetscInt i = grid.xs; i < grid.xs + grid.xm; ++i) { 00188 for (PetscInt j = grid.ys; j < grid.ys + grid.ym; ++j) { 00189 00190 planeStar<int> mask = vIcebergMask.int_star(i, j); 00191 00192 bool attached_to_grounded = (mask.e == ICEBERGMASK_STOP_ATTACHED || 00193 mask.w == ICEBERGMASK_STOP_ATTACHED || 00194 mask.n == ICEBERGMASK_STOP_ATTACHED || 00195 mask.s == ICEBERGMASK_STOP_ATTACHED), 00196 00197 attached_to_no_iceberg = (mask.e == ICEBERGMASK_NO_ICEBERG || 00198 mask.w == ICEBERGMASK_NO_ICEBERG || 00199 mask.n == ICEBERGMASK_NO_ICEBERG || 00200 mask.s == ICEBERGMASK_NO_ICEBERG); 00201 00202 if (vIcebergMask(i, j) == ICEBERGMASK_ICEBERG_CAND && 00203 (attached_to_grounded || attached_to_no_iceberg)) { 00204 00205 vIcebergMask(i, j) = ICEBERGMASK_NO_ICEBERG; 00206 done = false; 00207 } 00208 00209 } 00210 } 00211 ierr = vIcebergMask.end_access(); CHKERRQ(ierr); 00212 00213 ierr = vIcebergMask.beginGhostComm(); CHKERRQ(ierr); 00214 ierr = vIcebergMask.endGhostComm(); CHKERRQ(ierr); 00215 00216 // We're "done" only if the iceberg mask stopped changing on *all* 00217 // processor sub-domains. 00218 int flag = done; 00219 MPI_Allreduce(MPI_IN_PLACE, &flag, 1, MPI_INT, MPI_LAND, grid.com); 00220 done = flag; 00221 00222 loopcount += 1; 00223 } 00224 00225 ierr = verbPrintf(3, grid.com, 00226 "PISM-PIK INFO: %d loop(s) were needed to identify whether there are icebergs \n", 00227 loopcount); CHKERRQ(ierr); 00228 00229 return 0; 00230 } 00231 00232 00239 PetscErrorCode IceModel::killIdentifiedIceBergs() { 00240 PetscErrorCode ierr; 00241 ierr = verbPrintf(4, grid.com, "######### killIdentifiedIceBergs() start\n"); CHKERRQ(ierr); 00242 const bool vpik = config.get_flag("verbose_pik_messages"); 00243 00244 PetscScalar 00245 my_discharge_flux = 0, 00246 discharge_flux = 0; 00247 const PetscScalar dx = grid.dx, dy = grid.dy; 00248 00249 ierr = vMask.begin_access(); CHKERRQ(ierr); 00250 ierr = vIcebergMask.begin_access(); CHKERRQ(ierr); 00251 ierr = vH.begin_access(); CHKERRQ(ierr); 00252 ierr = vh.begin_access(); CHKERRQ(ierr); 00253 for (PetscInt i = grid.xs; i < grid.xs + grid.xm; ++i) { 00254 for (PetscInt j = grid.ys; j < grid.ys + grid.ym; ++j) { 00255 00256 if (vIcebergMask(i, j) == ICEBERGMASK_ICEBERG_CAND) { 00257 // it is not a candidate any more, it is an iceberg! 00258 my_discharge_flux -= vH(i, j); 00259 vH(i, j) = 0.0; 00260 vh(i, j) = 0.0; 00261 vMask(i, j) = MASK_ICE_FREE_OCEAN; 00262 if (vpik) { 00263 PetscSynchronizedPrintf(grid.com, 00264 "PISM-PIK INFO: [rank %d] killed iceberg at i=%d, j=%d\n", 00265 grid.rank, i, j); 00266 } 00267 } 00268 00269 } 00270 } 00271 00272 ierr = vMask.end_access(); CHKERRQ(ierr); 00273 ierr = vIcebergMask.end_access(); CHKERRQ(ierr); 00274 ierr = vH.end_access(); CHKERRQ(ierr); 00275 ierr = vh.end_access(); CHKERRQ(ierr); 00276 00277 ierr = PISMGlobalSum(&my_discharge_flux, &discharge_flux, grid.com); CHKERRQ(ierr); 00278 PetscScalar factor = config.get("ice_density") * (dx * dy); 00279 cumulative_discharge_flux += discharge_flux * factor; 00280 00281 ierr = vMask.beginGhostComm(); CHKERRQ(ierr); 00282 ierr = vMask.endGhostComm(); CHKERRQ(ierr); 00283 00284 ierr = vH.beginGhostComm(); CHKERRQ(ierr); 00285 ierr = vH.endGhostComm(); CHKERRQ(ierr); 00286 00287 ierr = vh.beginGhostComm(); CHKERRQ(ierr); 00288 ierr = vh.endGhostComm(); CHKERRQ(ierr); 00289 00290 return 0; 00291 } 00292 00293 00299 PetscErrorCode IceModel::killEasyIceBergs() { 00300 PetscErrorCode ierr; 00301 ierr = verbPrintf(4, grid.com, "######### killEasyIceBergs() start\n"); CHKERRQ(ierr); 00302 const bool vpik = config.get_flag("verbose_pik_messages"); 00303 00304 PetscScalar 00305 my_discharge_flux = 0, 00306 discharge_flux = 0; 00307 const PetscScalar dx = grid.dx, dy = grid.dy; 00308 00309 IceModelVec2S vHnew = vWork2d[0]; 00310 ierr = vH.copy_to(vHnew); CHKERRQ(ierr); 00311 00312 PetscReal sea_level; 00313 if (ocean != NULL) { 00314 ierr = ocean->sea_level_elevation(sea_level); CHKERRQ(ierr); 00315 } else { SETERRQ(grid.com, 2, "PISM ERROR: ocean == NULL"); } 00316 00317 double ocean_rho = config.get("sea_water_density"), 00318 ice_rho = config.get("ice_density"); 00319 00320 // looking for grid-cell wide floating ice noses that have at least six neighbors 00321 // of thickness H=0 like this (o ocean, fl and x floating): 00322 // 00323 // o o o o o o o o o 00324 // fl x fl OR o x o OR o x fl 00325 // o o o o o o o o o 00326 00327 PetscReal C = (1.0 - ice_rho / ocean_rho); 00328 00329 ierr = vHnew.begin_access(); CHKERRQ(ierr); 00330 ierr = vH.begin_access(); CHKERRQ(ierr); 00331 ierr = vMask.begin_access(); CHKERRQ(ierr); 00332 ierr = vh.begin_access(); CHKERRQ(ierr); 00333 ierr = vbed.begin_access(); CHKERRQ(ierr); 00334 for (PetscInt i = grid.xs; i < grid.xs + grid.xm; ++i) { 00335 for (PetscInt j = grid.ys; j < grid.ys + grid.ym; ++j) { 00336 00337 planeStar<PetscScalar> thk = vH.star(i, j), 00338 bed = vbed.star(i, j); 00339 00340 // instead of updating surface elevation, counting here floating or icefree neighbors 00341 const PetscScalar hgrounded = bed.ij + thk.ij, 00342 hfloating = sea_level + (1.0 - ice_rho / ocean_rho) * thk.ij; 00343 00344 if (vH(i, j) > 0.0 && hgrounded < hfloating) { //is floating ice shelf 00345 00346 const PetscScalar 00347 hgrounded_eb = bed.e + thk.e, 00348 hfloating_eb = sea_level + C * thk.e, 00349 hgrounded_wb = bed.w + thk.w, 00350 hfloating_wb = sea_level + C * thk.w, 00351 hgrounded_nb = bed.n + thk.n, 00352 hfloating_nb = sea_level + C * thk.n, 00353 hgrounded_sb = bed.s + thk.s, 00354 hfloating_sb = sea_level + C * thk.s; 00355 00356 PetscInt jcount = 0, icount = 0; // grid-cell wide floating ice nose 00357 00358 if (vH(i + 1, j + 1) == 0.0) {jcount += 1; icount += 1;} 00359 if (vH(i + 1, j - 1) == 0.0) {jcount += 1; icount += 1;} 00360 if (vH(i - 1, j + 1) == 0.0) {jcount += 1; icount += 1;} 00361 if (vH(i - 1, j - 1) == 0.0) {jcount += 1; icount += 1;} 00362 00363 if (thk.e == 0.0) jcount += 1; 00364 if (thk.w == 0.0) jcount += 1; 00365 if (thk.n == 0.0) icount += 1; 00366 if (thk.s == 0.0) icount += 1; 00367 00368 if ((icount == 6 && hgrounded_eb < hfloating_eb && hgrounded_wb < hfloating_wb) || 00369 (jcount == 6 && hgrounded_nb < hfloating_nb && hgrounded_sb < hfloating_sb)) { 00370 00371 my_discharge_flux -= vHnew(i, j); 00372 vHnew(i, j) = 0.0; 00373 vh(i, j) = 0.0; 00374 vMask(i, j) = MASK_ICE_FREE_OCEAN; 00375 if (vpik) { 00376 PetscSynchronizedPrintf(grid.com, 00377 "PISM-PIK INFO: [rank %d] cut off nose or one-box-iceberg at i=%d, j=%d\n", 00378 grid.rank, i, j); 00379 } 00380 } 00381 } 00382 } 00383 } 00384 ierr = vH.end_access(); CHKERRQ(ierr); 00385 ierr = vHnew.end_access(); CHKERRQ(ierr); 00386 00387 // finally copy vHnew into vH and communicate ghosted values 00388 ierr = vHnew.beginGhostComm(vH); CHKERRQ(ierr); 00389 ierr = vHnew.endGhostComm(vH); CHKERRQ(ierr); 00390 00391 ierr = vH.copy_to(vHnew); CHKERRQ(ierr); 00392 00393 // looking for one-grid-cell icebergs, that have 4 neighbors of thickness H=0 00394 ierr = vH.begin_access(); CHKERRQ(ierr); 00395 ierr = vHnew.begin_access(); CHKERRQ(ierr); 00396 for (PetscInt i = grid.xs; i < grid.xs + grid.xm; ++i) { 00397 for (PetscInt j = grid.ys; j < grid.ys + grid.ym; ++j) { 00398 00399 planeStar<PetscScalar> thk = vH.star(i, j); 00400 00401 // instead of updating surface elevation, counting here floating or icefree neighbors 00402 const PetscScalar hgrounded = vbed(i, j) + thk.ij, 00403 hfloating = sea_level + C * thk.ij; 00404 00405 bool all_4neighbors_icefree = (thk.e == 0.0 && thk.w == 0.0 && 00406 thk.n == 0.0 && thk.s == 0.0); 00407 00408 if (thk.ij > 0.0 && hgrounded < hfloating && all_4neighbors_icefree) { 00409 my_discharge_flux -= vHnew(i, j); 00410 vHnew(i, j) = 0.0; 00411 vh(i, j) = 0.0; 00412 vMask(i, j) = MASK_ICE_FREE_OCEAN; 00413 if (vpik) { 00414 PetscSynchronizedPrintf(grid.com, 00415 "PISM-PIK INFO: [rank %d] killed isolated one-box-iceberg at i=%d, j=%d\n", 00416 grid.rank, i, j); 00417 } 00418 } 00419 } 00420 } 00421 00422 ierr = vH.end_access(); CHKERRQ(ierr); 00423 ierr = vHnew.end_access(); CHKERRQ(ierr); 00424 00425 ierr = vHnew.beginGhostComm(vH); CHKERRQ(ierr); 00426 ierr = vHnew.endGhostComm(vH); CHKERRQ(ierr); 00427 00428 ierr = vH.copy_to(vHnew); CHKERRQ(ierr); 00429 00430 // looking for one-grid-cell partially filled grid cells, that have 4 neighbors of thickness H=0 00431 ierr = vH.begin_access(); CHKERRQ(ierr); 00432 ierr = vHnew.begin_access(); CHKERRQ(ierr); 00433 ierr = vHref.begin_access(); CHKERRQ(ierr); 00434 for (PetscInt i = grid.xs; i < grid.xs + grid.xm; ++i) { 00435 for (PetscInt j = grid.ys; j < grid.ys + grid.ym; ++j) { 00436 00437 // instead of updating surface elevation, counting here floating or icefree neighbors 00438 bool all_4neighbors_icefree = (vH(i + 1, j) == 0.0 && 00439 vH(i - 1, j) == 0.0 && 00440 vH(i, j + 1) == 0.0 && 00441 vH(i, j - 1) == 0.0); 00442 if (vHref(i, j) > 0.0 && all_4neighbors_icefree) { 00443 my_discharge_flux -= vHref(i, j); 00444 vHref(i, j) = 0.0; 00445 if (vpik) { 00446 PetscSynchronizedPrintf(grid.com, 00447 "PISM-PIK INFO: [rank %d] killed lonely partially filled grid cell at i = %d, j = %d\n", 00448 grid.rank, i, j); 00449 } 00450 } 00451 } 00452 } 00453 ierr = vbed.end_access(); CHKERRQ(ierr); 00454 ierr = vMask.end_access(); CHKERRQ(ierr); 00455 ierr = vh.end_access(); CHKERRQ(ierr); 00456 ierr = vHref.end_access(); CHKERRQ(ierr); 00457 ierr = vH.end_access(); CHKERRQ(ierr); 00458 ierr = vHnew.end_access(); CHKERRQ(ierr); 00459 00460 ierr = PISMGlobalSum(&my_discharge_flux, &discharge_flux, grid.com); CHKERRQ(ierr); 00461 PetscScalar factor = config.get("ice_density") * (dx * dy); 00462 cumulative_discharge_flux += discharge_flux * factor; 00463 00464 if (vpik) // actually get output from PetscSynchronizedPrintf() 00465 PetscSynchronizedFlush(grid.com); 00466 00467 ierr = vHnew.beginGhostComm(vH); CHKERRQ(ierr); 00468 ierr = vHnew.endGhostComm(vH); CHKERRQ(ierr); 00469 00470 ierr = vMask.beginGhostComm(); CHKERRQ(ierr); 00471 ierr = vMask.endGhostComm(); CHKERRQ(ierr); 00472 00473 ierr = vh.beginGhostComm(); CHKERRQ(ierr); 00474 ierr = vh.endGhostComm(); CHKERRQ(ierr); 00475 00476 ierr = vHref.beginGhostComm(); CHKERRQ(ierr); 00477 ierr = vHref.endGhostComm(); CHKERRQ(ierr); 00478 00479 return 0; 00480 } 00481
1.7.5.1