Setting the distribution type to sectrobin crashes with an integer-divide-by-zero error for a ESM 1.6 PiControl (i.e., access driver)
CICE (cice_init) 1 jobnum = 3
CICE (cice_init) 1 init_date = 10101
CICE (cice_init) 1 runtime = 31622400
CICE (cice_init) 1 idate = 0 0
forrtl: severe (71): integer divide by zero
Image PC Routine Line Source
libpthread-2.28.s 000014F6AFB65990 Unknown Unknown Unknown
cice_access-esm1. 000000000048C337 init_cpl 318 cpl_interface.F90
cice_access-esm1. 0000000000413531 cice_init 131 CICE_InitMod.F90
cice_access-esm1. 0000000000412D40 icemodel 51 CICE.F90
The relevant code is here
l_ilo=mod(my_task,nprocsX)*nx_global/nprocsX+1
l_ihi=l_ilo + nx_global/nprocsX -1
l_jlo=int(my_task/nprocsX) * ny_global/nprocsY+1
l_jhi=l_jlo+ny_global/nprocsY - 1
@anton-seaice showed that nprocsX, nprocsY are set to public but only ever set in the Cartesian distribution types. Hence, those public vars retain the default zero and get this divide-by-zero at runtime for all non-Cartesian distribution types. I have also confirmed that the same crash exists with the released config, by running an experiment with only the distribution type changed sectrobin and getting an identical crash.
Claude suggested the following patch for the access driver:
From 99db6f0502394461f9599ea3236c3fc639d01a44 Mon Sep 17 00:00:00 2001
From: Claude <noreply@anthropic.com>
Date: Wed, 19 Aug 2026 03:39:37 +0000
Subject: [PATCH] Fix divide-by-zero in the ESM coupler for non-cartesian
distributions
init_cpl derived its OASIS BOX partition from ice_distribution's public
nprocsX/nprocsY. Those are only ever assigned by create_distrb_cart, so
with distribution_type = 'sectrobin', 'roundrobin', 'sectcart' or
'spacecurve' they were still zero and the model died with an integer
divide by zero at startup. Only 'cartesian' (and 'rake', which builds on
it) happened to work.
The loop immediately above already computes the task's global index range
from the block distribution, and init_cpl requires max_blocks == 1, so
that range is exactly the rectangle this task owns for every distribution
type. Use it, and drop the overwrite. It is also more correct where the
two disagree: the old formula assumed the domain divided evenly by the
processor grid.
nprocsX/nprocsY were made public solely for this call site, so they go
back to being local to create_distrb_cart.
Pre-existing bug; not introduced by the run-time domain sizing series.
---
drivers/access/cpl_interface.F90 | 21 ++++++++++++++-------
source/ice_distribution.F90 | 16 ++++++++--------
2 files changed, 22 insertions(+), 15 deletions(-)
diff --git a/drivers/access/cpl_interface.F90 b/drivers/access/cpl_interface.F90
index 0308db7..a978a42 100644
--- a/drivers/access/cpl_interface.F90
+++ b/drivers/access/cpl_interface.F90
@@ -14,7 +14,7 @@
use ice_broadcast
use ice_blocks !, only : nx_block, ny_block, nghost
use ice_domain_size !, only : max_blocks, nx_global, ny_global, ncat
- use ice_distribution, only : distrb, nprocsX, nprocsY
+ use ice_distribution, only : distrb
use ice_gather_scatter
use ice_constants
use ice_boundary, only : ice_HaloUpdate
@@ -312,12 +312,19 @@
!print ghost info
! write(il_out,*) ' ghost global:',gh_ilo, gh_ihi, gh_jlo, gh_jhi
-!calculate partition using nprocsX and nprocsX
- l_ilo=mod(my_task,nprocsX)*nx_global/nprocsX+1
- l_ihi=l_ilo + nx_global/nprocsX -1
- l_jlo=int(my_task/nprocsX) * ny_global/nprocsY+1
- l_jhi=l_jlo+ny_global/nprocsY - 1
-
+! The OASIS partition is the rectangle this task actually owns, as derived
+! from the block distribution in the loop above. It used to be recomputed
+! here from ice_distribution's nprocsX/nprocsY, but those are only ever set
+! by create_distrb_cart, so with distribution_type = 'sectrobin', 'roundrobin',
+! 'sectcart' or 'spacecurve' they were still zero and this divided by zero.
+! The distribution-derived bounds are correct for every distribution type, and
+! this driver already requires max_blocks == 1, so the region is a rectangle.
+ if (l_ihi < l_ilo .or. l_jhi < l_jlo) then
+ call abort_ice('(init_cpl): this processor owns no ice blocks; the '// &
+ 'ACCESS/ESM coupling requires exactly one block per '// &
+ 'processor, so reduce nprocs or the block size')
+ endif
+
! write(il_out,*) ' 2local partion, ilo, ihi, jlo, jhi=', l_ilo, l_ihi, l_jlo, l_jhi
! write(il_out,*) ' 2partition x,y sizes:', l_ihi-l_ilo+1, l_jhi-l_jlo+1
diff --git a/source/ice_distribution.F90 b/source/ice_distribution.F90
index 0a3a31e..770ee14 100644
--- a/source/ice_distribution.F90
+++ b/source/ice_distribution.F90
@@ -50,12 +50,12 @@
! 'slenderX1' (NPX x 1)
! 'slenderX2' (NPX x 2)
-!ars599: 26032014: will call from cpl_interface
-! from function create_distrb_cart
-! so change to public
- integer (int_kind), public :: &
- nprocsX, &! num of procs in x for global domain
- nprocsY ! num of procs in y for global domain
+! nprocsX/nprocsY used to be module variables, made public (ars599, 26032014)
+! so that drivers/access/cpl_interface.F90 could reuse them. They are only
+! ever assigned by create_distrb_cart, so with any other distribution_type
+! they stayed zero and the driver divided by zero. The driver now derives its
+! OASIS partition from the block distribution itself, so these are local to
+! create_distrb_cart again.
!***********************************************************************
@@ -561,8 +561,8 @@
processor, &! processor position in cartesian decomp
globalID, &! global block ID
localID, &! block location on this processor
-! nprocsX, &! num of procs in x for global domain
-! nprocsY, &! num of procs in y for global domain
+ nprocsX, &! num of procs in x for global domain
+ nprocsY, &! num of procs in y for global domain
numBlocksXPerProc, &! num of blocks per processor in x
numBlocksYPerProc ! num of blocks per processor in y
--
2.43.0
Setting the distribution type to
sectrobincrashes with an integer-divide-by-zero error for a ESM 1.6 PiControl (i.e.,accessdriver)The relevant code is here
@anton-seaice showed that
nprocsX, nprocsYare set to public but only ever set in theCartesiandistribution types. Hence, those public vars retain the default zero and get this divide-by-zero at runtime for all non-Cartesian distribution types. I have also confirmed that the same crash exists with the released config, by running an experiment with only the distribution type changedsectrobinand getting an identical crash.Claude suggested the following patch for the
accessdriver: