Ice Sheet System Model  4.18
Code documentation
MpiDenseMumpsSolve.cpp
Go to the documentation of this file.
1 
5 /*Header files: */
6 #ifdef HAVE_CONFIG_H
7  #include <config.h>
8 #else
9 #error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
10 #endif
11 
12 #include "../../shared/Numerics/types.h"
13 #include "../../shared/MemOps/MemOps.h"
14 #include "../../shared/Exceptions/exceptions.h"
15 #include "../../shared/io/Comm/IssmComm.h"
16 #include "../../classes/Params/GenericParam.h"
17 #include "../../classes/Params/Parameters.h"
18 #include "../mpi/issmmpi.h"
19 #include "../adolc/adolcincludes.h"
20 #include "./mumpsincludes.h"
21 
22 /*Mumps header files: */
23 #include <dmumps_c.h>
24 
25 void MumpsInit(DMUMPS_STRUC_C &theMumpsStruc){
26  theMumpsStruc.par = 1;
27  theMumpsStruc.sym = 0;
28  theMumpsStruc.comm_fortran = MPI_Comm_c2f(IssmComm::GetComm());
29  theMumpsStruc.job = -1;
30  dmumps_c(&theMumpsStruc);
31 }
32 
33 // must be preceded by a call to MumpsInit
34 void MumpsSettings(DMUMPS_STRUC_C &theMumpsStruc) {
35  /*Control statements:{{{ */
36  theMumpsStruc.icntl[1-1] = 6; //error verbose: default 6, 0 or negative -> suppressed
37  theMumpsStruc.icntl[2-1] = 0; //std verbose: default 1, 0 or negative -> suppressed
38  theMumpsStruc.icntl[3-1] = 0; //global information verbose: default 6, 0 or negative -> suppressed
39  theMumpsStruc.icntl[4-1] = 0; //verbose everything: default is 4
40  theMumpsStruc.icntl[5-1] = 0;
41  theMumpsStruc.icntl[18-1] = 3;
42 
43  theMumpsStruc.icntl[20-1] = 0;
44  theMumpsStruc.icntl[21-1] = 0;
45  theMumpsStruc.icntl[30-1] = 0;
46  /*}}}*/
47 }
48 
49 // must be preceded by a call to MumpsInit
50 void MumpsAnalyze(DMUMPS_STRUC_C &theMumpsStruc) {
51  theMumpsStruc.job = 1;
52  dmumps_c(&theMumpsStruc);
53 }
54 
55 // must be preceded by a call to MumpsAnalyze
56 void MumpsFactorize(DMUMPS_STRUC_C &theMumpsStruc) {
57  theMumpsStruc.job = 2;
58  dmumps_c(&theMumpsStruc);
59 }
60 
61 // must be preceded by a call to MumpsFactorize
62 void MumpsBacksubstitute(DMUMPS_STRUC_C &theMumpsStruc) {
63  theMumpsStruc.job = 3;
64  dmumps_c(&theMumpsStruc);
65 }
66 
67 // must be preceded at least by a call to MumpsInit
68 void MumpsFinalize(DMUMPS_STRUC_C &theMumpsStruc) {
69  theMumpsStruc.job = -2;
70  dmumps_c(&theMumpsStruc);
71 }
72 
73 void MumpsSolve(int n,int nnz,int local_nnz,int* irn_loc,int* jcn_loc, IssmPDouble *a_loc, IssmPDouble *rhs, Parameters* parameters=0 /*unused here*/){
74  /*Initialize mumps*/
75  DMUMPS_STRUC_C theMumpsStruc;
76  MumpsInit(theMumpsStruc);
77  MumpsSettings(theMumpsStruc);
78 
79  /*now setup the rest of theMumpsStruc */
80  theMumpsStruc.n=n;
81  theMumpsStruc.nz=nnz;
82  theMumpsStruc.nz_loc=local_nnz;
83  theMumpsStruc.irn_loc=irn_loc;
84  theMumpsStruc.jcn_loc=jcn_loc;
85  theMumpsStruc.a_loc=a_loc;
86  theMumpsStruc.rhs=rhs;
87  theMumpsStruc.nrhs=1;
88  theMumpsStruc.lrhs=1;
89 
90  /*Solve system*/
91  MumpsAnalyze(theMumpsStruc);
92  MumpsFactorize(theMumpsStruc);
93  MumpsBacksubstitute(theMumpsStruc);
94  MumpsFinalize(theMumpsStruc);
95 }
96 
97 #ifdef _HAVE_ADOLC_
98 // prototype for active variant
99 void MumpsSolve(int n,
100  int nnz,
101  int local_nnz,
102  int* irn_loc,
103  int* jcn_loc,
104  IssmDouble *a_loc,
105  IssmDouble *rhs,
106  Parameters* parameters);
107 #endif
108 
109 void MpiDenseMumpsSolve( /*output: */ IssmDouble* uf, int uf_M, int uf_m, /*matrix input: */ IssmDouble* Kff, int Kff_M, int Kff_N, int Kff_m, /*right hand side vector: */ IssmDouble* pf, int pf_M, int pf_m, Parameters* parameters){ /*{{{*/
110 
111  /*Variables*/
112  ISSM_MPI_Comm comm;
113  int num_procs;
114  int i,j;
115  int nnz,local_nnz;
116  int *irn_loc = NULL;
117  int *jcn_loc = NULL;
118  IssmDouble *a_loc = NULL;
119  int count;
120  int lower_row;
121  int upper_row;
122  IssmDouble *rhs = NULL;
123  int *recvcounts = NULL;
124  int *displs = NULL;
125 
126  /*Communicator info */
127  num_procs = IssmComm::GetSize();
128  comm = IssmComm::GetComm();
129 
130  /*First, some checks*/
131  if (Kff_M!=Kff_N)_error_("stiffness matrix Kff should be square");
132  if (uf_M!=Kff_M || uf_M!=pf_M)_error_("solution vector should be the same size as stiffness matrix Kff and load vector pf");
133  if (uf_m!=Kff_m || uf_m!=pf_m)_error_("solution vector should be locally the same size as stiffness matrix Kff and load vector pf");
134 
135  /*Initialize matrix */
136  /*figure out number of non-zero entries: */
137  local_nnz=0;
138  for(i=0;i<Kff_m;i++){
139  for(j=0;j<Kff_N;j++){
140  if (Kff[i*Kff_N+j]!=0)local_nnz++;
141  }
142  }
143 
144  ISSM_MPI_Reduce(&local_nnz,&nnz,1,ISSM_MPI_INT,ISSM_MPI_SUM,0,comm);
145  ISSM_MPI_Bcast(&nnz,1,ISSM_MPI_INT,0,comm);
146 
147  /*Allocate: */
148  if(local_nnz){
149  irn_loc=xNew<int>(local_nnz);
150  jcn_loc=xNew<int>(local_nnz);
151  a_loc=xNew<IssmDouble>(local_nnz);
152  }
153 
154  /*Populate the triplets: */
155  GetOwnershipBoundariesFromRange(&lower_row,&upper_row,Kff_m,comm);
156  count=0;
157  for(i=0;i<Kff_m;i++){
158  for(j=0;j<Kff_N;j++){
159  if (Kff[i*Kff_N+j]!=0){
160  irn_loc[count]=lower_row+i+1; //fortran indexing
161  jcn_loc[count]=j+1; //fortran indexing
162  a_loc[count]=Kff[i*Kff_N+j];
163  count++;
164  }
165  }
166  }
167  /*Deal with right hand side. We need to ISSM_MPI_Gather it onto cpu 0: */
168  rhs=xNew<IssmDouble>(pf_M);
169 
170  recvcounts=xNew<int>(num_procs);
171  displs=xNew<int>(num_procs);
172 
173  /*recvcounts:*/
174  ISSM_MPI_Allgather(&pf_m,1,ISSM_MPI_INT,recvcounts,1,ISSM_MPI_INT,comm);
175 
176  /*displs: */
177  ISSM_MPI_Allgather(&lower_row,1,ISSM_MPI_INT,displs,1,ISSM_MPI_INT,comm);
178 
179  /*Gather:*/
180  ISSM_MPI_Gatherv(pf, pf_m, ISSM_MPI_DOUBLE, rhs, recvcounts, displs, ISSM_MPI_DOUBLE,0,comm);
181 
182  MumpsSolve(Kff_M,nnz,local_nnz,irn_loc,jcn_loc,a_loc,rhs,parameters);
183 
184  /*Now scatter from cpu 0 to all other cpus*/
185  ISSM_MPI_Scatterv( rhs, recvcounts, displs, ISSM_MPI_DOUBLE, uf, uf_m, ISSM_MPI_DOUBLE, 0, comm);
186 
187  /*Cleanup*/
188  xDelete<int>(irn_loc);
189  xDelete<int>(jcn_loc);
190  xDelete<IssmDouble>(a_loc);
191  xDelete<IssmDouble>(rhs);
192  xDelete<int>(recvcounts);
193  xDelete<int>(displs);
194 } /*}}}*/
195 
196 #ifdef _HAVE_ADOLC_
197 
198 int mumpsSolveEDF(int iArrLength, int* iArr, int /* ignored */, IssmPDouble* dp_x, int /* ignored */, IssmPDouble* dp_y) {
199  // unpack parameters
200  int n=iArr[0];
201  int nnz=iArr[1];
202  int local_nnz=iArr[2];
203  int *local_irn=xNew<int>(local_nnz);
204  int *local_jcn=xNew<int>(local_nnz);
205  IssmPDouble *A=xNew<IssmPDouble>(local_nnz);
206  for (int i=0;i<local_nnz;++i) {
207  local_irn[i]=iArr[3+i];
208  local_jcn[i]=iArr[3+local_nnz+i];
209  A[i]=dp_x[i];
210  }
211  IssmPDouble *rhs_sol=xNew<IssmPDouble>(n);
212  for (int i=0;i<n;++i) {
213  rhs_sol[i]=dp_x[local_nnz+i];
214  }
215  MumpsSolve(n,nnz,local_nnz,local_irn,local_jcn,A,rhs_sol);
216  for (int i=0;i<n;++i) {
217  dp_y[i]=rhs_sol[i];
218  }
219  xDelete(rhs_sol);
220  xDelete(A);
221  xDelete(local_jcn);
222  xDelete(local_irn);
223  return 0;
224 }
225 
226 void MumpsSolve(int n,int nnz,int local_nnz,int* irn_loc,int* jcn_loc,IssmDouble *a_loc,IssmDouble *rhs,Parameters* parameters){
227  int packedDimsSparseArrLength=1+1+1+local_nnz+local_nnz;
228  int *packedDimsSparseArr=xNew<int>(packedDimsSparseArrLength);
229  packedDimsSparseArr[0]=n;
230  packedDimsSparseArr[1]=nnz;
231  packedDimsSparseArr[2]=local_nnz;
232  for (int i=0;i<local_nnz;++i) {
233  packedDimsSparseArr[3+i]=irn_loc[i];
234  packedDimsSparseArr[3+local_nnz+i]=jcn_loc[i];
235  }
236  IssmDouble *pack_A_rhs=xNew<IssmDouble>(local_nnz+n);
237  for (int i=0;i<local_nnz;++i) {
238  pack_A_rhs[i]=a_loc[i];
239  }
240  for (int i=0;i<n;++i) {
241  pack_A_rhs[local_nnz+i]=rhs[i];
242  }
243  IssmPDouble *passivePack_A_rhs=xNew<IssmPDouble>(local_nnz+n);
244  IssmPDouble *passiveSol=xNew<IssmPDouble>(n);
245  IssmDouble *sol=xNew<IssmDouble>(n);
246  call_ext_fct(xDynamicCast<GenericParam<Adolc_edf> * >(parameters->FindParamObject(AdolcParamEnum))->GetParameterValue().myEDF_for_solverx_p,
247  packedDimsSparseArrLength, packedDimsSparseArr,
248  local_nnz+n, passivePack_A_rhs, pack_A_rhs,
249  n, passiveSol,sol);
250  for (int i=0;i<n;++i) {
251  rhs[i]=sol[i];
252  }
253  xDelete(sol);
254  xDelete(passiveSol);
255  xDelete(passivePack_A_rhs);
256  xDelete(pack_A_rhs);
257  xDelete(packedDimsSparseArr);
258 }
259 
260 int fos_reverse_mumpsSolveEDF(int iArrLength, int* iArr,
261  int m, IssmPDouble *dp_U,
262  int nPlusNz, IssmPDouble *dp_Z,
263  IssmPDouble *dp_x, IssmPDouble *dp_y) {
264  // unpack parameters
265  int n=iArr[0];
266  int nnz=iArr[1];
267  int local_nnz=iArr[2];
268  int *local_irn=xNew<int>(local_nnz);
269  int *local_jcn=xNew<int>(local_nnz);
270  IssmPDouble *a_loc=xNew<IssmPDouble>(local_nnz);
271  for (int i=0;i<local_nnz;++i) {
272  local_irn[i]=iArr[3+i];
273  local_jcn[i]=iArr[3+local_nnz+i];
274  a_loc[i]=dp_x[i];
275  }
276  IssmPDouble *rhs_sol=xNew<IssmPDouble>(n);
277  for (int i=0;i<n;++i) {
278  rhs_sol[i]=dp_U[i];
279  }
280  DMUMPS_STRUC_C theMumpsStruc;
281  MumpsInit(theMumpsStruc);
282  MumpsSettings(theMumpsStruc);
283  theMumpsStruc.n=n;
284  theMumpsStruc.nz=nnz;
285  theMumpsStruc.nz_loc=local_nnz;
286  theMumpsStruc.irn_loc=local_irn;
287  theMumpsStruc.jcn_loc=local_jcn;
288  theMumpsStruc.a_loc=a_loc;
289  theMumpsStruc.rhs=rhs_sol;
290  theMumpsStruc.nrhs=1;
291  theMumpsStruc.lrhs=1;
292  theMumpsStruc.icntl[9-1] = 0; //solve for the transpose
293  MumpsAnalyze(theMumpsStruc);
294  MumpsFactorize(theMumpsStruc);
295  MumpsBacksubstitute(theMumpsStruc);
296  MumpsFinalize(theMumpsStruc);
297  // update the adjoint of the rhs:
298  for (int i=0;i<n;++i) {
299  dp_Z[local_nnz+i]+=rhs_sol[i];
300  }
301  // bcast dp_y (the solution of the forward system)
303  // bcast the adjoint of the right-hand-side, i.e. this solution
305  // update the adjoint of the matrix with the outer product of right-hand-side adjoint and the original solution
306  for (int i=0;i<local_nnz;++i) {
307  dp_Z[i]-=rhs_sol[iArr[3+i]-1]*dp_y[iArr[3+local_nnz+i]-1];
308  }
309  xDelete(rhs_sol);
310  xDelete(a_loc);
311  xDelete(local_jcn);
312  xDelete(local_irn);
313  return 3;
314 }
315 
316 #endif
xDynamicCast
To xDynamicCast(const From &from)
Definition: recast.h:51
IssmDouble
double IssmDouble
Definition: types.h:37
MumpsAnalyze
void MumpsAnalyze(DMUMPS_STRUC_C &theMumpsStruc)
Definition: MpiDenseMumpsSolve.cpp:50
mumpsincludes.h
ISSM_MPI_Gatherv
int ISSM_MPI_Gatherv(void *sendbuf, int sendcnt, ISSM_MPI_Datatype sendtype, void *recvbuf, int *recvcnts, int *displs, ISSM_MPI_Datatype recvtype, int root, ISSM_MPI_Comm comm)
Definition: issmmpi.cpp:279
Parameters
Declaration of Parameters class.
Definition: Parameters.h:18
ISSM_MPI_SUM
#define ISSM_MPI_SUM
Definition: issmmpi.h:134
IssmComm::GetComm
static ISSM_MPI_Comm GetComm(void)
Definition: IssmComm.cpp:30
GetOwnershipBoundariesFromRange
void GetOwnershipBoundariesFromRange(int *plower_row, int *pupper_row, int range, ISSM_MPI_Comm comm)
Definition: GetOwnershipBoundariesFromRange.cpp:16
ISSM_MPI_DOUBLE
#define ISSM_MPI_DOUBLE
Definition: issmmpi.h:125
ISSM_MPI_INT
#define ISSM_MPI_INT
Definition: issmmpi.h:127
GenericParam::GetParameterValue
P & GetParameterValue()
Definition: GenericParam.h:62
xDelete
void xDelete(T **&aT_pp)
Definition: MemOps.h:97
IssmComm::GetSize
static int GetSize(void)
Definition: IssmComm.cpp:46
MumpsInit
void MumpsInit(DMUMPS_STRUC_C &theMumpsStruc)
Definition: MpiDenseMumpsSolve.cpp:25
ISSM_MPI_PDOUBLE
#define ISSM_MPI_PDOUBLE
Definition: issmmpi.h:126
ISSM_MPI_Bcast
int ISSM_MPI_Bcast(void *buffer, int count, ISSM_MPI_Datatype datatype, int root, ISSM_MPI_Comm comm)
Definition: issmmpi.cpp:162
ISSM_MPI_Allgather
int ISSM_MPI_Allgather(void *sendbuf, int sendcount, ISSM_MPI_Datatype sendtype, void *recvbuf, int recvcount, ISSM_MPI_Datatype recvtype, ISSM_MPI_Comm comm)
Definition: issmmpi.cpp:45
MpiDenseMumpsSolve
void MpiDenseMumpsSolve(IssmDouble *uf, int uf_M, int uf_m, IssmDouble *Kff, int Kff_M, int Kff_N, int Kff_m, IssmDouble *pf, int pf_M, int pf_m, Parameters *parameters)
Definition: MpiDenseMumpsSolve.cpp:109
_error_
#define _error_(StreamArgs)
Definition: exceptions.h:49
ISSM_MPI_Comm
int ISSM_MPI_Comm
Definition: issmmpi.h:118
AdolcParamEnum
@ AdolcParamEnum
Definition: EnumDefinitions.h:12
MumpsBacksubstitute
void MumpsBacksubstitute(DMUMPS_STRUC_C &theMumpsStruc)
Definition: MpiDenseMumpsSolve.cpp:62
MumpsFinalize
void MumpsFinalize(DMUMPS_STRUC_C &theMumpsStruc)
Definition: MpiDenseMumpsSolve.cpp:68
MumpsSettings
void MumpsSettings(DMUMPS_STRUC_C &theMumpsStruc)
Definition: MpiDenseMumpsSolve.cpp:34
ISSM_MPI_Reduce
int ISSM_MPI_Reduce(void *sendbuf, void *recvbuf, int count, ISSM_MPI_Datatype datatype, ISSM_MPI_Op op, int root, ISSM_MPI_Comm comm)
Definition: issmmpi.cpp:373
MumpsFactorize
void MumpsFactorize(DMUMPS_STRUC_C &theMumpsStruc)
Definition: MpiDenseMumpsSolve.cpp:56
IssmPDouble
IssmDouble IssmPDouble
Definition: types.h:38
Parameters::FindParamObject
Param * FindParamObject(int enum_type)
Definition: Parameters.cpp:588
MumpsSolve
void MumpsSolve(int n, int nnz, int local_nnz, int *irn_loc, int *jcn_loc, IssmPDouble *a_loc, IssmPDouble *rhs, Parameters *parameters=0)
Definition: MpiDenseMumpsSolve.cpp:73
ISSM_MPI_Scatterv
int ISSM_MPI_Scatterv(void *sendbuf, int *sendcnts, int *displs, ISSM_MPI_Datatype sendtype, void *recvbuf, int recvcnt, ISSM_MPI_Datatype recvtype, int root, ISSM_MPI_Comm comm)
Definition: issmmpi.cpp:444
GenericParam
Definition: GenericParam.h:26