1 | !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
2 | ! Math and Computer Science Division, Argonne National Laboratory ! |
---|
3 | !BOP ------------------------------------------------------------------- |
---|
4 | ! |
---|
5 | ! !MODULE: m_SparseMatrixPlus -- Class Parallel for Matrix-Vector Multiplication |
---|
6 | ! |
---|
7 | ! !DESCRIPTION: |
---|
8 | ! Matrix-vector multiplication is one of the MCT's core services, and is |
---|
9 | ! used primarily for the interpolation of data fields from one physical |
---|
10 | ! grid to another. Let ${\bf x} \in \Re^{N_x}$ and |
---|
11 | ! ${\bf y} \in \Re^{N_y}$ represent data fields on physical grids $A$ |
---|
12 | ! and $B$, respectively. Field data is interpolated from grid $A$ to grid |
---|
13 | ! $B$ by |
---|
14 | ! $$ {\bf y} = {\bf M} {\bf x} , $$ |
---|
15 | ! where {\bf M} is aa ${N_y} \times {N_x}$ matrix. |
---|
16 | ! |
---|
17 | ! Within MCT, the {\tt SparseMatrix} data type is MCT's object for |
---|
18 | ! storing sparse matrices such as {\bf M} , and the {\tt AttrVect} data |
---|
19 | ! type is MCT's field data storage object. That is, {\bf x} and {\bf y} |
---|
20 | ! are each stored in {\tt AttrVect} form, and {\bf M} is stored as a |
---|
21 | ! {\tt SparseMatrix}. |
---|
22 | ! |
---|
23 | ! For global address spaces (uniprocessor or shared-memory parallel), this |
---|
24 | ! picture of matrix-vector multiplication is sufficient. If one wishes |
---|
25 | ! to perform {\em distributed-memory parallel} matrix-vector multiplication, |
---|
26 | ! however, in addition to computation, one must consider {\em communication}. |
---|
27 | ! |
---|
28 | ! There are three basic message-passing parallel strategies for computing |
---|
29 | ! ${\bf y} = {\bf M} {\bf x}$: |
---|
30 | ! |
---|
31 | !\begin{enumerate} |
---|
32 | ! \item Decompose {\bf M} based on its {\em rows}, and corresponding to the |
---|
33 | ! decomposition for the vector {\bf y}. That is, if a given process owns |
---|
34 | ! the $i^{\rm th}$ element of {\bf y}, then all the elements of row $i$ of |
---|
35 | ! {\bf M} also reside on this process. Then ${\bf y} = {\bf M} {\bf x}$ is |
---|
36 | ! implemented as follows: |
---|
37 | ! \begin{enumerate} |
---|
38 | ! \item Create an {\em intermediate vector} {\bf x'} that is the pre-image of |
---|
39 | ! the elements of {\bf y} owned locally. |
---|
40 | ! \item Comunnicate with the appropriate processes on the local communicator to |
---|
41 | ! gather from {\bf x} the elements of {\bf x'}. |
---|
42 | ! \item Compute ${\bf y} = {\bf M} {\bf x'}$. |
---|
43 | ! \item Destroy the data structure holding {\bf x'}. |
---|
44 | ! \end{enumerate} |
---|
45 | ! \item Decompose {\bf M} based on its {\em columns}, and corresponding to the |
---|
46 | ! decomposition for the vector {\bf x}. That is, if a given process owns |
---|
47 | ! the $j^{\rm th}$ element of {\bf x}, then all the elements of column $j$ of |
---|
48 | ! {\bf M} also reside on this process. Then ${\bf y} = {\bf M} {\bf x}$ is |
---|
49 | ! implemented as follows: |
---|
50 | ! \begin{enumerate} |
---|
51 | ! \item Create an {\em intermediate vector} {\bf y'} that holds {\em partial sums} |
---|
52 | ! of elements of {\bf y} computed from {\bf x} and {\bf M}. |
---|
53 | ! \item Compute ${\bf y'} = {\bf M} {\bf x}$. |
---|
54 | ! \item Perform communications to route elements of {\bf y'} to their eventual |
---|
55 | ! destinations in {\bf y}, where they will be summed, resulting in the distributed |
---|
56 | ! vector {\bf y}. |
---|
57 | ! \item Destroy the data structure holding {\bf y'}. |
---|
58 | ! \end{enumerate} |
---|
59 | ! \item Decompose {\bf M} based on some arbitrary, user-supplied scheme. This will |
---|
60 | ! necessitate two intermediate vectors {\bf x'} and {\bf y'}. Then |
---|
61 | ! ${\bf y} = {\bf M} {\bf x}$ is implemented as follows: |
---|
62 | ! \begin{enumerate} |
---|
63 | ! \item Create {\em intermediate vectors} {\bf x'} and {\bf y'}. The numbers of |
---|
64 | ! elements in {\bf x'} and {\bf y'} are based {\bf M}, specifically its numbers of |
---|
65 | ! {\em distinct} row and column index values, respectively. |
---|
66 | ! \item Comunnicate with the appropriate processes on the local communicator to |
---|
67 | ! gather from {\bf x} the elements of {\bf x'}. |
---|
68 | ! \item Compute ${\bf y'} = {\bf M} {\bf x'}$. |
---|
69 | ! \item Perform communications to route elements of {\bf y'} to their eventual |
---|
70 | ! destinations in {\bf y}, where they will be summed, resulting in the distributed |
---|
71 | ! vector {\bf y}. |
---|
72 | ! \item Destroy the data structures holding {\bf x'} and {\bf y'}. |
---|
73 | ! \end{enumerate} |
---|
74 | ! \end{enumerate} |
---|
75 | ! |
---|
76 | ! These operations require information about many aspects of the multiplication |
---|
77 | ! process. These data are: |
---|
78 | ! \begin{itemize} |
---|
79 | ! \item The matrix-vector parallelization strategy, which is one of the following: |
---|
80 | ! \begin{enumerate} |
---|
81 | ! \item Distributed in {\bf x}, purely data local in {\bf y}, labeled by the |
---|
82 | ! public data member {\tt Xonly} |
---|
83 | ! \item Purely data local {\bf x}, distributed in {\bf y}, labeled by the |
---|
84 | ! public data member {\tt Yonly} |
---|
85 | ! \item Distributed in both {\bf x} and {\bf y}, labeled by the public data |
---|
86 | ! member {\tt XandY} |
---|
87 | ! \end{enumerate} |
---|
88 | ! \item A communications scheduler to create {\bf x'} from {\bf x}; |
---|
89 | ! \item A communications scheduler to deliver partial sums contained in {\bf y'} to |
---|
90 | ! {\bf y}. |
---|
91 | ! \item Lengths of the intermediate vectors {\bf x'} and {\bf y'}. |
---|
92 | ! \end{itemize} |
---|
93 | ! |
---|
94 | ! In MCT, the above data are stored in a {\em master} class for {\tt SparseMatrix}- |
---|
95 | ! {\tt AttrVect} multiplication. This master class is called a |
---|
96 | ! {\tt SparseMatrixPlus}. |
---|
97 | ! |
---|
98 | ! This module contains the definition of the {\tt SparseMatrixPlus}, and a variety |
---|
99 | ! of methods to support it. These include initialization, destruction, query, and |
---|
100 | ! data import/export. |
---|
101 | ! |
---|
102 | ! !INTERFACE: |
---|
103 | |
---|
104 | module m_SparseMatrixPlus |
---|
105 | |
---|
106 | ! !USES: |
---|
107 | |
---|
108 | use m_String, only : String |
---|
109 | use m_SparseMatrix, only : SparseMatrix |
---|
110 | use m_Rearranger, only : Rearranger |
---|
111 | |
---|
112 | ! !PUBLIC TYPES: |
---|
113 | |
---|
114 | public :: SparseMatrixPlus |
---|
115 | |
---|
116 | Type SparseMatrixPlus |
---|
117 | #ifdef SEQUENCE |
---|
118 | sequence |
---|
119 | #endif |
---|
120 | type(String) :: Strategy |
---|
121 | integer :: XPrimeLength |
---|
122 | type(Rearranger) :: XToXPrime |
---|
123 | integer :: YPrimeLength |
---|
124 | type(Rearranger) :: YPrimeToY |
---|
125 | type(SparseMatrix) :: Matrix |
---|
126 | integer :: Tag |
---|
127 | End Type SparseMatrixPlus |
---|
128 | |
---|
129 | ! !PUBLIC MEMBER FUNCTIONS: |
---|
130 | |
---|
131 | public :: init |
---|
132 | public :: vecinit |
---|
133 | public :: clean |
---|
134 | public :: initialized |
---|
135 | public :: exportStrategyToChar |
---|
136 | |
---|
137 | interface init ; module procedure & |
---|
138 | initFromRoot_, & |
---|
139 | initDistributed_ |
---|
140 | end interface |
---|
141 | interface vecinit ; module procedure vecinit_ ; end interface |
---|
142 | interface clean ; module procedure clean_ ; end interface |
---|
143 | interface initialized ; module procedure initialized_ ; end interface |
---|
144 | interface exportStrategyToChar ; module procedure & |
---|
145 | exportStrategyToChar_ |
---|
146 | end interface |
---|
147 | |
---|
148 | ! !PUBLIC DATA MEMBERS: |
---|
149 | |
---|
150 | public :: Xonly ! Matrix decomposed only by ROW (i.e., based |
---|
151 | ! on the decomposition of y); comms x->x' |
---|
152 | public :: Yonly ! Matrix decomposed only by COLUMN (i.e., based |
---|
153 | ! on the decomposition of x); comms y'->y |
---|
154 | public :: XandY ! Matrix has complex ROW/COLUMN decomposed |
---|
155 | |
---|
156 | ! !DEFINED PARAMETERS: |
---|
157 | |
---|
158 | integer,parameter :: DefaultTag = 700 |
---|
159 | |
---|
160 | |
---|
161 | ! !SEE ALSO: |
---|
162 | ! The MCT module m_SparseMatrix for more information about Sparse Matrices. |
---|
163 | ! The MCT module m_Rearranger for deatailed information about Communications |
---|
164 | ! scheduling. |
---|
165 | ! The MCT module m_AttrVect for details regarding the Attribute Vector. |
---|
166 | ! The MCT module m_MatAttrVectMult for documentation of API's that use |
---|
167 | ! the SparseMatrixPlus. |
---|
168 | ! |
---|
169 | ! !REVISION HISTORY: |
---|
170 | ! 29August 2002 - J. Larson <larson@mcs.anl.gov> - API specification. |
---|
171 | !EOP ------------------------------------------------------------------- |
---|
172 | |
---|
173 | character(len=*), parameter :: Xonly = 'Xonly' |
---|
174 | character(len=*), parameter :: Yonly = 'Yonly' |
---|
175 | character(len=*), parameter :: XandY = 'XandY' |
---|
176 | |
---|
177 | character(len=*), parameter :: myname = 'MCT::m_SparseMatrixPlus' |
---|
178 | |
---|
179 | contains |
---|
180 | |
---|
181 | !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
182 | ! Math and Computer Science Division, Argonne National Laboratory ! |
---|
183 | !BOP ------------------------------------------------------------------- |
---|
184 | ! |
---|
185 | ! !IROUTINE: initFromRoot_ - Creation and Initializtion from the Root |
---|
186 | ! |
---|
187 | ! !DESCRIPTION: |
---|
188 | ! This routine creates an {\tt SparseMatrixPlus} {\tt sMatPlus} using |
---|
189 | ! the following elements: |
---|
190 | ! \begin{itemize} |
---|
191 | ! \item A {\tt SparseMatrix} (the input argument {\tt sMat}), whose |
---|
192 | ! elements all reside only on the {\tt root} process of the MPI |
---|
193 | ! communicator with an integer handle defined by the input {\tt INTEGER} |
---|
194 | ! argument {\tt comm}; |
---|
195 | ! \item A {\tt GlobalSegMap} (the input argument {\tt xGSMap}) describing |
---|
196 | ! the domain decomposition of the vector {\bf x} on the communicator |
---|
197 | ! {\tt comm}; |
---|
198 | ! \item A {\tt GlobalSegMap} (the input argument {\tt yGSMap}) describing |
---|
199 | ! the domain decomposition of the vector {\bf y} on the communicator |
---|
200 | ! {\tt comm}; |
---|
201 | ! \item The matrix-vector multiplication parallelization strategy. This |
---|
202 | ! is set by the input {\tt CHARACTER} argument {\tt strategy}, which must |
---|
203 | ! have value corresponding to one of the following public data members |
---|
204 | ! defined in the declaration section of this module. Acceptable values |
---|
205 | ! for use in this routine are: {\tt Xonly} and {\tt Yonly}. |
---|
206 | ! \end{itemize} |
---|
207 | ! The optional argument {\tt Tag} can be used to set the tag value used in |
---|
208 | ! the call to {\tt Rearranger}. DefaultTag will be used otherwise. |
---|
209 | ! |
---|
210 | ! !INTERFACE: |
---|
211 | |
---|
212 | subroutine initFromRoot_(sMatPlus, sMat, xGSMap, yGSMap, strategy, & |
---|
213 | root, comm, ComponentID, Tag) |
---|
214 | |
---|
215 | ! !USES: |
---|
216 | |
---|
217 | use m_die |
---|
218 | use m_stdio |
---|
219 | use m_mpif90 |
---|
220 | |
---|
221 | use m_String, only : String |
---|
222 | use m_String, only : String_init => init |
---|
223 | |
---|
224 | use m_GlobalSegMap, only : GlobalSegMap |
---|
225 | use m_GlobalSegMap, only : GlobalSegMap_gsize => gsize |
---|
226 | use m_GlobalSegMap, only : GlobalSegMap_lsize => lsize |
---|
227 | use m_GlobalSegMap, only : GlobalSegMap_clean => clean |
---|
228 | |
---|
229 | use m_SparseMatrix, only : SparseMatrix |
---|
230 | use m_SparseMatrix, only : SparseMatrix_nRows => nRows |
---|
231 | use m_SparseMatrix, only : SparseMatrix_nCols => nCols |
---|
232 | |
---|
233 | use m_SparseMatrixComms, only : SparseMatrix_ScatterByRow => ScatterByRow |
---|
234 | use m_SparseMatrixComms, only : SparseMatrix_ScatterByColumn => & |
---|
235 | ScatterByColumn |
---|
236 | |
---|
237 | use m_SparseMatrixToMaps, only : SparseMatrixToXGlobalSegMap |
---|
238 | use m_SparseMatrixToMaps, only : SparseMatrixToYGlobalSegMap |
---|
239 | |
---|
240 | use m_GlobalToLocal, only : GlobalToLocalMatrix |
---|
241 | |
---|
242 | use m_Rearranger, only : Rearranger |
---|
243 | use m_Rearranger, only : Rearranger_init => init |
---|
244 | |
---|
245 | implicit none |
---|
246 | |
---|
247 | ! !INPUT PARAMETERS: |
---|
248 | |
---|
249 | type(GlobalSegMap), intent(in) :: xGSMap |
---|
250 | type(GlobalSegMap), intent(in) :: yGSMap |
---|
251 | character(len=*), intent(in) :: strategy |
---|
252 | integer, intent(in) :: root |
---|
253 | integer, intent(in) :: comm |
---|
254 | integer, intent(in) :: ComponentID |
---|
255 | integer,optional, intent(in) :: Tag |
---|
256 | |
---|
257 | ! !INPUT/OUTPUT PARAMETERS: |
---|
258 | |
---|
259 | type(SparseMatrix), intent(inout) :: sMat |
---|
260 | |
---|
261 | ! !OUTPUT PARAMETERS: |
---|
262 | |
---|
263 | type(SparseMatrixPlus), intent(out) :: SMatPlus |
---|
264 | |
---|
265 | ! !REVISION HISTORY: |
---|
266 | ! 30Aug02 - Jay Larson <larson@mcs.anl.gov> - API Specification |
---|
267 | !EOP ___________________________________________________________________ |
---|
268 | ! |
---|
269 | character(len=*),parameter :: myname_=myname//'::initFromRoot_' |
---|
270 | |
---|
271 | type(GlobalSegMap) :: xPrimeGSMap, yPrimeGSMap |
---|
272 | |
---|
273 | integer :: myID, ierr |
---|
274 | |
---|
275 | ! Set tag used in Rearranger call |
---|
276 | |
---|
277 | SMatPlus%Tag = DefaultTag |
---|
278 | if(present(Tag)) SMatPlus%Tag = Tag |
---|
279 | |
---|
280 | ! set vector flag |
---|
281 | SMatPlus%Matrix%vecinit = .FALSE. |
---|
282 | |
---|
283 | ! Get local process ID number |
---|
284 | |
---|
285 | call MPI_COMM_RANK(comm, myID, ierr) |
---|
286 | if(ierr /= 0) then |
---|
287 | call MP_perr_die(myname_,'MPI_COMM_RANK() failed',ierr) |
---|
288 | endif |
---|
289 | |
---|
290 | ! Basic Input Argument Checks: |
---|
291 | |
---|
292 | ! On the root, where the matrix is stored, do its number of |
---|
293 | ! rows and columns match the global lengths ofthe vectors y |
---|
294 | ! and x, respectively? |
---|
295 | |
---|
296 | if(myID == root) then |
---|
297 | |
---|
298 | if(GlobalSegMap_gsize(yGSMap) /= SparseMatrix_nRows(sMat)) then |
---|
299 | write(stderr,'(3a,i8,2a,i8)') myname_, & |
---|
300 | ':: FATAL--length of vector y different from row count of sMat.', & |
---|
301 | 'Length of y = ',GlobalSegMap_gsize(yGSMap),' Number of rows in ',& |
---|
302 | 'sMat = ',SparseMatrix_nRows(sMat) |
---|
303 | call die(myname_) |
---|
304 | endif |
---|
305 | |
---|
306 | if(GlobalSegMap_gsize(xGSMap) /= SparseMatrix_nCols(sMat)) then |
---|
307 | write(stderr,'(3a,i8,2a,i8)') myname_, & |
---|
308 | ':: FATAL--length of vector x different from column count of sMat.', & |
---|
309 | 'Length of x = ',GlobalSegMap_gsize(xGSMap),' Number of columns in ',& |
---|
310 | 'sMat = ',SparseMatrix_nCols(sMat) |
---|
311 | call die(myname_) |
---|
312 | endif |
---|
313 | |
---|
314 | endif ! if(myID == root) then... |
---|
315 | |
---|
316 | ! Check desired parallelization strategy name for validity. |
---|
317 | ! If either of the strategies supported by this routine are |
---|
318 | ! provided, initialize the appropriate component of sMatPlus. |
---|
319 | |
---|
320 | select case(strategy) |
---|
321 | case(Xonly) ! decompose sMat by rows following decomposition of y |
---|
322 | call String_init(sMatPlus%Strategy, strategy) |
---|
323 | case(Yonly) ! decompose sMat by columns following decomposition of x |
---|
324 | call String_init(sMatPlus%Strategy, strategy) |
---|
325 | case(XandY) ! User has called the wrong routine. Try initDistributed() |
---|
326 | ! instead. |
---|
327 | write(stderr,'(4a)') myname_, & |
---|
328 | ':: ERROR--Strategy name = ',strategy,' not supported by this routine.' |
---|
329 | case default ! strategy name not recognized. |
---|
330 | write(stderr,'(5a)') myname_, & |
---|
331 | ':: ERROR--Invalid parallelization strategy name = ',strategy,' not ', & |
---|
332 | 'recognized by this module.' |
---|
333 | call die(myname_) |
---|
334 | end select |
---|
335 | |
---|
336 | ! End Argument Sanity Checks. |
---|
337 | |
---|
338 | ! Based on the parallelization strategy, scatter sMat into |
---|
339 | ! sMatPlus%Matrix accordingly. |
---|
340 | |
---|
341 | select case(strategy) |
---|
342 | case(Xonly) |
---|
343 | ! Scatter sMat by Row |
---|
344 | call SparseMatrix_ScatterByRow(yGSMap, sMat, sMatPlus%Matrix, root, & |
---|
345 | comm, ierr) |
---|
346 | ! Compute GlobalSegMap associated with intermediate vector x' |
---|
347 | call SparseMatrixToXGlobalSegMap(sMatPlus%Matrix, xPrimeGSMap, & |
---|
348 | root, comm, ComponentID) |
---|
349 | ! Determine length of x' from xPrimeGSMap: |
---|
350 | sMatPlus%XPrimeLength = GlobalSegMap_lsize(xPrimeGSMap, comm) |
---|
351 | ! Create Rearranger to assemble x' from x |
---|
352 | call Rearranger_init(xGSMap, xPrimeGSMap, comm, sMatPlus%XToXPrime) |
---|
353 | ! Create local column indices based on xPrimeGSMap |
---|
354 | call GlobalToLocalMatrix(sMatPlus%Matrix, xPrimeGSMap, 'column', comm) |
---|
355 | ! Create local row indices based on yGSMap |
---|
356 | call GlobalToLocalMatrix(sMatPlus%Matrix, yGSMap, 'row', comm) |
---|
357 | ! Destroy intermediate GlobalSegMap for x' |
---|
358 | call GlobalSegMap_clean(xPrimeGSMap) |
---|
359 | case(Yonly) |
---|
360 | ! Scatter sMat by Column |
---|
361 | call SparseMatrix_ScatterByColumn(xGSMap, sMat, sMatPlus%Matrix, root, & |
---|
362 | comm, ierr) |
---|
363 | ! Compute GlobalSegMap associated with intermediate vector y' |
---|
364 | call SparseMatrixToYGlobalSegMap(sMatPlus%Matrix, yPrimeGSMap, & |
---|
365 | root, comm, ComponentID) |
---|
366 | ! Determine length of y' from yPrimeGSMap: |
---|
367 | sMatPlus%YPrimeLength = GlobalSegMap_lsize(yPrimeGSMap, comm) |
---|
368 | ! Create Rearranger to assemble y from partial sums in y' |
---|
369 | call Rearranger_init(yPrimeGSMap, yGSMap, comm, sMatPlus%YPrimeToY) |
---|
370 | ! Create local row indices based on yPrimeGSMap |
---|
371 | call GlobalToLocalMatrix(sMatPlus%Matrix, yPrimeGSMap, 'row', comm) |
---|
372 | ! Create local column indices based on xGSMap |
---|
373 | call GlobalToLocalMatrix(sMatPlus%Matrix, xGSMap, 'column', comm) |
---|
374 | ! Destroy intermediate GlobalSegMap for y' |
---|
375 | call GlobalSegMap_clean(yPrimeGSMap) |
---|
376 | case default ! do nothing |
---|
377 | end select |
---|
378 | |
---|
379 | end subroutine initFromRoot_ |
---|
380 | |
---|
381 | !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
382 | ! Math and Computer Science Division, Argonne National Laboratory ! |
---|
383 | !BOP ------------------------------------------------------------------- |
---|
384 | ! |
---|
385 | ! !IROUTINE: initDistributed_ - Distributed Creation and Initializtion |
---|
386 | ! |
---|
387 | ! !DESCRIPTION: |
---|
388 | ! This routine creates an {\tt SparseMatrixPlus} {\tt sMatPlus} using |
---|
389 | ! the following elements: |
---|
390 | ! \begin{itemize} |
---|
391 | ! \item A {\tt SparseMatrix} (the input argument {\tt sMat}), whose |
---|
392 | ! elements have previously been destributed across the MPI communicator |
---|
393 | ! with an integer handle defined by the input {\tt INTEGER} argument |
---|
394 | ! {\tt comm}; |
---|
395 | ! \item A {\tt GlobalSegMap} (the input argument {\tt xGSMap}) describing |
---|
396 | ! the domain decomposition of the vector {\bf x} on the communicator |
---|
397 | ! {\tt comm}; and |
---|
398 | ! \item A {\tt GlobalSegMap} (the input argument {\tt yGSMap}) describing |
---|
399 | ! the domain decomposition of the vector {\bf y} on the communicator |
---|
400 | ! {\tt comm}; |
---|
401 | ! \end{itemize} |
---|
402 | ! The other input arguments required by this routine are the {\tt INTEGER} |
---|
403 | ! arguments {\tt root} and {\tt ComponentID}, which define the communicator |
---|
404 | ! root ID and MCT component ID, respectively. |
---|
405 | ! |
---|
406 | ! !INTERFACE: |
---|
407 | |
---|
408 | subroutine initDistributed_(sMatPlus, sMat, xGSMap, yGSMap, root, comm, & |
---|
409 | ComponentID, Tag) |
---|
410 | |
---|
411 | ! !USES: |
---|
412 | |
---|
413 | use m_die |
---|
414 | use m_stdio |
---|
415 | use m_mpif90 |
---|
416 | |
---|
417 | use m_String, only : String |
---|
418 | use m_String, only : String_init => init |
---|
419 | |
---|
420 | use m_GlobalSegMap, only : GlobalSegMap |
---|
421 | use m_GlobalSegMap, only : GlobalSegMap_gsize => gsize |
---|
422 | use m_GlobalSegMap, only : GlobalSegMap_lsize => lsize |
---|
423 | use m_GlobalSegMap, only : GlobalSegMap_clean => clean |
---|
424 | |
---|
425 | use m_SparseMatrix, only : SparseMatrix |
---|
426 | use m_SparseMatrix, only : SparseMatrix_nRows => nRows |
---|
427 | use m_SparseMatrix, only : SparseMatrix_nCols => nCols |
---|
428 | use m_SparseMatrix, only : SparseMatrix_Copy => Copy |
---|
429 | |
---|
430 | use m_SparseMatrixComms, only : SparseMatrix_ScatterByRow => ScatterByRow |
---|
431 | use m_SparseMatrixComms, only : SparseMatrix_ScatterByColumn => & |
---|
432 | ScatterByColumn |
---|
433 | |
---|
434 | use m_SparseMatrixToMaps, only : SparseMatrixToXGlobalSegMap |
---|
435 | use m_SparseMatrixToMaps, only : SparseMatrixToYGlobalSegMap |
---|
436 | |
---|
437 | use m_GlobalToLocal, only : GlobalToLocalMatrix |
---|
438 | |
---|
439 | use m_Rearranger, only : Rearranger |
---|
440 | use m_Rearranger, only : Rearranger_init => init |
---|
441 | |
---|
442 | implicit none |
---|
443 | |
---|
444 | ! !INPUT PARAMETERS: |
---|
445 | |
---|
446 | type(GlobalSegMap), intent(in) :: xGSMap |
---|
447 | type(GlobalSegMap), intent(in) :: yGSMap |
---|
448 | integer, intent(in) :: root |
---|
449 | integer, intent(in) :: comm |
---|
450 | integer, intent(in) :: ComponentID |
---|
451 | integer,optional, intent(in) :: Tag |
---|
452 | |
---|
453 | ! !INPUT/OUTPUT PARAMETERS: |
---|
454 | |
---|
455 | type(SparseMatrix), intent(inout) :: sMat |
---|
456 | |
---|
457 | ! !OUTPUT PARAMETERS: |
---|
458 | |
---|
459 | type(SparseMatrixPlus), intent(out) :: SMatPlus |
---|
460 | |
---|
461 | ! !REVISION HISTORY: |
---|
462 | ! 30Aug02 - Jay Larson <larson@mcs.anl.gov> - API Specification |
---|
463 | !EOP ___________________________________________________________________ |
---|
464 | ! |
---|
465 | character(len=*),parameter :: myname_=myname//'::initDistributed_' |
---|
466 | |
---|
467 | type(GlobalSegMap) :: xPrimeGSMap, yPrimeGSMap |
---|
468 | |
---|
469 | integer :: myID, ierr |
---|
470 | |
---|
471 | ! Set tag used in Rearranger call |
---|
472 | |
---|
473 | SMatPlus%Tag = DefaultTag |
---|
474 | if(present(Tag)) SMatPlus%Tag = Tag |
---|
475 | |
---|
476 | ! Get local process ID number |
---|
477 | |
---|
478 | call MPI_COMM_RANK(comm, myID, ierr) |
---|
479 | if(ierr /= 0) then |
---|
480 | call MP_perr_die(myname_,'MPI_COMM_RANK() failed',ierr) |
---|
481 | endif |
---|
482 | ! Basic Input Argument Checks: |
---|
483 | |
---|
484 | ! A portion of sMat (even if there are no nonzero elements in |
---|
485 | ! this local chunk) on each PE. We must check to ensure the |
---|
486 | ! number rows and columns match the global lengths ofthe |
---|
487 | ! vectors y and x, respectively. |
---|
488 | |
---|
489 | if(GlobalSegMap_gsize(yGSMap) /= SparseMatrix_nRows(sMat)) then |
---|
490 | write(stderr,'(3a,i8,2a,i8)') myname, & |
---|
491 | ':: FATAL--length of vector y different from row count of sMat.', & |
---|
492 | 'Length of y = ',GlobalSegMap_gsize(yGSMap),' Number of rows in ',& |
---|
493 | 'sMat = ',SparseMatrix_nRows(sMat) |
---|
494 | call die(myname_) |
---|
495 | endif |
---|
496 | |
---|
497 | if(GlobalSegMap_gsize(xGSMap) /= SparseMatrix_nCols(sMat)) then |
---|
498 | write(stderr,'(3a,i8,2a,i8)') myname, & |
---|
499 | ':: FATAL--length of vector x different from column count of sMat.', & |
---|
500 | 'Length of x = ',GlobalSegMap_gsize(xGSMap),' Number of columns in ',& |
---|
501 | 'sMat = ',SparseMatrix_nCols(sMat) |
---|
502 | call die(myname_) |
---|
503 | endif |
---|
504 | |
---|
505 | ! End Argument Sanity Checks. |
---|
506 | |
---|
507 | ! Set parallelization strategy to XandY, since the work distribution |
---|
508 | ! was previously determined and in principle can be *anything* |
---|
509 | |
---|
510 | call String_init(sMatPlus%Strategy, XandY) |
---|
511 | |
---|
512 | ! Based on the XandY parallelization strategy, build SMatPlus |
---|
513 | ! First, copy Internals of sMat into sMatPlus%Matrix: |
---|
514 | call SparseMatrix_Copy(sMat, sMatPlus%Matrix) |
---|
515 | ! Compute GlobalSegMap associated with intermediate vector x' |
---|
516 | call SparseMatrixToXGlobalSegMap(sMatPlus%Matrix, xPrimeGSMap, & |
---|
517 | root, comm, ComponentID) |
---|
518 | ! Determine length of x' from xPrimeGSMap: |
---|
519 | sMatPlus%XPrimeLength = GlobalSegMap_lsize(xPrimeGSMap, comm) |
---|
520 | ! Create Rearranger to assemble x' from x |
---|
521 | call Rearranger_init(xGSMap, xPrimeGSMap, comm, sMatPlus%XToXPrime) |
---|
522 | ! Create local column indices based on xPrimeGSMap |
---|
523 | call GlobalToLocalMatrix(sMatPlus%Matrix, xPrimeGSMap, 'column', comm) |
---|
524 | ! Destroy intermediate GlobalSegMap for x' |
---|
525 | call GlobalSegMap_clean(xPrimeGSMap) |
---|
526 | ! Compute GlobalSegMap associated with intermediate vector y' |
---|
527 | call SparseMatrixToYGlobalSegMap(sMatPlus%Matrix, yPrimeGSMap, & |
---|
528 | root, comm, ComponentID) |
---|
529 | ! Determine length of y' from yPrimeGSMap: |
---|
530 | sMatPlus%YPrimeLength = GlobalSegMap_lsize(yPrimeGSMap, comm) |
---|
531 | ! Create Rearranger to assemble y from partial sums in y' |
---|
532 | call Rearranger_init(yPrimeGSMap, yGSMap, comm, sMatPlus%YPrimeToY) |
---|
533 | ! Create local row indices based on yPrimeGSMap |
---|
534 | call GlobalToLocalMatrix(sMatPlus%Matrix, yPrimeGSMap, 'row', comm) |
---|
535 | ! Destroy intermediate GlobalSegMap for y' |
---|
536 | call GlobalSegMap_clean(yPrimeGSMap) |
---|
537 | |
---|
538 | end subroutine initDistributed_ |
---|
539 | |
---|
540 | !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
541 | ! Math and Computer Science Division, Argonne National Laboratory ! |
---|
542 | !BOP ------------------------------------------------------------------- |
---|
543 | ! |
---|
544 | ! !IROUTINE: vecinit_ - Initialize vector parts of a SparseMatrixPlus |
---|
545 | ! |
---|
546 | ! !DESCRIPTION: |
---|
547 | ! This routine will initialize the parts of the SparseMatrix in |
---|
548 | ! the SparseMatrixPlus object that are used in the vector-friendly |
---|
549 | ! version of the sparse matrix multiply. |
---|
550 | ! |
---|
551 | ! !INTERFACE: |
---|
552 | |
---|
553 | subroutine vecinit_(SMatP) |
---|
554 | ! |
---|
555 | ! !USES: |
---|
556 | ! |
---|
557 | use m_die |
---|
558 | use m_SparseMatrix, only : SparseMatrix_vecinit => vecinit |
---|
559 | |
---|
560 | implicit none |
---|
561 | |
---|
562 | ! !INPUT/OUTPUT PARAMETERS: |
---|
563 | |
---|
564 | type(SparseMatrixPlus), intent(inout) :: SMatP |
---|
565 | |
---|
566 | ! !REVISION HISTORY: |
---|
567 | ! 29Oct03 - R. Jacob <jacob@mcs.anl.gov> - initial prototype |
---|
568 | !EOP ___________________________________________________________________ |
---|
569 | ! |
---|
570 | character(len=*),parameter :: myname_=myname//'::vecinit_' |
---|
571 | |
---|
572 | call SparseMatrix_vecinit(SMatP%Matrix) |
---|
573 | |
---|
574 | end subroutine vecinit_ |
---|
575 | |
---|
576 | !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
577 | ! Math and Computer Science Division, Argonne National Laboratory ! |
---|
578 | !BOP ------------------------------------------------------------------- |
---|
579 | ! |
---|
580 | ! !IROUTINE: clean_ - Destruction of a SparseMatrixPlus Object |
---|
581 | ! |
---|
582 | ! !DESCRIPTION: |
---|
583 | ! This routine deallocates all allocated memory belonging to the |
---|
584 | ! input/output {\tt SparseMatrixPlus} argument {\tt SMatP}, and sets |
---|
585 | ! to zero its integer components describing intermediate vector length, |
---|
586 | ! and sets its {\tt LOGICAL} flag signifying initialization to |
---|
587 | ! {\tt .FALSE.} The success (failure) of this operation is signified |
---|
588 | ! by the zero (non-zero) value of the optional {\tt INTEGER} output |
---|
589 | ! argument {\tt status}. If the user does supply {\tt status} when |
---|
590 | ! invoking this routine, failure of {\tt clean\_()} will lead to |
---|
591 | ! termination of execution with an error message. |
---|
592 | ! |
---|
593 | ! !INTERFACE: |
---|
594 | |
---|
595 | subroutine clean_(SMatP, status) |
---|
596 | |
---|
597 | ! !USES: |
---|
598 | |
---|
599 | use m_die |
---|
600 | use m_stdio |
---|
601 | |
---|
602 | use m_String, only : String |
---|
603 | use m_String, only : String_init => init |
---|
604 | use m_String, only : String_ToChar => toChar |
---|
605 | use m_String, only : String_clean => clean |
---|
606 | |
---|
607 | use m_SparseMatrix, only : SparseMatrix |
---|
608 | use m_SparseMatrix, only : SparseMatrix_clean => clean |
---|
609 | |
---|
610 | use m_Rearranger, only : Rearranger |
---|
611 | use m_Rearranger, only : Rearranger_clean => clean |
---|
612 | |
---|
613 | implicit none |
---|
614 | |
---|
615 | ! !INPUT/OUTPUT PARAMETERS: |
---|
616 | |
---|
617 | type(SparseMatrixPlus), intent(inout) :: SMatP |
---|
618 | |
---|
619 | ! !OUTPUT PARAMETERS: |
---|
620 | |
---|
621 | integer, optional, intent(out) :: status |
---|
622 | |
---|
623 | ! !REVISION HISTORY: |
---|
624 | ! 30Aug02 - Jay Larson <larson@mcs.anl.gov> - API Specification |
---|
625 | !EOP ___________________________________________________________________ |
---|
626 | ! |
---|
627 | character(len=*),parameter :: myname_=myname//'::clean_' |
---|
628 | |
---|
629 | integer :: myStatus |
---|
630 | type(String) :: dummyStrategy ! SGI IR->WHIRL work-around |
---|
631 | character(len=5) :: myStrategy |
---|
632 | |
---|
633 | ! If status was supplied, set it to zero (success) |
---|
634 | |
---|
635 | if(present(status)) status = 0 |
---|
636 | |
---|
637 | ! The following string copy is superfluous. It is placed here |
---|
638 | ! to outwit a compiler bug in the SGI and SunOS compilers. |
---|
639 | ! It occurs when a component of a derived type is used as an |
---|
640 | ! argument to String_ToChar. This bug crashes the compiler |
---|
641 | ! with the error message: |
---|
642 | ! Error: Signal Segmentation fault in phase IR->WHIRL Conversion |
---|
643 | |
---|
644 | call String_init(dummyStrategy, SMatP%Strategy) |
---|
645 | myStrategy = String_ToChar(dummyStrategy) |
---|
646 | |
---|
647 | ! Use SMatP%Strategy to determine which Rearranger(s) need |
---|
648 | ! to be destroyed. The CHARACTER parameters Xonly, Yonly, |
---|
649 | ! and XandY are inherited from the declaration section of |
---|
650 | ! this module. |
---|
651 | |
---|
652 | |
---|
653 | select case(myStrategy) |
---|
654 | case(Xonly) ! destroy X-rearranger only |
---|
655 | |
---|
656 | call Rearranger_clean(SMatP%XToXprime, myStatus) |
---|
657 | if(myStatus /= 0) then ! something went wrong |
---|
658 | if(present(status)) then |
---|
659 | status = myStatus |
---|
660 | return |
---|
661 | else |
---|
662 | write(stderr,'(3a,i8)') myname_, & |
---|
663 | ':: ERROR - call to Rearranger_clean(SMatP%XToXprime) failed.', & |
---|
664 | ' stat = ',myStatus |
---|
665 | endif |
---|
666 | endif |
---|
667 | |
---|
668 | case(Yonly) ! destroy Y-rearranger only |
---|
669 | |
---|
670 | call Rearranger_clean(SMatP%YprimeToY, myStatus) |
---|
671 | if(myStatus /= 0) then ! something went wrong |
---|
672 | if(present(status)) then |
---|
673 | status = myStatus |
---|
674 | return |
---|
675 | else |
---|
676 | write(stderr,'(3a,i8)') myname_, & |
---|
677 | ':: ERROR - call to Rearranger_clean(SMatP%YPrimeToY) failed.', & |
---|
678 | ' stat = ',myStatus |
---|
679 | endif |
---|
680 | endif |
---|
681 | |
---|
682 | case(XandY) ! destroy both X- and Y-rearrangers |
---|
683 | |
---|
684 | call Rearranger_clean(SMatP%XToXprime, myStatus) |
---|
685 | if(myStatus /= 0) then ! something went wrong |
---|
686 | if(present(status)) then |
---|
687 | status = myStatus |
---|
688 | return |
---|
689 | else |
---|
690 | write(stderr,'(3a,i8)') myname_, & |
---|
691 | ':: ERROR - call to Rearranger_clean(SMatP%XToXprime) failed.', & |
---|
692 | ' stat = ',myStatus |
---|
693 | endif |
---|
694 | endif |
---|
695 | |
---|
696 | call Rearranger_clean(SMatP%YprimeToY, myStatus) |
---|
697 | if(myStatus /= 0) then ! something went wrong |
---|
698 | if(present(status)) then |
---|
699 | status = myStatus |
---|
700 | return |
---|
701 | else |
---|
702 | write(stderr,'(3a,i8)') myname_, & |
---|
703 | ':: ERROR - call to Rearranger_clean(SMatP%YPrimeToY) failed.', & |
---|
704 | ' stat = ',myStatus |
---|
705 | endif |
---|
706 | endif |
---|
707 | |
---|
708 | case default ! do nothing--corresponds to purely data local case |
---|
709 | end select |
---|
710 | |
---|
711 | ! Zero out XPrimeLength and YPrimeLength |
---|
712 | |
---|
713 | SMatP%XPrimeLength = 0 |
---|
714 | SMatP%YPrimeLength = 0 |
---|
715 | |
---|
716 | ! Destroy the SparseMatrix component SMatP%Matrix |
---|
717 | |
---|
718 | call SparseMatrix_clean(SMatP%Matrix, myStatus) |
---|
719 | if(myStatus /= 0) then ! something went wrong |
---|
720 | if(present(status)) then |
---|
721 | status = myStatus |
---|
722 | return |
---|
723 | else |
---|
724 | write(stderr,'(2a,i8)') myname_, & |
---|
725 | ':: ERROR - call to SparseMatrix_clean() failed with stat=',myStatus |
---|
726 | endif |
---|
727 | endif |
---|
728 | |
---|
729 | ! Destroy the String SMatP%Strategy and its copy |
---|
730 | |
---|
731 | call String_clean(SMatP%Strategy) |
---|
732 | call String_clean(dummyStrategy) |
---|
733 | |
---|
734 | end subroutine clean_ |
---|
735 | |
---|
736 | !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
737 | ! Math and Computer Science Division, Argonne National Laboratory ! |
---|
738 | !BOP ------------------------------------------------------------------- |
---|
739 | ! |
---|
740 | ! !IROUTINE: initialized_ - Confirmation of Initialization |
---|
741 | ! |
---|
742 | ! !DESCRIPTION: |
---|
743 | ! This {\tt LOGICAL} query function tells the user if the input |
---|
744 | ! {\tt SparseMatrixPlus} argument {\tt sMatPlus} has been initialized. |
---|
745 | ! The return value of {\tt initialized\_} is {\tt .TRUE.} if |
---|
746 | ! {\tt sMatPlus} has been previously initialized, {\tt .FALSE.} if it |
---|
747 | ! has not. |
---|
748 | ! |
---|
749 | ! !INTERFACE: |
---|
750 | |
---|
751 | logical function initialized_(sMatPlus) |
---|
752 | ! |
---|
753 | ! !USES: |
---|
754 | ! |
---|
755 | ! No external modules are used by this function. |
---|
756 | |
---|
757 | use m_String, only : String_len |
---|
758 | use m_List, only : List |
---|
759 | use m_List, only : List_init => init |
---|
760 | use m_List, only : List_identical => identical |
---|
761 | use m_List, only : List_clean => clean |
---|
762 | |
---|
763 | use m_die |
---|
764 | |
---|
765 | implicit none |
---|
766 | |
---|
767 | ! !INPUT PARAMETERS: |
---|
768 | ! |
---|
769 | type(SparseMatrixPlus), intent(in) :: sMatPlus |
---|
770 | |
---|
771 | ! !REVISION HISTORY: |
---|
772 | ! 26Sep02 - Jay Larson <larson@mcs.anl.gov> - Implementation |
---|
773 | !EOP ___________________________________________________________________ |
---|
774 | ! |
---|
775 | character(len=*),parameter :: myname_=myname//'::initialized_' |
---|
776 | |
---|
777 | integer :: XonlyLen, YonlyLen, XandYLen |
---|
778 | type(List) :: XonlyList, YonlyList, XandYList, stratList |
---|
779 | |
---|
780 | initialized_ = .FALSE. |
---|
781 | |
---|
782 | XonlyLen = len(trim(Xonly)) |
---|
783 | YonlyLen = len(trim(Yonly)) |
---|
784 | XandYLen = len(trim(XandY)) |
---|
785 | |
---|
786 | if( (XonlyLen /= YonlyLen) .or. (XonlyLen /= XandYLen) ) then |
---|
787 | call die(myname_,"The length of the strategies are unequal. & |
---|
788 | &This routine needs to be rewritten.") |
---|
789 | endif |
---|
790 | |
---|
791 | if(associated(sMatPlus%strategy%c)) then |
---|
792 | if(String_len(sMatPlus%strategy) == XonlyLen) then |
---|
793 | call List_init(XonlyList,Xonly) |
---|
794 | call List_init(YonlyList,Yonly) |
---|
795 | call List_init(XandYList,XandY) |
---|
796 | call List_init(stratList,sMatPlus%strategy) |
---|
797 | if(List_identical(stratList,XonlyList)) initialized_ = .TRUE. |
---|
798 | if(List_identical(stratList,YonlyList)) initialized_ = .TRUE. |
---|
799 | if(List_identical(stratList,XandYList)) initialized_ = .TRUE. |
---|
800 | call List_clean(XonlyList) |
---|
801 | call List_clean(YonlyList) |
---|
802 | call List_clean(XandYList) |
---|
803 | call List_clean(stratList) |
---|
804 | endif |
---|
805 | endif |
---|
806 | |
---|
807 | end function initialized_ |
---|
808 | |
---|
809 | !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
810 | ! Math and Computer Science Division, Argonne National Laboratory ! |
---|
811 | !BOP ------------------------------------------------------------------- |
---|
812 | ! |
---|
813 | ! !IROUTINE: exportStrategyToChar - Return Parallelization Strategy |
---|
814 | ! |
---|
815 | ! !DESCRIPTION: |
---|
816 | ! This query subroutine returns the parallelization strategy set in |
---|
817 | ! the input {\tt SparseMatrixPlus} argument {\tt sMatPlus}. The result |
---|
818 | ! is returned in the output {\tt CHARACTER} argument {\tt StratChars}. |
---|
819 | ! |
---|
820 | ! !INTERFACE: |
---|
821 | |
---|
822 | function exportStrategyToChar_(sMatPlus) |
---|
823 | ! |
---|
824 | ! !USES: |
---|
825 | ! |
---|
826 | use m_stdio |
---|
827 | use m_die |
---|
828 | |
---|
829 | use m_String, only : String_ToChar => toChar |
---|
830 | use m_String, only : String_init => init |
---|
831 | use m_String, only : String_clean => clean |
---|
832 | use m_String, only : String |
---|
833 | |
---|
834 | implicit none |
---|
835 | |
---|
836 | ! !INPUT PARAMETERS: |
---|
837 | ! |
---|
838 | type(SparseMatrixPlus), intent(in) :: sMatPlus |
---|
839 | |
---|
840 | ! !OUTPUT PARAMETERS: |
---|
841 | ! |
---|
842 | character(len=size(sMatPlus%Strategy%c)) :: exportStrategyToChar_ |
---|
843 | |
---|
844 | ! !REVISION HISTORY: |
---|
845 | ! 01Aug07 - Jay Larson <larson@mcs.anl.gov> - Implementation |
---|
846 | !EOP ___________________________________________________________________ |
---|
847 | ! |
---|
848 | character(len=*),parameter :: myname_=myname//'::exportStrategyToChar_' |
---|
849 | type(String) :: dummyStrategy ! SGI IR->WHIRL work-around |
---|
850 | |
---|
851 | ! Check input argument to ensure it has been initialized. If not, |
---|
852 | ! signal an error and terminate execution. |
---|
853 | |
---|
854 | if( .not. initialized_(sMatPlus) ) then |
---|
855 | write(stderr,'(3a)') myname_,':: Warning, input argument not initialized, ', & |
---|
856 | 'returning empty character field for parallelization strategy.' |
---|
857 | exportStrategyToChar_ = ' ' |
---|
858 | return |
---|
859 | endif |
---|
860 | |
---|
861 | ! Return in character form the parallelizaiton strategy |
---|
862 | call String_init(dummyStrategy, SMatPlus%Strategy) |
---|
863 | |
---|
864 | exportStrategyToChar_ = String_ToChar(dummyStrategy) |
---|
865 | |
---|
866 | call String_clean(dummyStrategy) |
---|
867 | |
---|
868 | end function exportStrategyToChar_ |
---|
869 | |
---|
870 | end module m_SparseMatrixPlus |
---|
871 | |
---|