Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SourceIMP/utilities/RocfracPrep/NewCommList.f90
Go to the documentation of this file.
1 !*********************************************************************
2 !* Illinois Open Source License *
3 !* *
4 !* University of Illinois/NCSA *
5 !* Open Source License *
6 !* *
7 !* Copyright@2008, University of Illinois. All rights reserved. *
8 !* *
9 !* Developed by: *
10 !* *
11 !* Center for Simulation of Advanced Rockets *
12 !* *
13 !* University of Illinois *
14 !* *
15 !* www.csar.uiuc.edu *
16 !* *
17 !* Permission is hereby granted, free of charge, to any person *
18 !* obtaining a copy of this software and associated documentation *
19 !* files (the "Software"), to deal with the Software without *
20 !* restriction, including without limitation the rights to use, *
21 !* copy, modify, merge, publish, distribute, sublicense, and/or *
22 !* sell copies of the Software, and to permit persons to whom the *
23 !* Software is furnished to do so, subject to the following *
24 !* conditions: *
25 !* *
26 !* *
27 !* @ Redistributions of source code must retain the above copyright *
28 !* notice, this list of conditions and the following disclaimers. *
29 !* *
30 !* @ Redistributions in binary form must reproduce the above *
31 !* copyright notice, this list of conditions and the following *
32 !* disclaimers in the documentation and/or other materials *
33 !* provided with the distribution. *
34 !* *
35 !* @ Neither the names of the Center for Simulation of Advanced *
36 !* Rockets, the University of Illinois, nor the names of its *
37 !* contributors may be used to endorse or promote products derived *
38 !* from this Software without specific prior written permission. *
39 !* *
40 !* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
41 !* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES *
42 !* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND *
43 !* NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR *
44 !* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
45 !* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
46 !* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
47 !* USE OR OTHER DEALINGS WITH THE SOFTWARE. *
48 !*********************************************************************
49 !* Please acknowledge The University of Illinois Center for *
50 !* Simulation of Advanced Rockets in works and publications *
51 !* resulting from this software or its derivatives. *
52 !*********************************************************************
53 SUBROUTINE newcommlist(NumEl, NumNP, NumProcs, NumVertex, &
54  nodeconn,elpart,numprocpernd,procndlist,maxnumberofprocstosharenode,&
55  numelperproc,numndperproc)
56 
57  USE commglobal
58  USE linked_list2
59 
60 
61  IMPLICIT NONE
62 
63  INTEGER :: i, j, k, m, npart,icnt
64 
65  INTEGER :: numel
66  INTEGER :: numnp
67  INTEGER :: numprocs
68  INTEGER :: numvertex
69  integer :: maxnumberofprocstosharenode
70 
71  INTEGER, DIMENSION(1:NumVertex,1:NumEl) :: nodeconn
72  INTEGER, DIMENSION(1:NumEl) :: elpart
73  INTEGER, DIMENSION(1:NumNP) :: numprocpernd ! NumProcPerNd
74 
75  INTEGER, DIMENSION(1:NumNP,1:MaxNumberOfProcsToShareNode) :: procndlist
76  INTEGER, DIMENSION(1:NumProcs) :: numelperproc, numndperproc
77  INTEGER :: locnodenum, elid
78  LOGICAL :: debug = .true.
79  TYPE proclist
80  INTEGER, DIMENSION(:), POINTER :: proc_list
81  END TYPE proclist
82  TYPE(proclist), ALLOCATABLE, DIMENSION(:) :: node
83 
84 
85  INTEGER, ALLOCATABLE, DIMENSION(:) :: nproc_neigh_lst
86 
87  TYPE(procelemlist_data_ptr), pointer :: ptr
88 
89  ALLOCATE(id_sendto(1:numprocs,1:numprocs))
90 
91  id_sendto(1:numprocs,1:numprocs)%num_border_comm = 0
92 
93 
94 ! Here's a quick way to build communication lists in any
95 ! FEM-type program. There are e elements, p processors,
96 ! and n nodes. When I write that a table maps foo->bar,
97 ! I mean table[foo] .eq. bar
98 
99 ! 1.) Partition the elements (using, e.g. metis). This will
100 ! give you a table mapping element->processor.
101 
102 ! 2.) Build a list of the elements on each processor, by going
103 ! through the element->processor table once, adding each element
104 ! to the processor's local element list. Time is O(e).
105 
106 ! Initialize list
107 
108  allocate(procelemlist(1:numprocs))
109  DO i = 1, numprocs
110  nullify(procelemlist(i)%head,procelemlist(i)%tail)
111  enddo
112 
113 ! Build up list (add to stack)
114  DO i = 1, numel
115  npart = elpart(i)
116  allocate(procelem_item)
117  procelem_item%GlbElNum = i
118  CALL add_procelemlist(procelem_item,procelemlist(npart)%head,procelemlist(npart)%tail)
119  ENDDO
120 
121 
122 ! 3.) Build a list of the nodes on each processor. The way
123 ! you do this is critical:
124 ! -First, build an emtpy node->processors table, to
125 ! store a list of processors that touch each node. Time is O(n).
126 ! -For each processor, for each local element,
127 ! add this processor to all the element's nodes'
128 ! processor lists (if it's not already in the list).
129 ! The nodes' processor lists will be very short
130 ! (almost always 0 or 1), so this step will be O(n).
131 ! -Go through the node->processors table, and
132 ! add each node to all its adjacent processors.
133 ! Nearly all node->processors lists have length 1, so
134 ! this step is also O(n).
135 
136  numprocpernd(:) = 0
137 
138  DO i = 1, numprocs ! Number of processors
139  numelperproc(i) = 0 ! Get_Len_ProcElemList(ProcElemList_head(i)) ! length of linked list, i.e. number of elements per processor
140 
141  ptr => procelemlist(i)%head
142 
143  DO WHILE(ASSOCIATED(ptr))
144 
145  numelperproc(i) = numelperproc(i) + 1
146 
147  elid = ptr%GlbElNum
148 
149  DO k = 1, numvertex
150  locnodenum = nodeconn(k,elid)
151  DO m = 1, numprocpernd(locnodenum)
152  IF(procndlist(locnodenum,m).EQ.i)THEN
153  goto 2
154  ENDIF
155  ENDDO
156  numprocpernd(locnodenum) = numprocpernd(locnodenum) + 1
157  IF(numprocpernd(locnodenum).GT.maxnumberofprocstosharenode)THEN
158  print*,'Error in NewCommlist'
159  print*,'Greater then ',maxnumberofprocstosharenode, &
160  ' processors share a node on the boundary'
161  print*,'Increase MaxNumberOfProcsToShareNode'
162  print*,'MaxNumberOfProcsToShareNode =', maxnumberofprocstosharenode
163  print*,' Needed Size= ', numprocpernd(locnodenum)
164  print*,'Stopping'
165  stop
166  endif
167  procndlist(locnodenum,numprocpernd(locnodenum)) = i
168  numndperproc(i) = numndperproc(i) + 1
169 2 CONTINUE
170  ENDDO
171 
172  ptr => ptr%next
173 
174  ENDDO
175  ENDDO
176 
177 ! 4.) Build the communication lists. We can re-use the node->processors
178 ! table we built before-- go through the table, and for each node:
179 ! -If the processor list for this node has length 1 (usual case),
180 ! the node is local to the processor and never needs to be sent anywhere.
181 ! -If the length is greater than 1, the node is shared
182 ! and you add it to the comm. lists for each listed processor.
183 ! Time for this step is O(n).
184  DO i = 1, numprocs
185  DO j = 1, numprocs
186  nullify(id_sendto(i,j)%comm_head )
187  nullify(id_sendto(i,j)%comm_tail )
188  enddo
189  enddo
190 
191  DO i = 1, numnp
192  IF(numprocpernd(i).NE.1)THEN
193  DO j = 1, numprocpernd(i)
194  DO k = 1, numprocpernd(i)
195  IF(k.NE.j) CALL addcommnd(id_sendto(procndlist(i,j),procndlist(i,k)),i)
196  ENDDO
197  ENDDO
198  ENDIF
199  ENDDO
200 
201 !!$ ALLOCATE(nproc_neigh_lst(1:NumProcs))
202 !!$ nproc_neigh_lst(1:NumProcs) = 0
203 !!$ DO i = 1, NumProcs
204 !!$!
205 !!$! Determine the neighbor of processors 'i' is communicating with.
206 !!$!
207 !!$ DO j = 1,NumProcs
208 !!$ IF(ID_sendto(i,j)%num_border_comm.NE.0) &
209 !!$ nproc_neigh_lst(i) = nproc_neigh_lst(i) + 1
210 !!$ ENDDO
211 !!$
212 !!$ WRITE(4000+i-1,*) nproc_neigh_lst(i)
213 !!$
214 !!$
215 !!$
216 !!$ DO j = 1, NumProcs ! receiving processor
217 !!$ IF(ID_sendto(j,i)%num_border_comm.NE.0)THEN
218 !!$! Number of nodes that need to be communicated for R_in calculation
219 !!$ WRITE(4000+i-1,*) j-1,ID_sendto(j,i)%num_border_comm ! common
220 !!$! List of nodes that need to be communicated for R_in calculation
221 !!$ CALL print_comm_list(ID_sendto(j,i))
222 !!$ ENDIF
223 !!$ ENDDO
224 !!$
225 !!$ ENDDO
226 
227 ! That's it-- total time is O(n+e), as long as most nodes and
228 ! elements are not shared. Note that the node->processors
229 ! table we build in 3 is critical to the performance of both
230 ! 3 and 4. You could use a simpler implementation for step 3,
231 ! such as:
232 ! for each processor; for each element; add the
233 ! nodes around the element to the processor's node list
234 ! (if it's not already there).
235 !
236 
237 ! This alternate step 3 actually runs slower, because
238 ! you have to check the processor's long node list for
239 ! duplicates [it's O(p*(n/p)^2)]. Worse yet, 4 becomes
240 ! horrifically expensive without a node->processors table--
241 ! because you have to check if every node is shared,
242 ! by running through all other processor's nodes, it's O(n^2)!
243 !
244 ! For n = 10 million nodes, n^2 is unbelievably painful--
245 ! 100 trillion. The node->processors table, by contrast, can easily be
246 ! done (in C) with about 12 bytes of memory per node (a processor #,
247 ! a processor-local node #, and a rarely-used next pointer), almost
248 ! all allocated contiguously.
249 ! The node->processors table is the way to go for neighbor lists.
250 
251 
252 
253 
254 END SUBROUTINE newcommlist
255 
FT m(int i, int j) const
subroutine newcommlist(NumEl, NumNP, NumProcs, NumVertex, NodeConn, ElPart, NumProcPerNd, ProcNdList, MaxNumberOfProcsToShareNode, NumElPerProc, NumNdPerProc)
j indices k indices k
Definition: Indexing.h:6
Definition: adj.h:150
blockLoc i
Definition: read.cpp:79
subroutine addcommnd(arg_b, comm_item)
Aff_transformation_rep_baseS2< FT > * ptr() const
virtual std::ostream & print(std::ostream &os) const
j indices j
Definition: Indexing.h:6
subroutine add_procelemlist(new, head, tail)
bool debug(bool s=true)
Definition: GEM.H:193