xref: /petsc/src/ksp/pc/impls/bddc/bddcscalingbasic.c (revision e6e75211d226c622f451867f53ce5d558649ff4f)
1 #include <../src/ksp/pc/impls/bddc/bddc.h>
2 #include <../src/ksp/pc/impls/bddc/bddcprivate.h>
3 
4 /* prototypes for deluxe functions */
5 static PetscErrorCode PCBDDCScalingCreate_Deluxe(PC);
6 static PetscErrorCode PCBDDCScalingDestroy_Deluxe(PC);
7 static PetscErrorCode PCBDDCScalingSetUp_Deluxe(PC);
8 static PetscErrorCode PCBDDCScalingSetUp_Deluxe_Private(PC);
9 static PetscErrorCode PCBDDCScalingReset_Deluxe_Solvers(PCBDDCDeluxeScaling);
10 
11 #undef __FUNCT__
12 #define __FUNCT__ "PCBDDCScalingExtension_Basic"
13 static PetscErrorCode PCBDDCScalingExtension_Basic(PC pc, Vec local_interface_vector, Vec global_vector)
14 {
15   PC_IS*         pcis = (PC_IS*)pc->data;
16   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
17   PetscErrorCode ierr;
18 
19   PetscFunctionBegin;
20   /* Apply partition of unity */
21   ierr = VecPointwiseMult(pcbddc->work_scaling,pcis->D,local_interface_vector);CHKERRQ(ierr);
22   ierr = VecSet(global_vector,0.0);CHKERRQ(ierr);
23   ierr = VecScatterBegin(pcis->global_to_B,pcbddc->work_scaling,global_vector,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24   ierr = VecScatterEnd(pcis->global_to_B,pcbddc->work_scaling,global_vector,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
25   PetscFunctionReturn(0);
26 }
27 
28 #undef __FUNCT__
29 #define __FUNCT__ "PCBDDCScalingExtension_Deluxe"
30 static PetscErrorCode PCBDDCScalingExtension_Deluxe(PC pc, Vec x, Vec y)
31 {
32   PC_IS*              pcis=(PC_IS*)pc->data;
33   PC_BDDC*            pcbddc=(PC_BDDC*)pc->data;
34   PCBDDCDeluxeScaling deluxe_ctx = pcbddc->deluxe_ctx;
35   PetscErrorCode      ierr;
36 
37   PetscFunctionBegin;
38   ierr = VecSet(pcbddc->work_scaling,0.0);CHKERRQ(ierr);
39   ierr = VecSet(y,0.0);CHKERRQ(ierr);
40   if (deluxe_ctx->n_simple) { /* scale deluxe vertices using diagonal scaling */
41     PetscInt          i;
42     const PetscScalar *array_x,*array_D;
43     PetscScalar       *array;
44     ierr = VecGetArrayRead(x,&array_x);CHKERRQ(ierr);
45     ierr = VecGetArrayRead(pcis->D,&array_D);CHKERRQ(ierr);
46     ierr = VecGetArray(pcbddc->work_scaling,&array);CHKERRQ(ierr);
47     for (i=0;i<deluxe_ctx->n_simple;i++) {
48       array[deluxe_ctx->idx_simple_B[i]] = array_x[deluxe_ctx->idx_simple_B[i]]*array_D[deluxe_ctx->idx_simple_B[i]];
49     }
50     ierr = VecRestoreArray(pcbddc->work_scaling,&array);CHKERRQ(ierr);
51     ierr = VecRestoreArrayRead(pcis->D,&array_D);CHKERRQ(ierr);
52     ierr = VecRestoreArrayRead(x,&array_x);CHKERRQ(ierr);
53   }
54   /* sequential part : all problems and Schur applications collapsed into a single matrix vector multiplication or a matvec and a solve */
55   if (deluxe_ctx->seq_mat) {
56     ierr = VecScatterBegin(deluxe_ctx->seq_scctx,x,deluxe_ctx->seq_work1,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
57     ierr = VecScatterEnd(deluxe_ctx->seq_scctx,x,deluxe_ctx->seq_work1,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
58     ierr = MatMultTranspose(deluxe_ctx->seq_mat,deluxe_ctx->seq_work1,deluxe_ctx->seq_work2);CHKERRQ(ierr);
59     if (deluxe_ctx->seq_ksp) {
60       ierr = KSPSolveTranspose(deluxe_ctx->seq_ksp,deluxe_ctx->seq_work2,deluxe_ctx->seq_work2);CHKERRQ(ierr);
61     }
62     ierr = VecScatterBegin(deluxe_ctx->seq_scctx,deluxe_ctx->seq_work2,pcbddc->work_scaling,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
63     ierr = VecScatterEnd(deluxe_ctx->seq_scctx,deluxe_ctx->seq_work2,pcbddc->work_scaling,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
64   }
65   /* put local boundary part in global vector */
66   ierr = VecScatterBegin(pcis->global_to_B,pcbddc->work_scaling,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
67   ierr = VecScatterEnd(pcis->global_to_B,pcbddc->work_scaling,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
68   PetscFunctionReturn(0);
69 }
70 
71 #undef __FUNCT__
72 #define __FUNCT__ "PCBDDCScalingExtension"
73 PetscErrorCode PCBDDCScalingExtension(PC pc, Vec local_interface_vector, Vec global_vector)
74 {
75   PC_BDDC *pcbddc=(PC_BDDC*)pc->data;
76   PetscErrorCode ierr;
77 
78   PetscFunctionBegin;
79   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
80   PetscValidHeaderSpecific(local_interface_vector,VEC_CLASSID,2);
81   PetscValidHeaderSpecific(global_vector,VEC_CLASSID,3);
82   if (local_interface_vector == pcbddc->work_scaling) {
83     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local vector cannot be pcbddc->work_scaling!\n");
84   }
85   ierr = PetscTryMethod(pc,"PCBDDCScalingExtension_C",(PC,Vec,Vec),(pc,local_interface_vector,global_vector));CHKERRQ(ierr);
86   PetscFunctionReturn(0);
87 }
88 
89 #undef __FUNCT__
90 #define __FUNCT__ "PCBDDCScalingRestriction_Basic"
91 static PetscErrorCode PCBDDCScalingRestriction_Basic(PC pc, Vec global_vector, Vec local_interface_vector)
92 {
93   PetscErrorCode ierr;
94   PC_IS* pcis = (PC_IS*)pc->data;
95 
96   PetscFunctionBegin;
97   ierr = VecScatterBegin(pcis->global_to_B,global_vector,local_interface_vector,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
98   ierr = VecScatterEnd(pcis->global_to_B,global_vector,local_interface_vector,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
99   /* Apply partition of unity */
100   ierr = VecPointwiseMult(local_interface_vector,pcis->D,local_interface_vector);CHKERRQ(ierr);
101   PetscFunctionReturn(0);
102 }
103 
104 #undef __FUNCT__
105 #define __FUNCT__ "PCBDDCScalingRestriction_Deluxe"
106 static PetscErrorCode PCBDDCScalingRestriction_Deluxe(PC pc, Vec x, Vec y)
107 {
108   PC_IS*              pcis=(PC_IS*)pc->data;
109   PC_BDDC*            pcbddc=(PC_BDDC*)pc->data;
110   PCBDDCDeluxeScaling deluxe_ctx = pcbddc->deluxe_ctx;
111   PetscErrorCode      ierr;
112 
113   PetscFunctionBegin;
114   /* get local boundary part of global vector */
115   ierr = VecScatterBegin(pcis->global_to_B,x,y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
116   ierr = VecScatterEnd(pcis->global_to_B,x,y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
117   if (deluxe_ctx->n_simple) { /* scale deluxe vertices using diagonal scaling */
118     PetscInt          i;
119     PetscScalar       *array_y;
120     const PetscScalar *array_D;
121     ierr = VecGetArray(y,&array_y);CHKERRQ(ierr);
122     ierr = VecGetArrayRead(pcis->D,&array_D);CHKERRQ(ierr);
123     for (i=0;i<deluxe_ctx->n_simple;i++) {
124       array_y[deluxe_ctx->idx_simple_B[i]] *= array_D[deluxe_ctx->idx_simple_B[i]];
125     }
126     ierr = VecRestoreArrayRead(pcis->D,&array_D);CHKERRQ(ierr);
127     ierr = VecRestoreArray(y,&array_y);CHKERRQ(ierr);
128   }
129   /* sequential part : all problems and Schur applications collapsed into a single matrix vector multiplication and ksp solution */
130   if (deluxe_ctx->seq_mat) {
131     ierr = VecScatterBegin(deluxe_ctx->seq_scctx,y,deluxe_ctx->seq_work1,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
132     ierr = VecScatterEnd(deluxe_ctx->seq_scctx,y,deluxe_ctx->seq_work1,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
133     if (deluxe_ctx->seq_ksp) {
134       ierr = KSPSolve(deluxe_ctx->seq_ksp,deluxe_ctx->seq_work1,deluxe_ctx->seq_work1);CHKERRQ(ierr);
135     }
136     ierr = MatMult(deluxe_ctx->seq_mat,deluxe_ctx->seq_work1,deluxe_ctx->seq_work2);CHKERRQ(ierr);
137     ierr = VecScatterBegin(deluxe_ctx->seq_scctx,deluxe_ctx->seq_work2,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
138     ierr = VecScatterEnd(deluxe_ctx->seq_scctx,deluxe_ctx->seq_work2,y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
139   }
140   PetscFunctionReturn(0);
141 }
142 
143 #undef __FUNCT__
144 #define __FUNCT__ "PCBDDCScalingRestriction"
145 PetscErrorCode PCBDDCScalingRestriction(PC pc, Vec global_vector, Vec local_interface_vector)
146 {
147   PC_BDDC        *pcbddc=(PC_BDDC*)pc->data;
148   PetscErrorCode ierr;
149 
150   PetscFunctionBegin;
151   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
152   PetscValidHeaderSpecific(global_vector,VEC_CLASSID,2);
153   PetscValidHeaderSpecific(local_interface_vector,VEC_CLASSID,3);
154   if (local_interface_vector == pcbddc->work_scaling) {
155     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local vector cannot be pcbddc->work_scaling!\n");
156   }
157   ierr = PetscTryMethod(pc,"PCBDDCScalingRestriction_C",(PC,Vec,Vec),(pc,global_vector,local_interface_vector));CHKERRQ(ierr);
158   PetscFunctionReturn(0);
159 }
160 
161 #undef __FUNCT__
162 #define __FUNCT__ "PCBDDCScalingSetUp"
163 PetscErrorCode PCBDDCScalingSetUp(PC pc)
164 {
165   PC_IS*         pcis=(PC_IS*)pc->data;
166   PC_BDDC*       pcbddc=(PC_BDDC*)pc->data;
167   PetscErrorCode ierr;
168 
169   PetscFunctionBegin;
170   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
171   /* create work vector for the operator */
172   ierr = VecDestroy(&pcbddc->work_scaling);CHKERRQ(ierr);
173   ierr = VecDuplicate(pcis->vec1_B,&pcbddc->work_scaling);CHKERRQ(ierr);
174   /* always rebuild pcis->D */
175   if (pcis->use_stiffness_scaling) {
176     ierr = MatGetDiagonal(pcbddc->local_mat,pcis->vec1_N);CHKERRQ(ierr);
177     ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_N,pcis->D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
178     ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_N,pcis->D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
179   }
180   ierr = VecCopy(pcis->D,pcis->vec1_B);CHKERRQ(ierr);
181   ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
182   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
183   ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
184   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_global,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
185   ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_global,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
186   ierr = VecPointwiseDivide(pcis->D,pcis->D,pcis->vec1_B);CHKERRQ(ierr);
187   /* now setup */
188   if (pcbddc->use_deluxe_scaling) {
189     if (!pcbddc->deluxe_ctx) {
190       ierr = PCBDDCScalingCreate_Deluxe(pc);CHKERRQ(ierr);
191     }
192     ierr = PCBDDCScalingSetUp_Deluxe(pc);CHKERRQ(ierr);
193     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCScalingRestriction_C",PCBDDCScalingRestriction_Deluxe);CHKERRQ(ierr);
194     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCScalingExtension_C",PCBDDCScalingExtension_Deluxe);CHKERRQ(ierr);
195   } else {
196     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCScalingRestriction_C",PCBDDCScalingRestriction_Basic);CHKERRQ(ierr);
197     ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCScalingExtension_C",PCBDDCScalingExtension_Basic);CHKERRQ(ierr);
198   }
199 
200   /* test */
201   if (pcbddc->dbg_flag) {
202     Vec         vec2_global;
203     PetscViewer viewer=pcbddc->dbg_viewer;
204     PetscReal   error;
205 
206     /* extension -> from local to parallel */
207     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
208     ierr = VecSetRandom(pcis->vec1_B,NULL);CHKERRQ(ierr);
209     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
210     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
211     ierr = VecDuplicate(pcis->vec1_global,&vec2_global);CHKERRQ(ierr);
212     ierr = VecCopy(pcis->vec1_global,vec2_global);CHKERRQ(ierr);
213 
214     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_global,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
215     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_global,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
216     ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,pcis->vec1_global);CHKERRQ(ierr);
217     ierr = VecAXPY(pcis->vec1_global,-1.0,vec2_global);CHKERRQ(ierr);
218     ierr = VecNorm(pcis->vec1_global,NORM_INFINITY,&error);CHKERRQ(ierr);
219     ierr = PetscViewerASCIIPrintf(viewer,"Error scaling extension %1.14e\n",error);CHKERRQ(ierr);
220     if (error>1.e-8 && pcbddc->dbg_flag>1) {
221       ierr = VecView(pcis->vec1_global,viewer);CHKERRQ(ierr);
222     }
223     ierr = VecDestroy(&vec2_global);CHKERRQ(ierr);
224 
225     /* restriction -> from parallel to local */
226     ierr = VecSet(pcis->vec1_global,0.0);CHKERRQ(ierr);
227     ierr = VecSetRandom(pcis->vec1_B,NULL);CHKERRQ(ierr);
228     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
229     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
230 
231     ierr = PCBDDCScalingRestriction(pc,pcis->vec1_global,pcis->vec1_B);CHKERRQ(ierr);
232     ierr = VecScale(pcis->vec1_B,-1.0);CHKERRQ(ierr);
233     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
234     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,pcis->vec1_global,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
235     ierr = VecNorm(pcis->vec1_global,NORM_INFINITY,&error);CHKERRQ(ierr);
236     ierr = PetscViewerASCIIPrintf(viewer,"Error scaling restriction %1.14e\n",error);CHKERRQ(ierr);
237     if (error>1.e-8 && pcbddc->dbg_flag>1) {
238       ierr = VecView(pcis->vec1_global,viewer);CHKERRQ(ierr);
239     }
240   }
241   PetscFunctionReturn(0);
242 }
243 
244 #undef __FUNCT__
245 #define __FUNCT__ "PCBDDCScalingDestroy"
246 PetscErrorCode PCBDDCScalingDestroy(PC pc)
247 {
248   PC_BDDC* pcbddc=(PC_BDDC*)pc->data;
249   PetscErrorCode ierr;
250 
251   PetscFunctionBegin;
252   if (pcbddc->deluxe_ctx) {
253     ierr = PCBDDCScalingDestroy_Deluxe(pc);CHKERRQ(ierr);
254   }
255   ierr = VecDestroy(&pcbddc->work_scaling);CHKERRQ(ierr);
256   /* remove functions */
257   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCScalingRestriction_C",NULL);CHKERRQ(ierr);
258   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCScalingExtension_C",NULL);CHKERRQ(ierr);
259   PetscFunctionReturn(0);
260 }
261 
262 #undef __FUNCT__
263 #define __FUNCT__ "PCBDDCScalingCreate_Deluxe"
264 static PetscErrorCode PCBDDCScalingCreate_Deluxe(PC pc)
265 {
266   PC_BDDC*            pcbddc=(PC_BDDC*)pc->data;
267   PCBDDCDeluxeScaling deluxe_ctx;
268   PetscErrorCode      ierr;
269 
270   PetscFunctionBegin;
271   ierr = PetscNew(&deluxe_ctx);CHKERRQ(ierr);
272   pcbddc->deluxe_ctx = deluxe_ctx;
273   PetscFunctionReturn(0);
274 }
275 
276 #undef __FUNCT__
277 #define __FUNCT__ "PCBDDCScalingDestroy_Deluxe"
278 static PetscErrorCode PCBDDCScalingDestroy_Deluxe(PC pc)
279 {
280   PC_BDDC*            pcbddc=(PC_BDDC*)pc->data;
281   PetscErrorCode      ierr;
282 
283   PetscFunctionBegin;
284   ierr = PCBDDCScalingReset_Deluxe_Solvers(pcbddc->deluxe_ctx);CHKERRQ(ierr);
285   ierr = PetscFree(pcbddc->deluxe_ctx);CHKERRQ(ierr);
286   PetscFunctionReturn(0);
287 }
288 
289 #undef __FUNCT__
290 #define __FUNCT__ "PCBDDCScalingReset_Deluxe_Solvers"
291 static PetscErrorCode PCBDDCScalingReset_Deluxe_Solvers(PCBDDCDeluxeScaling deluxe_ctx)
292 {
293   PetscErrorCode      ierr;
294 
295   PetscFunctionBegin;
296   ierr = PetscFree(deluxe_ctx->idx_simple_B);CHKERRQ(ierr);
297   deluxe_ctx->n_simple = 0;
298   ierr = VecScatterDestroy(&deluxe_ctx->seq_scctx);CHKERRQ(ierr);
299   ierr = VecDestroy(&deluxe_ctx->seq_work1);CHKERRQ(ierr);
300   ierr = VecDestroy(&deluxe_ctx->seq_work2);CHKERRQ(ierr);
301   ierr = MatDestroy(&deluxe_ctx->seq_mat);CHKERRQ(ierr);
302   ierr = KSPDestroy(&deluxe_ctx->seq_ksp);CHKERRQ(ierr);
303   PetscFunctionReturn(0);
304 }
305 
306 #undef __FUNCT__
307 #define __FUNCT__ "PCBDDCScalingSetUp_Deluxe"
308 static PetscErrorCode PCBDDCScalingSetUp_Deluxe(PC pc)
309 {
310   PC_IS               *pcis=(PC_IS*)pc->data;
311   PC_BDDC             *pcbddc=(PC_BDDC*)pc->data;
312   PCBDDCDeluxeScaling deluxe_ctx=pcbddc->deluxe_ctx;
313   PCBDDCSubSchurs     sub_schurs=pcbddc->sub_schurs;
314   PetscErrorCode      ierr;
315 
316   PetscFunctionBegin;
317   /* (TODO: reuse) throw away the solvers */
318   ierr = PCBDDCScalingReset_Deluxe_Solvers(deluxe_ctx);CHKERRQ(ierr);
319 
320   /* Compute data structures to solve sequential problems */
321   ierr = PCBDDCScalingSetUp_Deluxe_Private(pc);CHKERRQ(ierr);
322 
323   /* diagonal scaling on interface dofs not contained in cc */
324   if (sub_schurs->is_vertices || sub_schurs->is_dir) {
325     PetscInt n_com,n_dir;
326     n_com = 0;
327     if (sub_schurs->is_vertices) {
328       ierr = ISGetLocalSize(sub_schurs->is_vertices,&n_com);CHKERRQ(ierr);
329     }
330     n_dir = 0;
331     if (sub_schurs->is_dir) {
332       ierr = ISGetLocalSize(sub_schurs->is_dir,&n_dir);CHKERRQ(ierr);
333     }
334     deluxe_ctx->n_simple = n_dir + n_com;
335     ierr = PetscMalloc1(deluxe_ctx->n_simple,&deluxe_ctx->idx_simple_B);CHKERRQ(ierr);
336     if (sub_schurs->is_vertices) {
337       PetscInt       nmap;
338       const PetscInt *idxs;
339 
340       ierr = ISGetIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
341       ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_com,idxs,&nmap,deluxe_ctx->idx_simple_B);CHKERRQ(ierr);
342       if (nmap != n_com) {
343         SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error when mapping simply scaled dofs (is_vertices)! %d != %d",nmap,n_com);
344       }
345       ierr = ISRestoreIndices(sub_schurs->is_vertices,&idxs);CHKERRQ(ierr);
346     }
347     if (sub_schurs->is_dir) {
348       PetscInt       nmap;
349       const PetscInt *idxs;
350 
351       ierr = ISGetIndices(sub_schurs->is_dir,&idxs);CHKERRQ(ierr);
352       ierr = ISGlobalToLocalMappingApply(pcis->BtoNmap,IS_GTOLM_DROP,n_dir,idxs,&nmap,deluxe_ctx->idx_simple_B+n_com);CHKERRQ(ierr);
353       if (nmap != n_dir) {
354         SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Error when mapping simply scaled dofs (sub_schurs->is_dir)! %d != %d",nmap,n_dir);
355       }
356       ierr = ISRestoreIndices(sub_schurs->is_dir,&idxs);CHKERRQ(ierr);
357     }
358     ierr = PetscSortInt(deluxe_ctx->n_simple,deluxe_ctx->idx_simple_B);CHKERRQ(ierr);
359   } else {
360     deluxe_ctx->n_simple = 0;
361     deluxe_ctx->idx_simple_B = 0;
362   }
363   PetscFunctionReturn(0);
364 }
365 
366 #undef __FUNCT__
367 #define __FUNCT__ "PCBDDCScalingSetUp_Deluxe_Private"
368 static PetscErrorCode PCBDDCScalingSetUp_Deluxe_Private(PC pc)
369 {
370   PC_BDDC                *pcbddc=(PC_BDDC*)pc->data;
371   PCBDDCDeluxeScaling    deluxe_ctx=pcbddc->deluxe_ctx;
372   PCBDDCSubSchurs        sub_schurs = pcbddc->sub_schurs;
373   PetscErrorCode         ierr;
374 
375   PetscFunctionBegin;
376   if (!sub_schurs->n_subs) {
377     PetscFunctionReturn(0);
378   }
379 
380   /* Create work vectors for sequential part of deluxe */
381   ierr = MatCreateVecs(sub_schurs->S_Ej_all,&deluxe_ctx->seq_work1,&deluxe_ctx->seq_work2);CHKERRQ(ierr);
382 
383   /* Compute deluxe sequential scatter */
384   if (sub_schurs->reuse_mumps && !sub_schurs->is_dir) {
385     PCBDDCReuseMumps reuse_mumps = sub_schurs->reuse_mumps;
386     ierr = PetscObjectReference((PetscObject)reuse_mumps->correction_scatter_B);CHKERRQ(ierr);
387     deluxe_ctx->seq_scctx = reuse_mumps->correction_scatter_B;
388   } else {
389     ierr = VecScatterCreate(pcbddc->work_scaling,sub_schurs->is_Ej_all,deluxe_ctx->seq_work1,NULL,&deluxe_ctx->seq_scctx);CHKERRQ(ierr);
390   }
391 
392   /* Create Mat object for deluxe scaling */
393   ierr = PetscObjectReference((PetscObject)sub_schurs->S_Ej_all);CHKERRQ(ierr);
394   deluxe_ctx->seq_mat = sub_schurs->S_Ej_all;
395   if (sub_schurs->sum_S_Ej_all) { /* if this matrix is present, then we need to create the KSP object to invert it */
396     PC               pc_temp;
397     MatSolverPackage solver=NULL;
398     char             ksp_prefix[256];
399     size_t           len;
400 
401     ierr = KSPCreate(PETSC_COMM_SELF,&deluxe_ctx->seq_ksp);CHKERRQ(ierr);
402     ierr = KSPSetOperators(deluxe_ctx->seq_ksp,sub_schurs->sum_S_Ej_all,sub_schurs->sum_S_Ej_all);CHKERRQ(ierr);
403     ierr = KSPSetType(deluxe_ctx->seq_ksp,KSPPREONLY);CHKERRQ(ierr);
404     ierr = KSPGetPC(deluxe_ctx->seq_ksp,&pc_temp);CHKERRQ(ierr);
405     ierr = PCSetType(pc_temp,PCLU);CHKERRQ(ierr);
406     ierr = KSPGetPC(pcbddc->ksp_D,&pc_temp);CHKERRQ(ierr);
407     ierr = PCFactorGetMatSolverPackage(pc_temp,(const MatSolverPackage*)&solver);CHKERRQ(ierr);
408     if (solver) {
409       PC     new_pc;
410       PCType type;
411 
412       ierr = PCGetType(pc_temp,&type);CHKERRQ(ierr);
413       ierr = KSPGetPC(deluxe_ctx->seq_ksp,&new_pc);CHKERRQ(ierr);
414       ierr = PCSetType(new_pc,type);CHKERRQ(ierr);
415       ierr = PCFactorSetMatSolverPackage(new_pc,solver);CHKERRQ(ierr);
416     }
417     ierr = PetscStrlen(((PetscObject)(pcbddc->ksp_D))->prefix,&len);CHKERRQ(ierr);
418     len -= 10; /* remove "dirichlet_" */
419     ierr = PetscStrncpy(ksp_prefix,((PetscObject)(pcbddc->ksp_D))->prefix,len+1);CHKERRQ(ierr);
420     ierr = PetscStrcat(ksp_prefix,"deluxe_");CHKERRQ(ierr);
421     ierr = KSPSetOptionsPrefix(deluxe_ctx->seq_ksp,ksp_prefix);CHKERRQ(ierr);
422     ierr = KSPSetFromOptions(deluxe_ctx->seq_ksp);CHKERRQ(ierr);
423     ierr = KSPSetUp(deluxe_ctx->seq_ksp);CHKERRQ(ierr);
424   }
425   PetscFunctionReturn(0);
426 }
427