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