1 /* FactorMPI.c */
2
3 #include "../BridgeMPI.h"
4
5 #define MYDEBUG 1
6
7 #if MYDEBUG > 0
8 static int count_Factor = 0 ;
9 static double time_Factor = 0.0 ;
10 #endif
11
12 /*--------------------------------------------------------------------*/
13 /*
14 ---------------------------------------------------------------------
15 purpose -- to compute the factorization of A - sigma * B
16
17 note: all variables in the calling sequence are references
18 to allow call from fortran.
19
20 input parameters
21
22 data -- pointer to bridge data object
23 psigma -- shift for the matrix pencil
24 ppvttol -- pivot tolerance
25 *ppvttol = 0.0 --> no pivoting used
26 *ppvttol != 0.0 --> pivoting used, entries in factor are
27 bounded above by 1/pvttol in magnitude
28
29 output parameters
30
31 *pinertia -- on return contains the number of negative eigenvalues
32 *perror -- on return contains an error code
33 1 -- error found during factorization
34 0 -- normal return
35 -1 -- psigma is NULL
36 -2 -- ppvttol is NULL
37 -3 -- data is NULL
38 -4 -- pinertia is NULL
39
40 created -- 98aug10, cca & jcp
41 ---------------------------------------------------------------------
42 */
43 void
FactorMPI(double * psigma,double * ppvttol,void * data,int * pinertia,int * perror)44 FactorMPI (
45 double *psigma,
46 double *ppvttol,
47 void *data,
48 int *pinertia,
49 int *perror
50 ) {
51 BridgeMPI *bridge = (BridgeMPI *) data ;
52 Chv *rootchv ;
53 ChvManager *chvmanager ;
54 double droptol=0.0, tau ;
55 double cpus[20] ;
56 FILE *msgFile ;
57 int recvtemp[3], sendtemp[3], stats[20] ;
58 int msglvl, nnegative, nzero, npositive, pivotingflag, tag ;
59 MPI_Comm comm ;
60 int nproc ;
61
62 #if MYDEBUG > 0
63 double t1, t2 ;
64 count_Factor++ ;
65 MARKTIME(t1) ;
66 if ( bridge->myid == 0 ) {
67 fprintf(stdout, "\n (%d) FactorMPI()", count_Factor) ;
68 fflush(stdout) ;
69 }
70 #endif
71 #if MYDEBUG > 1
72 fprintf(bridge->msgFile, "\n (%d) FactorMPI()", count_Factor) ;
73 fflush(bridge->msgFile) ;
74 #endif
75
76 nproc = bridge->nproc ;
77 /*
78 ---------------
79 check the input
80 ---------------
81 */
82 if ( psigma == NULL ) {
83 fprintf(stderr, "\n error in FactorMPI()"
84 "\n psigma is NULL\n") ;
85 *perror = -1 ; return ;
86 }
87 if ( ppvttol == NULL ) {
88 fprintf(stderr, "\n error in FactorMPI()"
89 "\n ppvttol is NULL\n") ;
90 *perror = -2 ; return ;
91 }
92 if ( data == NULL ) {
93 fprintf(stderr, "\n error in FactorMPI()"
94 "\n data is NULL\n") ;
95 *perror = -3 ; return ;
96 }
97 if ( pinertia == NULL ) {
98 fprintf(stderr, "\n error in FactorMPI()"
99 "\n pinertia is NULL\n") ;
100 *perror = -4 ; return ;
101 }
102 if ( perror == NULL ) {
103 fprintf(stderr, "\n error in FactorMPI()"
104 "\n perror is NULL\n") ;
105 return ;
106 }
107 comm = bridge->comm ;
108 msglvl = bridge->msglvl ;
109 msgFile = bridge->msgFile ;
110 /*
111 ----------------------------------
112 set the shift in the pencil object
113 ----------------------------------
114 */
115 bridge->pencil->sigma[0] = -(*psigma) ;
116 bridge->pencil->sigma[1] = 0.0 ;
117 /*
118 -----------------------------------------
119 if the matrices are in local coordinates
120 (i.e., this is the first factorization
121 following a matrix-vector multiply) then
122 map the matrix into global coordinates
123 -----------------------------------------
124 */
125 if ( bridge->coordFlag == LOCAL ) {
126 if ( bridge->prbtype == 1 ) {
127 MatMul_setGlobalIndices(bridge->info, bridge->B) ;
128 if ( msglvl > 2 ) {
129 fprintf(msgFile, "\n\n matrix B in local coordinates") ;
130 InpMtx_writeForHumanEye(bridge->B, msgFile) ;
131 fflush(msgFile) ;
132 }
133 }
134 if ( bridge->prbtype == 2 ) {
135 MatMul_setGlobalIndices(bridge->info, bridge->A) ;
136 if ( msglvl > 2 ) {
137 fprintf(msgFile, "\n\n matrix A in local coordinates") ;
138 InpMtx_writeForHumanEye(bridge->A, msgFile) ;
139 fflush(msgFile) ;
140 }
141 }
142 bridge->coordFlag = GLOBAL ;
143 }
144 /*
145 -----------------------------------------------------
146 clear the front matrix and submatrix mananger objects
147 -----------------------------------------------------
148 */
149 FrontMtx_clearData(bridge->frontmtx);
150 SubMtxManager_clearData(bridge->mtxmanager);
151 SolveMap_clearData(bridge->solvemap) ;
152 if ( bridge->rowmapIV != NULL ) {
153 IV_free(bridge->rowmapIV) ;
154 bridge->rowmapIV = NULL ;
155 }
156 /*
157 -----------------------------------------------------------
158 set the pivot tolerance.
159 NOTE: spooles's "tau" parameter is a bound on the magnitude
160 of the factor entries, and is the recipricol of that of the
161 pivot tolerance of the lanczos code
162 -----------------------------------------------------------
163 */
164 if ( *ppvttol == 0.0 ) {
165 tau = 10.0 ;
166 pivotingflag = SPOOLES_NO_PIVOTING ;
167 } else {
168 tau = (1.0)/(*ppvttol) ;
169 pivotingflag = SPOOLES_PIVOTING ;
170 }
171 /*
172 ----------------------------------
173 initialize the front matrix object
174 ----------------------------------
175 */
176 FrontMtx_init(bridge->frontmtx, bridge->frontETree, bridge->symbfacIVL,
177 SPOOLES_REAL, SPOOLES_SYMMETRIC, FRONTMTX_DENSE_FRONTS,
178 pivotingflag, NO_LOCK, bridge->myid, bridge->ownersIV,
179 bridge->mtxmanager, bridge->msglvl, bridge->msgFile) ;
180 /*
181 -------------------------
182 compute the factorization
183 -------------------------
184 */
185 tag = 0 ;
186 chvmanager = ChvManager_new() ;
187 ChvManager_init(chvmanager, NO_LOCK, 0);
188 IVfill(20, stats, 0) ;
189 DVfill(20, cpus, 0.0) ;
190 rootchv = FrontMtx_MPI_factorPencil(bridge->frontmtx, bridge->pencil,
191 tau, droptol, chvmanager, bridge->ownersIV,
192 0, perror, cpus, stats, bridge->msglvl,
193 bridge->msgFile, tag, comm) ;
194 ChvManager_free(chvmanager);
195 tag += 3*FrontMtx_nfront(bridge->frontmtx) + 2 ;
196 if ( msglvl > 3 ) {
197 fprintf(msgFile, "\n\n numeric factorization") ;
198 FrontMtx_writeForHumanEye(bridge->frontmtx, bridge->msgFile) ;
199 fflush(bridge->msgFile) ;
200 }
201 /*
202 ----------------------------
203 if matrix is singular then
204 set error flag and return
205 ----------------------------
206 */
207 if ( rootchv != NULL ) {
208 fprintf(msgFile, "\n WHOA NELLY!, matrix is singular") ;
209 fflush(msgFile) ;
210 *perror = 1 ;
211 return ;
212 }
213 /*
214 ------------------------------------------------------------------
215 post-process the factor matrix, convert from fronts to submatrices
216 ------------------------------------------------------------------
217 */
218 FrontMtx_MPI_postProcess(bridge->frontmtx, bridge->ownersIV, stats,
219 bridge->msglvl, bridge->msgFile, tag, comm);
220 tag += 5*bridge->nproc ;
221 /*
222 -------------------
223 compute the inertia
224 -------------------
225 */
226 FrontMtx_inertia(bridge->frontmtx, &nnegative, &nzero, &npositive) ;
227 sendtemp[0] = nnegative ;
228 sendtemp[1] = nzero ;
229 sendtemp[2] = npositive ;
230 if ( bridge->msglvl > 2 && bridge->msgFile != NULL ) {
231 fprintf(bridge->msgFile, "\n local inertia = < %d, %d, %d >",
232 nnegative, nzero, npositive) ;
233 fflush(bridge->msgFile) ;
234 }
235 MPI_Allreduce((void *) sendtemp, (void *) recvtemp, 3, MPI_INT,
236 MPI_SUM, comm) ;
237 nnegative = recvtemp[0] ;
238 nzero = recvtemp[1] ;
239 npositive = recvtemp[2] ;
240 if ( bridge->msglvl > 2 && bridge->msgFile != NULL ) {
241 fprintf(bridge->msgFile, "\n global inertia = < %d, %d, %d >",
242 nnegative, nzero, npositive) ;
243 fflush(bridge->msgFile) ;
244 }
245 *pinertia = nnegative;
246 /*
247 ---------------------------
248 create the solve map object
249 ---------------------------
250 */
251 SolveMap_ddMap(bridge->solvemap, SPOOLES_REAL,
252 FrontMtx_upperBlockIVL(bridge->frontmtx),
253 FrontMtx_lowerBlockIVL(bridge->frontmtx), nproc,
254 bridge->ownersIV, FrontMtx_frontTree(bridge->frontmtx),
255 bridge->seed, bridge->msglvl, bridge->msgFile) ;
256 /*
257 -------------------------------
258 redistribute the front matrices
259 -------------------------------
260 */
261 FrontMtx_MPI_split(bridge->frontmtx, bridge->solvemap, stats,
262 bridge->msglvl, bridge->msgFile, tag, comm) ;
263 if ( *ppvttol != 0.0 ) {
264 /*
265 -------------------------------------------------------------
266 pivoting for stability may have taken place. create rowmapIV,
267 the map from rows in the factorization to processes.
268 -------------------------------------------------------------
269 */
270 bridge->rowmapIV = FrontMtx_MPI_rowmapIV(bridge->frontmtx,
271 bridge->ownersIV, bridge->msglvl,
272 bridge->msgFile, bridge->comm) ;
273 if ( bridge->msglvl > 2 && bridge->msgFile != NULL ) {
274 fprintf(bridge->msgFile, "\n\n bridge->rowmapIV") ;
275 IV_writeForHumanEye(bridge->rowmapIV, bridge->msgFile) ;
276 fflush(bridge->msgFile) ;
277 }
278 } else {
279 bridge->rowmapIV = NULL ;
280 }
281 /*
282 ------------------------------------------------------------------
283 set the error. (this is simple since when the spooles codes detect
284 a fatal error, they print out a message to stderr and exit.)
285 ------------------------------------------------------------------
286 */
287 *perror = 0 ;
288
289 #if MYDEBUG > 0
290 MARKTIME(t2) ;
291 time_Factor += t2 - t1 ;
292 if ( bridge->myid == 0 ) {
293 fprintf(stdout, ", %8.3f seconds, %8.3f total time",
294 t2 - t1, time_Factor) ;
295 fflush(stdout) ;
296 }
297 #endif
298 #if MYDEBUG > 1
299 fprintf(bridge->msgFile, ", %8.3f seconds, %8.3f total time",
300 t2 - t1, time_Factor) ;
301 fflush(bridge->msgFile) ;
302 #endif
303
304 return; }
305
306 /*--------------------------------------------------------------------*/
307