-
Notifications
You must be signed in to change notification settings - Fork 63
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
Fortran bmi grid #508
Fortran bmi grid #508
Conversation
9f4f76b
to
64ae376
Compare
9f24c9b
to
52229a6
Compare
if( bmi_status .ne. BMI_SUCCESS ) return | ||
bmi_status = bmi_box%ptr%get_var_itemsize(f_str, item_size) | ||
if( bmi_status .ne. BMI_SUCCESS ) return | ||
if( item_size .eq. 0 ) then |
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.
Per discussion, I think we should actually not allow this (and related updates in this commit), and rather fail if get_var_itemsize
is reporting zero... but yes this does seem to be the source of the FPE.
@@ -686,6 +718,30 @@ function test_var_itemsize(this, name, size) result (bmi_status) | |||
!TODO think of a better way to do this | |||
!Use 'sizeof' in gcc & ifort | |||
select case(name) | |||
case("grid_1_shape") |
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 needs fixed!!! sizeof
will give you the number of bytes of a scalar, but when called on an array, it gives the number of bytes of the the entire array...
Pretty sure this will pass the remaining two tests after merge... will rollback if somehow not. |
Add gridded input and output variables to the fortran BMI test model. Unit tests covering at least two different 3D indexing orderings are included, and the following helps illustrate how gridded data is flattened and reconstructed across the Fortran/C BMI interface.
Multi Dimension Data between Fortran and C/C++ interfaces
In Fortran, the
reshape
intrinsic function can be used to "flatten" the array using the native indexing of the fortran grid.For example, the following Fortran snippet will create a column major flattened array that can move across the BMI interface and be reconstructed by the framework. This creates a 2-Z dimension, 2-Y dimension, and 3-X dimension array, and then
reshapes it to a flattened array using the default (natural) order of the original array
(z,y,x)
.In the example below, this
flattened_data
would look like[ 11, 101, 14, 104, 12, 102, 15, 105, 13, 103, 16, 106 ]
.Pitfalls to be aware of in Fortran BMI
Beware that using the
size
intrinsic in certain BMI interface functions is problematic, since the some functions usesize
as a dummy variable, the dummy variable shadows the intrinsic name andsize
will refer to that variable in the scope of the function.This can present as a puzzling bug when first encounted. Consider the following implementation of a simple loop for grid size
This produces compiler errors that confusing without this intrinsic aliasing context
There are some workarounds using
block ... end block
that might get around this in certain scenarios. For the grid size function above, it can be written asBut there are other cases where it isn't as straight forward. For example, if one needs to get the
shape
of a dummy variable namedshape
, then one must copy the dummy variable first, then apply the block trick, e.g.As of this writing,
size
,shape
, andrank
are all identified as victims of this shadowing in BMI 2.0.Data Description
The test model applies this 2D grid to the 3D grid, with +10 in the Z0 dimension
and + 100 in the Z1 dimension, so the resulting grid should look like
Row Major Flattening given different indexing strategies
A row-major flattening of this looks like (last index changes fastest):
assuming the index is
(z,y,x)
:assuming the index is
(z,x,y)
:assuming the index is
(y,x,z)
:assuming the index is
(y,z,x)
:assuming the index is
(x,y,z)
:assuming the index is
(x,z,y)
:Column Major Flattening given different indexing strategies
A column-major flattening of this looks like (first index changes fastest):
assuming the index is
(z,y,x)
:assuming the index is
(z,x,y)
:assuming the index is
(y,x,z)
:assuming the index is
(y,z,x)
:assuming the index is
(x,y,z)
:assuming the index is
(x,z,y)
:Applying to flattened data
Row Major 3D indexing
Indexing the returned array in 3 dimensions using row-major conventions appropriately would be (assuming
y,x,z
indexing)data[i][j][k] = flattened_data[ depth*(j+cols*i) + k ]
where depth is the size of the 3rd dimension (z) and cols is the size of the second second dimension (x) and
i = row iterator (first dimension)
j = column iterator (second dimension)
k = depth iterator (thrid dimension)
For example, using the grid described above, extracting the linear data into a
y,x,z
3D array would look like thisdata[i][j][k] = flattened_data[ 2*(j+3*i) + k ]
which implemented in loops looks like
Column Major 3D indexing
Indexing with column major conventions would look like (assuming
y,x,z
indexing)data[i][j][k] = flattened_data[ rows*cols*k + rows*j + i ]
where rows is the size of the first dimension, and the rest of the of the variables are as before.
Using our example grid, this looks the following
data[i][j][k] = flattened_data[ 2*3*k + 2*j + i ]
which implemented in loops looks like
Additions
Removals
Changes
Testing
Todos
Checklist
Target Environment support