say wall(nwall1, nwall2), will be divided up into
an array of overlapping windows
each window of size (nwind1,nwind2).
To choose the number of windows, you specify (npatch1,npatch2).
Overlap on the 2-axis is measured by the fraction
(nwind2*npatch2)/nwall2.
We turn to the language of F90 which allows us to discuss
N-dimensional hypercubes almost as easily as two-dimensional spaces.
We define an N-dimensional volume (like the wall) with the vector
nwall= (nwall1, nwall2, ...).
We define subvolume size (like a 2-D window) with the vector
nwind=(nwind1, nwind2, ...).
The number of subvolumes on each axis is
npatch=(npatch1, npatch2, ...).
The operator
patch
simply grabs one patch from the wall,
or when used in adjoint form, it puts the patch back on the wall.
The number of patches on the wall is
product(npatch).
Getting and putting all the patches is shown later in module
patching
.
The i-th patch is denoted by the scalar counter ipatch.
Typical patch extraction begins by taking
ipatch, a fortran linear index,
and converting it to a multidimensional subscript jj
each component of which is less than npatch.
The patches cover all edges and corners of the given data plane
(actually the hypervolume)
even where
nwall/npatch is not an integer,
even for axes whose length is not an integer number of the patch length.
Where there are noninteger ratios,
the spacing of patches is slightly uneven,
but we'll see later that
it is easy to reassemble seamlessly the full plane from the patches,
so the unevenness does not matter.
You might wish to review the utilities
line2cart and
cart2line
which convert between multidimensional array subscripts
and the linear memory subscript
before looking at the patch extraction-putback code:
#$=head1 NAME
#$
#$patch - extract and putback patches
#$
#$=head1 SYNOPSIS
#$
#$C<call patch_init(npatch,nwall,nwind)>
#$
#$C<ierr=ptch_lop(adj,add,wall,wind)>
#$
#$=head1 PARAMETERS
#$
#$=over 4
#$
#$=item npatches - C<integer(:)>
#$
#$ number of patches
#$
#$=item nwall - C<integer(:)>
#$
#$=item nwind - C<integer(:)>
#$
#$=item adj,add,wall,wind -
#$
#$ Standard operator interface
#$
#$=back
#$
#$=head1 DESCRIPTION
#$
#$Extract and put back patches
#$
#$=head1 SEE ALSO
#$
#$L<misinput>
#$
#$=head1 LIBRARY
#$
#$B<geef90>
#$
#$=cut
module patch { # N-dimensional patch extract and putback
use cartesian
integer, private :: ipatch # count till product(npatch)
integer, dimension (:), pointer :: npatch, nwind, nwall
# overlap where npatch * nwind > nwall
#% _init( npatch, nwall, nwind)
ipatch = 1
#% _lop ( wall, wind)
integer, dimension( size( npatch)) :: ii, jj # Ndim=size(npatch)
integer :: i, j, shift
call line2cart( npatch, ipatch, jj ) # (j1,j2) = (1,1) to (npatch1,npatch2)
# round jj to shift end of last patch flush against the far wall.
where( npatch==1) { jj = 1 }
elsewhere { jj = 1.5 +( nwall - nwind)*( jj - 1.)/( npatch - 1.)}
call cart2line( nwall, jj, shift) # jj is where the patch begins.
shift -= 1 #
do i = 1, size( wind) { # sweep through a window
call line2cart( nwind, i, ii) # ii(i) is (i1,i2) in window
call cart2line( nwall, ii, j) # j(ii) linear subscript in window
if( adj)
wall( j + shift) += wind( i)
else
wind( i) += wall( j + shift)
}
#% _close
ipatch = ipatch + 1
}
The cartesian vector jj points to the beginning of a patch, where on the wall the (1,1,..) coordinate of the patch lies. Obviously this begins at the beginning edge of the wall. Then we pick jj so that the last patch on any axis has its last point exactly abutting the end of the axis. The formula for doing this would divide by zero for a wall with only one patch on it. This case arises legitimately where an axis has length one. Thus we handle the case npatch=1 by abutting the patch to the beginning of the wall and forgetting about its end. As in any code mixing integers with floats, to guard against having a floating-point number, say 99.9999, rounding down to 99 instead of up to 100, the rule is to always add .5 to a floating point number the moment before converting it to an integer. Now we are ready to sweep a window to or from the wall. The number of points in a window is size(wind) or equivalently product(nwind).
Figure 2 shows an example with five nonoverlapping patches on the 1-axis and many overlapping patches on the 2-axis.
|
parcel90
Figure 2 A plane of identical values after patches have been cut and then added back. Results are shown for nwall=(100,30), nwind=(17,6), npatch=(5,11). For these parameters, there is gapping on the horizontal axis and overlap on the depth axis. | ![]() |