//#####################################################################
// Function Initialize_Array_Divisions
//#####################################################################
template <class T> void THREAD_DIVISION_PARAMETERS<T>::
Initialize_Array_Divisions(const int length,const int divisions,ARRAY<VECTOR_2D<int> >& ranges) const
{
    ranges.Resize_Array(divisions);
    for(int i=1; i<=divisions; i++) {
        int quotient=length/divisions,remainder=length%divisions;
        ranges(i)=VECTOR_2D<int>((i-1)*quotient+min(i-1,remainder)+1,i*quotient+min(i,remainder));
    }
}
//#####################################################################
// Function Initialize_Array_Divisions_With_Equal_Extents
//#####################################################################
template <class T> void THREAD_DIVISION_PARAMETERS<T>::
Initialize_Array_Divisions_With_Equal_Extents(const VECTOR_2D<T>& length,const VECTOR_2D<int>& divisions,const VECTOR_2D<int>& overlap,ARRAY<BOX_2D<int> >& ranges) const
{
    ARRAY<VECTOR_2D<int> > x_ranges,y_ranges;
    Initialize_Array_Divisions_With_Equal_Extents(length.x,divisions.x,overlap.x,x_ranges);
    Initialize_Array_Divisions_With_Equal_Extents(length.y,divisions.y,overlap.y,y_ranges);
    ranges.Resize_Array(divisions.x*divisions.y);
    for(int j=1; j<=divisions.y; j++) for(int i=1; i<=divisions.x; i++)
            ranges((j-1)*divisions.x+i)=BOX_2D<int>(x_ranges(i).x,x_ranges(i).y,y_ranges(j).x,y_ranges(j).y);
}
//#####################################################################
// Function Initialize_Array_Divisions_With_Equal_Extents
//#####################################################################
template <class T> void THREAD_DIVISION_PARAMETERS<T>::
Initialize_Array_Divisions_With_Equal_Extents(const int length,const int divisions,const int overlap,ARRAY<VECTOR_2D<int> >& ranges) const
{
    assert((length-2*overlap)%divisions==0); // need specific length to guarantee exact partitioning
    int span=(length-2*overlap)/divisions+2*overlap-1;
    ranges.Resize_Array(divisions);
    for(int i=1; i<=divisions; i++) ranges(i)=VECTOR_2D<int>((i-1)*span-(2*i-3)*overlap+i,i*span-(2*i-1)*overlap+i);
    ranges(1).x=1;
    ranges(divisions).y=length;
}
//#####################################################################
// Function Initialize_Grid_Divisions
//#####################################################################
template <class T> void THREAD_DIVISION_PARAMETERS<T>::
Initialize_Grid_Divisions(const BOX_2D<T>& grid_box,ARRAY<BOX_2D<int> >& ranges) const
{
    assert(grid_divisions_2d.x && grid_divisions_2d.y);
    ranges.Resize_Array(grid_divisions_2d.x*grid_divisions_2d.y);
    int size_x=grid_box.xmax-grid_box.xmin, size_y=grid_box.ymax-grid_box.ymin;
    for(int i=1; i<=grid_divisions_2d.x; i++) {
        int m_quotient=size_x/grid_divisions_2d.x,m_remainder=size_x%grid_divisions_2d.x;
        for(int j=1; j<=grid_divisions_2d.y; j++) {
            int n_quotient=size_y/grid_divisions_2d.y,n_remainder=size_y%grid_divisions_2d.y;
            BOX_2D<int> range(grid_box.xmin+(i-1)*m_quotient+min(i-1,m_remainder)+1,grid_box.xmin+i*m_quotient+min(i,m_remainder),
                              grid_box.ymin+(j-1)*n_quotient+min(j-1,n_remainder)+1,grid_box.ymin+j*n_quotient+min(j,n_remainder));
            ranges((i-1)*grid_divisions_2d.y+j)=range;
        }
    }
}
//#####################################################################
// Function Initialize_Grid_Divisions
//#####################################################################
template <class T> void THREAD_DIVISION_PARAMETERS<T>::
Initialize_Grid_Divisions(const GRID_2D<T>& grid,ARRAY<BOX_2D<int> >& ranges,ARRAY<BOX_2D<int> >* ranges_padded,const int ghost_cells,const int range_overlap) const
{
    assert(grid_divisions_2d.x && grid_divisions_2d.y);
    ranges.Resize_Array(grid_divisions_2d.x*grid_divisions_2d.y);
    if(ranges_padded) ranges_padded->Resize_Array(grid_divisions_2d.x*grid_divisions_2d.y);
    for(int i=1; i<=grid_divisions_2d.x; i++) {
        int m_quotient=grid.m/grid_divisions_2d.x,m_remainder=grid.m%grid_divisions_2d.x;
        for(int j=1; j<=grid_divisions_2d.y; j++) {
            int n_quotient=grid.n/grid_divisions_2d.y,n_remainder=grid.n%grid_divisions_2d.y;
            BOX_2D<int> range((i-1)*m_quotient+min(i-1,m_remainder)+1,i*m_quotient+min(i,m_remainder),
                              (j-1)*n_quotient+min(j-1,n_remainder)+1,j*n_quotient+min(j,n_remainder));
            BOX_2D<int> range_padded(max(range.xmin-range_overlap,1-ghost_cells),min(range.xmax+range_overlap,grid.m+ghost_cells),
                                     max(range.ymin-range_overlap,1-ghost_cells),min(range.ymax+range_overlap,grid.n+ghost_cells));
            ranges((i-1)*grid_divisions_2d.y+j)=range;
            if(ranges_padded) (*ranges_padded)((i-1)*grid_divisions_2d.y+j)=range_padded;
        }
    }
}