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 ith element in m_procAssignments is the processor/process number * assigned to the ith 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 ith box is the jth one assigned to its processor/process, then * the ith 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 * ith 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