-
Notifications
You must be signed in to change notification settings - Fork 149
Update outer boundary implementation to support open boundary conditions #1062
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
- Refactor HaloUpdate in ice_boundary in serial and mpi
- Add ewBoundaryType and nsBoundaryType to halo datatype
- Zero out outer boundary during HaloUpdate only under certain conditions
including cyclic or tripole bcs or if a fillValue is explicitly passed
- Update the i_glob and j_glob indexing for 'open' boundary conditions (in development)
- Add a few fillvalue=c0 arguments to HaloUpdate calls during initialization
- Explicitly zero out all allocated variables at initialization
- Add support for kmt_type = none with in subroutine rectgrid for rectangular grids
- Explicitly Zero out restart fields before reading to be extra careful
- Refactor halochk unit test, add explicit fill tests
closed, and tripole (south) boundaries, now extrapolate index values on the outer boundary. These boundary indices were "reflected" in some cases to generate valid indices but an invalid implementation. The use of 0 as a special value for the global index is also deprecated. There were lots of hidden features that had to be corrected. - Refactor the scatter routines to simplify and remove hidden features that scatter valid data to boundaries that should not have any data. Rename iglb/jglb to isrc/jsrc consistent in scatter_global_ext to be consistent with other scatter methods. - Add several HaloExtrapolate calls to initialize boundary values for grid fields. This replaces those fields being set by the global indices (incorrectly) and the scatter. - Replace the G_HTN and G_HTE initialization with a call to gather_global_ext on HTN and HTE respectively. - Update ice_HaloExtrapolate to support more than 1 ghost cell - Zero out some arrays in the evp1d - Check for valid boundary_types in ice_domain.F90 - Some code cleanup in init_domain_distribution and init_grid2
if someone passed in restart_ext=.false., nothing would happen. The update also allows some extra restart_ext logic in io_netcdf/ice_restart.F90 to be cleaned up. Clean up refactor, remove dead code.
|
This is a significant amount of work and the code looks sensible. I'm confused though why everything should be bfb? Are we just not doing the right tests to capture this behavior? |
| character(len=*), parameter :: subname = '(gather_static)' | ||
|
|
||
| G_uarear = c0 | ||
| G_dyT = c0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is necessary because the G_ARRAY of gather_global_ext is intent(inout).
Are there places where it is intent in?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may not be necessary in practice if we can be sure that the gather_global_ext sets all gridcells in the G_ arrays. But the cost of zeroing the arrays at initialization is also very small and probably reasonable to do. The hope is that zeroing these arrays makes the implementation more robust. Given we have a small technical issue in the evp1d implementation where some compilers trap a floating point error, this seems like a sensible thing to do for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A slightly bigger worry is resetting all the G_ arrays to zero in convert_1d_2d_dyn below which happens each timestep. Again, it may improve robustness in the short term. But at some point, we may decide it's unnecessary and want to remove that code again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Many of these conversions are not really needed or only needed for history output which should be done smarter than it currently is (only convert when needed).
It's bfb because open boundary conditions don't work except when there is land or no ice on the boundary. And all of our tests with open boundary conditions meet that criteria (global grids at j=1, box grids, etc). So, open boundary conditions weren't working and we weren't testing them. But now we need them to work. As we create cases with sea ice on an open boundary, we will probably have more debugging to do. This initial goal was just to refactor stuff to get ready for open boundary conditions and check whether answers changed. I hope to start work on another PR that would implement zero-gradient, constant-gradient, or other "technical" boundary conditions on open boundaries and create box test cases for them. That could be done concurrently with the open boundary condition work where specified fluxes/states are imposed on the boundary based on model/observations. The open boundary conditions create a lot of complexity though in terms of when and how to impose them in the timestepping. |
|
I have looked through and the changes seems reasonably. The changes I have noted In addition some semantics has been changed. With regards to the 1d evp solver I will take a look at it along with the conversions of 1d to 2d data and vice versa. I should probably take a look at the halo updates of 1dEVP as well now that they have changed. |
| integer (kind=int_kind) :: lnrec ! local value of nrec | ||
|
|
||
| lnrec = nrec | ||
| logical (kind=log_kind) :: lrestart_ext ! local value of reatart_ext |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| logical (kind=log_kind) :: lrestart_ext ! local value of reatart_ext | |
| logical (kind=log_kind) :: lrestart_ext ! local value of restart_ext |
PR checklist
Update outer boundary implementation to support open boundary conditions
apcraig
All tests are bit-for-bit except the halochk unittest which was refactored and passes. There is an issue in the evp1d implementation where on some compilers when the debug flag is on, the code will trap on a floating point error. See more details below. https://github.com/CICE-Consortium/Test-Results/wiki/cice_by_hash_forks#85e4ed8a966197ba8479928cbd93ba8e0597df1a, https://github.com/CICE-Consortium/Test-Results/wiki/cice_by_hash_forks#a8862c3bc36f31d3f5fa07d180f45e3a8e8979b6
Refactor CICE to support open boundary conditions where values may be imposed on the outer boundary. Prior to this update, the HaloUpdate was zeroing out the halo before updating the halo. This meant any values set on the halo were lost anytime a HaloUpdate was executed. Several other issues upstream and downstream were found as this was implemented. In particular, the global index set on the outer boundary for open and closed boundary conditions was "special", a zero global index was used internally as a flag, and both the scatter_global and haloUpdate was covering up some issues with uninitialized data.
Update the i_glob and j_glob indexing for open and closed boundary conditions on the outer boundary. For open, closed, and tripole (south) boundaries, now extrapolate index values on the outer boundary. This might mean indices are less than 0 or greater than n[x,y]_global+2*nghost. In the original implementation, these outer boundary indices were either set to some internal values so they would be set with the scatter_global method or to zero which was treated as a special value. The zero special value feature has been removed and the scatter_global implementation has been refactored to fill all gridpoints with valid global indices and leave others unset. The only special case remaining in the global indexing is for tripole grids on the north boundary where the j global index is set to a negative value.
Additional Features
All tests are bit-for-bit except the halochk unittest which was refactored and passes. There is an issue in the evp1d implementation where on some compilers when the debug flag is on, the code will trap on a floating point error. If the floating point error isn't trapped, the cases run to completion and are bit-for-bit with the current trunk. This suggests there is something like a 0/0 calculation being trapped in the evp1d which has no impact on the solution, is only caught by a subset of compilers, and probably requires an if test to avoid. I spent some time trying to track down the error without any success.