package BoxTools;
import java.lang.Math;
/**
* A BoxLayout
object contains a set of boxes(RectDomains) along with their processor/
* process assignments. Each box in a BoxLayout
has a processor/process number assigned
* to it, and each processor/process may be assigned to multiple boxes. These boxes may not be
* disjointed. A BoxLayout
object serves as the metadata of a distributed data structure
* defined on the boxes this BoxLayout
object contains and their processor assignments.
* The default constructor constructs an open BoxLayout
. Boxes may be added/deleted to an
* open BoxLayout
. But when a BoxLayout
is closed, no change is allowed.
* Before a BoxLayout
being closed, boxes and their processor/process assignments are
* stored in linked lists, so that users can add or delete them easily. When a BoxLayout
* is closed, information stored in lists is copied to arrays for better performance. Users can use
* the methods coarsen
, refine
, and highBoundary
as well as
* lowBoundary
to generate a new BoxLayout
object. The Layout information
* in BoxLayout
is single, and all the data in BoxLayout
is local. We do not
* use "single" keyword everywhere to prevent propagating effect of this qualifier.
*
Usage: a BoxLayout
object must be declared local.
* @see List, LayoutIndex
* @see Chombo Specification
* @version 1.1
* Modified on Feb 24. Add m_neighbors.
* //Modified on Aug 09, 2004. Add m_iterator.
* @author Tong Wen, LBNL
* @since 1.0
*/
public class BoxLayout {
//static SharedRegion REGION=new SharedRegion();
//PrivateRegion REGION=new PrivateRegion();
private static final int SPACE_DIM =Util.SPACE_DIM;
private static final int SORT_DIM =Util.SORT_DIM;
private static int m_counts=0;
private final int m_layoutID;
protected String local m_layoutName;
/**The i
th element in m_procAssignments
is the processor/process number
* assigned to the i
th box. The size of this array is the number of all the boxes.
*/
template List local temp_procAssignments;
protected int [1d] local m_procAssignments;
/**If the i
th box is the j
th one assigned to its processor/process, then
* the i
th element in m_localIndexes
is equal to j
.
*/
template List local temp_localIndexes;
protected int [1d] local m_localIndexes;
/**m_boxes
stores all the boxes. */
template List > local temp_boxes;
protected RectDomain [1d] local m_boxes;
/**m_boxAssignments[i]
stores the indexes of all the boxes assigned to the
* i
th processor/process. */
template List local [] local temp_boxAssignments;
protected int [1d] local [1d] local m_boxAssignments;
protected int single m_numOfBoxes;
protected final int single m_numOfProcs;
/**If BoxLayoutA
is a copy of or generated from BoxLayoutB
, then
* BoxLayoutA.m_root
is set to BoxLayoutB.m_root
. Otherwise, it is set to
* this
.
*/
private BoxLayout local m_root;
//private LayoutIterator local m_iterator;
/**If this BoxLayout is closed, then m_closed
is set to ture
. */
protected boolean single m_closed=false;
/**If the boxes are disjointed, then m_disjointed
is set to ture
. */
protected boolean single m_disjointed=false;
protected int [] local [] local m_neighbors;
/**If findNeighbors() are called, then m_neighborsFound
is set to ture
. */
protected boolean m_neighborsFound=false;
protected boolean single m_tempUsed=false;
SharedRegion single m_region;
protected boolean single m_sorted=false;
protected DataIndex local [] local m_indexes;
/** The simple O(n^2)
sorting algorithm. */
public final local void sort(RectDomain single [] single a_Boxes, int single [] single a_procIDs){
m_sorted=Util.sort(a_Boxes,a_procIDs,SORT_DIM);
}
/** To check if boxes in a_Boxes are disjointed. */
final boolean single isDisjointed(RectDomain single [] single a_Boxes, boolean single sorted){
int single n=a_Boxes.length-1;
int single i,j,k;
boolean single disjointed=true;
checking:
for (i=0; i single [] single boxes=new RectDomain single [m_numOfBoxes];
for (int single i=0;i single)m_boxes[i];
if (!m_sorted) Util.sort(boxes, SORT_DIM);
m_disjointed=isDisjointed(boxes, true);
}
else{
Util.printErrMsg("BoxLayout::checkIfDisjointed: Layout must be closed!");
}
}
private final local void generateDataIndexes(){
if (m_closed){
//m_indexes=new(REGION) DataIndex local [m_numOfBoxes] local;
m_indexes=new DataIndex local [m_numOfBoxes] local;
DataIndex local DI;
for(int i=0;i=0 && i=0) && (a_li.m_index=0 && i getBox(LayoutIndex local a_index){
if (checkLayoutIndex(a_index) && m_closed)
return m_boxes[a_index.m_index];
else
return Util.NULL_BOX;
}
public final inline local RectDomain op[](LayoutIndex local a_index){
if (checkLayoutIndex(a_index) && m_closed)
return m_boxes[a_index.m_index];
else
return Util.NULL_BOX;
}
public BoxLayout(){
m_counts++;
m_layoutID=m_counts;
m_layoutName="BoxLayout"+m_layoutID;
m_root=this;
m_numOfProcs=Ti.numProcs();
}
public BoxLayout(RectDomain single [] single a_Boxes, int single [] single a_procIDs){
this();
//m_sorted=Util.sort(a_Boxes,a_procIDs,SORT_DIM);
define(a_Boxes,a_procIDs, true);
m_disjointed=isDisjointed(a_Boxes, m_sorted);
findNeighbors(1);
//m_iterator=new LayoutIterator(this);
}
/**a_Boxes
is an array of boxes and a_procIDs
is the array of corresponding processor/process
* assignments. The layout information is single because a_Boxes
and a_procIDs
are single.
*/
public final local void define(RectDomain single [] single a_Boxes, int single [] single a_procIDs, boolean single sortFirst){
if (m_closed) {
Util.printErrMsg("BoxLayout::define( , ): this layout has already been closed!");
return;
}
else{
if (a_Boxes.length != a_procIDs.length){
Util.printErrMsg("BoxLayout::define( , ): the sizes of the two input arrarys must be equal!");
return;
}
else{
if (sortFirst) m_sorted=Util.sort(a_Boxes,a_procIDs,SORT_DIM);
m_numOfBoxes=a_Boxes.length;
m_procAssignments=new int [[0:m_numOfBoxes-1]];
m_localIndexes=new int [[0:m_numOfBoxes-1]];
m_boxes =new RectDomain [[0:m_numOfBoxes-1]];
m_boxAssignments=new int [[0:m_numOfProcs-1]] local [1d] local;
PrivateRegion local region=new PrivateRegion();
template List local [] local temp_boxAssignments=new (region) template List local [m_numOfProcs];
for (int i=0;i();
int single i, procID;
for (i=0;i single [] single a_Boxes, int single [] single a_procIDs, boolean single sortFirst){
if (m_closed) {
Util.printErrMsg("BoxLayout::initialize( , ): this layout has already been closed!");
return;
}
else{
if (a_Boxes.length != a_procIDs.length){
Util.printErrMsg("BoxLayout::initialize( , ): the sizes of the two input arrarys must be equal!");
return;
}
else{
if (sortFirst) m_sorted=Util.sort(a_Boxes,a_procIDs,SORT_DIM);
m_region=new SharedRegion();
temp_procAssignments=new (m_region) template List();
temp_localIndexes=new (m_region) template List();
temp_boxes =new (m_region) template List >();
temp_boxAssignments=new (m_region) template List local [m_numOfProcs];
for (int i=0;i();
int single i, procID;
for (i=0;i box_i;
for (i=0;i local [] local temp_neighbors=new (region) template List local [m_numOfBoxes] local;
for (i=0;i();
RectDomain box;
for (i=0;i [] local getNeighbors(LayoutIndex a_index){
RectDomain [] local result;
if (!m_closed) {
Util.printErrMsg("BoxLayout::getNeighbors(): layout must be closed!");
return null;
}
else{
if (!m_neighborsFound) findNeighbors();
int index=a_index.m_index;
int size=m_neighbors[index].length;
//int size=m_neighbors[m_localIndexes[index]].length;
result=new RectDomain [size];
for (int i=0;i a_box){ return m_boxes.indexOf(a_box);}
public final inline local int numBoxesAt(int a_procID){
if (checkProcIndex(a_procID))
if (m_closed)
return m_boxAssignments[a_procID].domain().size();
else
return temp_boxAssignments[a_procID].size();
else{
return 0;
}
}
final local int [] boxesAt(int a_procID){
//if (checkProcIndex(a_procID)){
int size= m_boxAssignments[a_procID].domain().size();
//Util.printErrMsg("size: "+size);
int[] temp=new int[size];
for (int i=0;i [[0:m_numOfBoxes-1]];
//for (i=0;i0) new_BL.m_boxAssignments[i].copy(m_boxAssignments[i]);
}
new_BL.m_closed=true;
new_BL.m_indexes=m_indexes;
new_BL.m_sorted=m_sorted;
//new_BL.m_iterator=new LayoutIterator(new_BL);
return new_BL;
}
else{
Util.printErrMsg("BoxLayout::copy(): this layout is not closed!");
return null;
}
}
/**A deep copy is generated but with the boxes refined by a factor a_factor
. */
public final local BoxLayout single local refine(int single a_factor){
BoxLayout local single newLayout=this.copy();
RectDomain box;
Point lwb,upb;
//Point temp;
final Point STRIDE,stride;
int i,j,k;
if (m_numOfBoxes>0) {STRIDE=newLayout.m_boxes[0].stride();stride=STRIDE*a_factor;}
for (i=0;i.all(1);
lwb=lwb*stride;
//upb=lwb+temp*stride-Point.all(1);
upb=(upb+STRIDE)*stride-STRIDE;
newLayout.m_boxes[i]=[lwb:upb:STRIDE];
}
if (m_neighborsFound){
newLayout.m_neighbors=new int [m_numOfBoxes] local [] local;
for (i=0;ia_factor. */
public final local BoxLayout local single coarsen(int single a_factor){
BoxLayout local single newLayout=this.copy();
RectDomain box;
Point lwb,upb;
//Point temp;
final Point STRIDE,stride;
int i,j,k;
if (m_numOfBoxes>0){STRIDE=newLayout.m_boxes[0].stride();stride=STRIDE*a_factor;}
for (i=0;i STRIDE;
if (m_numOfBoxes>0) STRIDE=newLayout.m_boxes[0].stride();
for (int i=0;ia_direction of length a_length
.
*/
public final local BoxLayout local single highBoundary(int single a_direction, int single a_length, boolean single a_expendBy1){
int single d=java.lang.Math.abs(a_direction);
if (d>0 && d<=SPACE_DIM){
BoxLayout local single newLayout=this.copy();
RectDomain box;
Point lwb,upb,stride;
for (int i=0;i.direction(d, upb[d]-lwb[d]+1);
upb=upb+Point.direction(d, java.lang.Math.abs(a_length));
if (a_expendBy1)
for (int j=1;j<=SPACE_DIM;j++)
if (j!=d){
lwb=lwb-Point.direction(j,1);
upb=upb+Point.direction(j,1);
}
newLayout.m_boxes[i]=[lwb:upb:stride];
}
newLayout.m_layoutName="high boundary of "+m_layoutName;
//newLayout.m_iterator=new LayoutIterator(newLayout);
return newLayout;
}
else{
Util.printErrMsg("BoxLayout::highBoundary( , ): direction is out of range!");
return null;
}
}
/**A deep copy is generated but with each box replaced by the box adjacent to its lower corner
* in the direction a_direction
of length a_length
.
*/
public final local BoxLayout local single lowBoundary(int single a_direction, int single a_length, boolean single a_expendBy1){
int single d=java.lang.Math.abs(a_direction);
if (d>0 && d<=SPACE_DIM){
BoxLayout local single newLayout=this.copy();
RectDomain box;
Point lwb,upb,stride;
for (int i=0;i.direction(d,upb[d]-lwb[d]+1);
lwb=lwb-Point.direction(d, java.lang.Math.abs(a_length));
if (a_expendBy1)
for (int j=1;j<=SPACE_DIM;j++)
if (j!=d){
lwb=lwb-Point.direction(j,1);
upb=upb+Point.direction(j,1);
}
newLayout.m_boxes[i]=[lwb:upb:stride];
}
newLayout.m_layoutName="low boundary of "+m_layoutName;
//newLayout.m_iterator=new LayoutIterator(newLayout);
return newLayout;
}
else{
Util.printErrMsg("BoxLayout::lowBoundary( , ): direction is out of range!");
return null;
}
}
/**this method is used for debugging. */
public local void myprint(){
int i,j;
if (Ti.thisProc()==0)
if (!m_closed) {
j=temp_boxes.size();
System.out.println("temp_boxes.size(): "+j);
for (i=0;i