xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision bf3a8328b6ce96d64a5fca2f10f053ff47f095d4)
153cdbc3dSStefano Zampini /* TODOLIST
2eb97c9d2SStefano Zampini 
3eb97c9d2SStefano Zampini    Solvers
4a0d3c3abSStefano Zampini    - Add support for cholesky for coarse solver (similar to local solvers)
5eb97c9d2SStefano Zampini    - Propagate ksp prefixes for solvers to mat objects?
6eb97c9d2SStefano Zampini 
7eb97c9d2SStefano Zampini    User interface
80f202f7eSStefano Zampini    - ** DM attached to pc?
9eb97c9d2SStefano Zampini 
10eb97c9d2SStefano Zampini    Debugging output
11b9b85e73SStefano Zampini    - * Better management of verbosity levels of debugging output
12eb97c9d2SStefano Zampini 
13eb97c9d2SStefano Zampini    Extra
14b9b85e73SStefano Zampini    - *** Is it possible to work with PCBDDCGraph on boundary indices only (less memory consumed)?
15eb97c9d2SStefano Zampini    - BDDC with MG framework?
16eb97c9d2SStefano Zampini 
17eb97c9d2SStefano Zampini    FETIDP
18eb97c9d2SStefano Zampini    - Move FETIDP code to its own classes
19eb97c9d2SStefano Zampini 
20eb97c9d2SStefano Zampini    MATIS related operations contained in BDDC code
21eb97c9d2SStefano Zampini    - Provide general case for subassembling
22eb97c9d2SStefano Zampini 
2353cdbc3dSStefano Zampini */
240c7d97c5SJed Brown 
25ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddc.h> /*I "petscpc.h" I*/  /* includes for fortran wrappers */
26ab5c6b0cSJed Brown #include <../src/ksp/pc/impls/bddc/bddcprivate.h>
273b03a366Sstefano_zampini #include <petscblaslapack.h>
28674ae819SStefano Zampini 
290369aaf7SStefano Zampini /* temporarily declare it */
300369aaf7SStefano Zampini PetscErrorCode PCApply_BDDC(PC,Vec,Vec);
310369aaf7SStefano Zampini 
320c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
330c7d97c5SJed Brown #undef __FUNCT__
340c7d97c5SJed Brown #define __FUNCT__ "PCSetFromOptions_BDDC"
358c34d3f5SBarry Smith PetscErrorCode PCSetFromOptions_BDDC(PetscOptions *PetscOptionsObject,PC pc)
360c7d97c5SJed Brown {
370c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
380c7d97c5SJed Brown   PetscErrorCode ierr;
390c7d97c5SJed Brown 
400c7d97c5SJed Brown   PetscFunctionBegin;
41e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"BDDC options");CHKERRQ(ierr);
428eeda7d8SStefano Zampini   /* Verbose debugging */
438eeda7d8SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_check_level","Verbose output for PCBDDC (intended for debug)","none",pcbddc->dbg_flag,&pcbddc->dbg_flag,NULL);CHKERRQ(ierr);
448eeda7d8SStefano Zampini   /* Primal space cumstomization */
4508a5cf49SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_local_mat_graph","Use or not adjacency graph of local mat for interface analysis","none",pcbddc->use_local_adj,&pcbddc->use_local_adj,NULL);CHKERRQ(ierr);
468eeda7d8SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_vertices","Use or not corner dofs in coarse space","none",pcbddc->use_vertices,&pcbddc->use_vertices,NULL);CHKERRQ(ierr);
478eeda7d8SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_edges","Use or not edge constraints in coarse space","none",pcbddc->use_edges,&pcbddc->use_edges,NULL);CHKERRQ(ierr);
488eeda7d8SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_faces","Use or not face constraints in coarse space","none",pcbddc->use_faces,&pcbddc->use_faces,NULL);CHKERRQ(ierr);
496661aa1dSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_true_nnsp","Use near null space attached to the matrix without modifications","none",pcbddc->use_nnsp_true,&pcbddc->use_nnsp_true,NULL);CHKERRQ(ierr);
50ac632422SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_qr_single","Use QR factorization for single constraints on cc (QR is used when multiple constraints are present)","none",pcbddc->use_qr_single,&pcbddc->use_qr_single,NULL);CHKERRQ(ierr);
518eeda7d8SStefano Zampini   /* Change of basis */
52b9b85e73SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_change_of_basis","Use or not internal change of basis on local edge nodes","none",pcbddc->use_change_of_basis,&pcbddc->use_change_of_basis,NULL);CHKERRQ(ierr);
53b9b85e73SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_change_on_faces","Use or not internal change of basis on local face nodes","none",pcbddc->use_change_on_faces,&pcbddc->use_change_on_faces,NULL);CHKERRQ(ierr);
54674ae819SStefano Zampini   if (!pcbddc->use_change_of_basis) {
55674ae819SStefano Zampini     pcbddc->use_change_on_faces = PETSC_FALSE;
56674ae819SStefano Zampini   }
578eeda7d8SStefano Zampini   /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */
588eeda7d8SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_switch_static","Switch on static condensation ops around the interface preconditioner","none",pcbddc->switch_static,&pcbddc->switch_static,NULL);CHKERRQ(ierr);
5974e2c79eSStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_coarse_redistribute","Number of procs where to redistribute coarse problem","none",pcbddc->redistribute_coarse,&pcbddc->redistribute_coarse,NULL);CHKERRQ(ierr);
600298fd71SBarry Smith   ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","none",pcbddc->coarsening_ratio,&pcbddc->coarsening_ratio,NULL);CHKERRQ(ierr);
612b510759SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_levels","Set maximum number of levels for multilevel","none",pcbddc->max_levels,&pcbddc->max_levels,NULL);CHKERRQ(ierr);
62323d395dSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_coarse_estimates","Use estimated eigenvalues for coarse problem","none",pcbddc->use_coarse_estimates,&pcbddc->use_coarse_estimates,NULL);CHKERRQ(ierr);
63674ae819SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_deluxe_scaling","Use deluxe scaling for BDDC","none",pcbddc->use_deluxe_scaling,&pcbddc->use_deluxe_scaling,NULL);CHKERRQ(ierr);
64b96c3477SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_schur_rebuild","Whether or not the interface graph for Schur principal minors has to be rebuilt (i.e. define the interface without any adjacency)","none",pcbddc->sub_schurs_rebuild,&pcbddc->sub_schurs_rebuild,NULL);CHKERRQ(ierr);
65b96c3477SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_schur_layers","Number of dofs' layers for the computation of principal minors (i.e. -1 uses all dofs)","none",pcbddc->sub_schurs_layers,&pcbddc->sub_schurs_layers,NULL);CHKERRQ(ierr);
66b96c3477SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_schur_use_useradj","Whether or not the CSR graph specified by the user should be used for computing successive layers (default is to use adj of local mat)","none",pcbddc->sub_schurs_use_useradj,&pcbddc->sub_schurs_use_useradj,NULL);CHKERRQ(ierr);
67683d3df6SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_schur_exact","Whether or not to use the exact Schur complement instead of the reduced one (which excludes size 1 cc)","none",pcbddc->sub_schurs_exact_schur,&pcbddc->sub_schurs_exact_schur,NULL);CHKERRQ(ierr);
68*bf3a8328SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_deluxe_zerorows","Zero rows and columns of deluxe operators associated with primal dofs","none",pcbddc->deluxe_zerorows,&pcbddc->deluxe_zerorows,NULL);CHKERRQ(ierr);
69ac632422SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_deluxe_faster","Faster application of deluxe scaling (requires extra work during setup)","none",pcbddc->faster_deluxe,&pcbddc->faster_deluxe,NULL);CHKERRQ(ierr);
70*bf3a8328SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_adaptive_userdefined","Use user-defined constraints (should be attached via MatSetNearNullSpace to pmat) in addition to those adaptively generated","none",pcbddc->adaptive_userdefined,&pcbddc->adaptive_userdefined,NULL);CHKERRQ(ierr);
714c6709b3SStefano Zampini   ierr = PetscOptionsReal("-pc_bddc_adaptive_threshold","Threshold to be used for adaptive selection of constraints","none",pcbddc->adaptive_threshold,&pcbddc->adaptive_threshold,NULL);CHKERRQ(ierr);
7208122e43SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_adaptive_nmin","Minimum number of constraints per connected components","none",pcbddc->adaptive_nmin,&pcbddc->adaptive_nmin,NULL);CHKERRQ(ierr);
7308122e43SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_adaptive_nmax","Maximum number of constraints per connected components","none",pcbddc->adaptive_nmax,&pcbddc->adaptive_nmax,NULL);CHKERRQ(ierr);
743301b35fSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_symmetric","Symmetric computation of primal basis functions","none",pcbddc->symmetric_primal,&pcbddc->symmetric_primal,NULL);CHKERRQ(ierr);
75b0c7d250SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_coarse_adj","Number of processors where to map the coarse adjacency list","none",pcbddc->coarse_adj_red,&pcbddc->coarse_adj_red,NULL);CHKERRQ(ierr);
7606a4e24aSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_benign_trick","Apply the benign subspace trick to a class of saddle point problems","none",pcbddc->benign_saddle_point,&pcbddc->benign_saddle_point,NULL);CHKERRQ(ierr);
774f1b2e48SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_detect_disconnected","Detects disconnected subdomains","none",pcbddc->detect_disconnected,&pcbddc->detect_disconnected,NULL);CHKERRQ(ierr);
780c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
790c7d97c5SJed Brown   PetscFunctionReturn(0);
800c7d97c5SJed Brown }
810c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
82674ae819SStefano Zampini #undef __FUNCT__
83906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCSetChangeOfBasisMat_BDDC"
84906d46d4SStefano Zampini static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change)
85b9b85e73SStefano Zampini {
86b9b85e73SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
87b9b85e73SStefano Zampini   PetscErrorCode ierr;
88b9b85e73SStefano Zampini 
89b9b85e73SStefano Zampini   PetscFunctionBegin;
90b9b85e73SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
91b9b85e73SStefano Zampini   ierr = PetscObjectReference((PetscObject)change);CHKERRQ(ierr);
92b9b85e73SStefano Zampini   pcbddc->user_ChangeOfBasisMatrix = change;
93b9b85e73SStefano Zampini   PetscFunctionReturn(0);
94b9b85e73SStefano Zampini }
95b9b85e73SStefano Zampini #undef __FUNCT__
96906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCSetChangeOfBasisMat"
97b9b85e73SStefano Zampini /*@
98906d46d4SStefano Zampini  PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs
99b9b85e73SStefano Zampini 
100b9b85e73SStefano Zampini    Collective on PC
101b9b85e73SStefano Zampini 
102b9b85e73SStefano Zampini    Input Parameters:
103b9b85e73SStefano Zampini +  pc - the preconditioning context
104906d46d4SStefano Zampini -  change - the change of basis matrix
105b9b85e73SStefano Zampini 
106b9b85e73SStefano Zampini    Level: intermediate
107b9b85e73SStefano Zampini 
108b9b85e73SStefano Zampini    Notes:
109b9b85e73SStefano Zampini 
110b9b85e73SStefano Zampini .seealso: PCBDDC
111b9b85e73SStefano Zampini @*/
112906d46d4SStefano Zampini PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change)
113b9b85e73SStefano Zampini {
114b9b85e73SStefano Zampini   PetscErrorCode ierr;
115b9b85e73SStefano Zampini 
116b9b85e73SStefano Zampini   PetscFunctionBegin;
117b9b85e73SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
118b9b85e73SStefano Zampini   PetscValidHeaderSpecific(change,MAT_CLASSID,2);
119906d46d4SStefano Zampini   PetscCheckSameComm(pc,1,change,2);
120906d46d4SStefano Zampini   if (pc->mat) {
121906d46d4SStefano Zampini     PetscInt rows_c,cols_c,rows,cols;
122906d46d4SStefano Zampini     ierr = MatGetSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
123906d46d4SStefano Zampini     ierr = MatGetSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
124906d46d4SStefano Zampini     if (rows_c != rows) {
125906d46d4SStefano Zampini       SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of rows for change of basis matrix! %d != %d",rows_c,rows);
126906d46d4SStefano Zampini     }
127906d46d4SStefano Zampini     if (cols_c != cols) {
128906d46d4SStefano Zampini       SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of columns for change of basis matrix! %d != %d",cols_c,cols);
129906d46d4SStefano Zampini     }
130906d46d4SStefano Zampini     ierr = MatGetLocalSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
131906d46d4SStefano Zampini     ierr = MatGetLocalSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
132906d46d4SStefano Zampini     if (rows_c != rows) {
133906d46d4SStefano Zampini       SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local rows for change of basis matrix! %d != %d",rows_c,rows);
134906d46d4SStefano Zampini     }
135906d46d4SStefano Zampini     if (cols_c != cols) {
136906d46d4SStefano Zampini       SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local columns for change of basis matrix! %d != %d",cols_c,cols);
137906d46d4SStefano Zampini     }
138906d46d4SStefano Zampini   }
139906d46d4SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetChangeOfBasisMat_C",(PC,Mat),(pc,change));CHKERRQ(ierr);
140b9b85e73SStefano Zampini   PetscFunctionReturn(0);
141b9b85e73SStefano Zampini }
142b9b85e73SStefano Zampini /* -------------------------------------------------------------------------- */
143b9b85e73SStefano Zampini #undef __FUNCT__
14430368db7SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesIS_BDDC"
14530368db7SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices)
14630368db7SStefano Zampini {
14730368db7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
14830368db7SStefano Zampini   PetscErrorCode ierr;
14930368db7SStefano Zampini 
15030368db7SStefano Zampini   PetscFunctionBegin;
15130368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
15230368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
15330368db7SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
15430368db7SStefano Zampini   pcbddc->user_primal_vertices = PrimalVertices;
15530368db7SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
15630368db7SStefano Zampini   PetscFunctionReturn(0);
15730368db7SStefano Zampini }
15830368db7SStefano Zampini #undef __FUNCT__
15930368db7SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesIS"
16030368db7SStefano Zampini /*@
16130368db7SStefano Zampini  PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in PCBDDC
16230368db7SStefano Zampini 
16330368db7SStefano Zampini    Collective
16430368db7SStefano Zampini 
16530368db7SStefano Zampini    Input Parameters:
16630368db7SStefano Zampini +  pc - the preconditioning context
16730368db7SStefano Zampini -  PrimalVertices - index set of primal vertices in global numbering (can be empty)
16830368db7SStefano Zampini 
16930368db7SStefano Zampini    Level: intermediate
17030368db7SStefano Zampini 
17130368db7SStefano Zampini    Notes:
17230368db7SStefano Zampini      Any process can list any global node
17330368db7SStefano Zampini 
17430368db7SStefano Zampini .seealso: PCBDDC
17530368db7SStefano Zampini @*/
17630368db7SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices)
17730368db7SStefano Zampini {
17830368db7SStefano Zampini   PetscErrorCode ierr;
17930368db7SStefano Zampini 
18030368db7SStefano Zampini   PetscFunctionBegin;
18130368db7SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
18230368db7SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
18330368db7SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
18430368db7SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
18530368db7SStefano Zampini   PetscFunctionReturn(0);
18630368db7SStefano Zampini }
18730368db7SStefano Zampini /* -------------------------------------------------------------------------- */
18830368db7SStefano Zampini #undef __FUNCT__
189674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS_BDDC"
190674ae819SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
191674ae819SStefano Zampini {
192674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
193674ae819SStefano Zampini   PetscErrorCode ierr;
1941e6b0712SBarry Smith 
195674ae819SStefano Zampini   PetscFunctionBegin;
196674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
19730368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
198674ae819SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
19930368db7SStefano Zampini   pcbddc->user_primal_vertices_local = PrimalVertices;
20030368db7SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
201674ae819SStefano Zampini   PetscFunctionReturn(0);
202674ae819SStefano Zampini }
203674ae819SStefano Zampini #undef __FUNCT__
204674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS"
205674ae819SStefano Zampini /*@
20628509bceSStefano Zampini  PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC
207674ae819SStefano Zampini 
20817eb1463SStefano Zampini    Collective
209674ae819SStefano Zampini 
210674ae819SStefano Zampini    Input Parameters:
211674ae819SStefano Zampini +  pc - the preconditioning context
21217eb1463SStefano Zampini -  PrimalVertices - index set of primal vertices in local numbering (can be empty)
213674ae819SStefano Zampini 
214674ae819SStefano Zampini    Level: intermediate
215674ae819SStefano Zampini 
216674ae819SStefano Zampini    Notes:
217674ae819SStefano Zampini 
218674ae819SStefano Zampini .seealso: PCBDDC
219674ae819SStefano Zampini @*/
220674ae819SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
221674ae819SStefano Zampini {
222674ae819SStefano Zampini   PetscErrorCode ierr;
223674ae819SStefano Zampini 
224674ae819SStefano Zampini   PetscFunctionBegin;
225674ae819SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
226674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
22717eb1463SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
228674ae819SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
229674ae819SStefano Zampini   PetscFunctionReturn(0);
230674ae819SStefano Zampini }
231674ae819SStefano Zampini /* -------------------------------------------------------------------------- */
2320c7d97c5SJed Brown #undef __FUNCT__
2334fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetCoarseningRatio_BDDC"
2344fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)
2354fad6a16SStefano Zampini {
2364fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
2374fad6a16SStefano Zampini 
2384fad6a16SStefano Zampini   PetscFunctionBegin;
2394fad6a16SStefano Zampini   pcbddc->coarsening_ratio = k;
2404fad6a16SStefano Zampini   PetscFunctionReturn(0);
2414fad6a16SStefano Zampini }
2421e6b0712SBarry Smith 
2434fad6a16SStefano Zampini #undef __FUNCT__
2444fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetCoarseningRatio"
2454fad6a16SStefano Zampini /*@
24628509bceSStefano Zampini  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel
2474fad6a16SStefano Zampini 
2484fad6a16SStefano Zampini    Logically collective on PC
2494fad6a16SStefano Zampini 
2504fad6a16SStefano Zampini    Input Parameters:
2514fad6a16SStefano Zampini +  pc - the preconditioning context
25228509bceSStefano Zampini -  k - coarsening ratio (H/h at the coarser level)
2534fad6a16SStefano Zampini 
2540f202f7eSStefano Zampini    Options Database Keys:
2550f202f7eSStefano Zampini .    -pc_bddc_coarsening_ratio
2564fad6a16SStefano Zampini 
2574fad6a16SStefano Zampini    Level: intermediate
2584fad6a16SStefano Zampini 
2594fad6a16SStefano Zampini    Notes:
2600f202f7eSStefano Zampini      Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level
2614fad6a16SStefano Zampini 
2620f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetLevels()
2634fad6a16SStefano Zampini @*/
2644fad6a16SStefano Zampini PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k)
2654fad6a16SStefano Zampini {
2664fad6a16SStefano Zampini   PetscErrorCode ierr;
2674fad6a16SStefano Zampini 
2684fad6a16SStefano Zampini   PetscFunctionBegin;
2694fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2702b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,k,2);
2714fad6a16SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr);
2724fad6a16SStefano Zampini   PetscFunctionReturn(0);
2734fad6a16SStefano Zampini }
2742b510759SStefano Zampini 
275b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */
2762b510759SStefano Zampini #undef __FUNCT__
277b8ffe317SStefano Zampini #define __FUNCT__ "PCBDDCSetUseExactDirichlet_BDDC"
278b8ffe317SStefano Zampini static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg)
279b8ffe317SStefano Zampini {
280b8ffe317SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
281b8ffe317SStefano Zampini 
282b8ffe317SStefano Zampini   PetscFunctionBegin;
28385c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = flg;
284b8ffe317SStefano Zampini   PetscFunctionReturn(0);
285b8ffe317SStefano Zampini }
286b8ffe317SStefano Zampini 
287b8ffe317SStefano Zampini #undef __FUNCT__
288b8ffe317SStefano Zampini #define __FUNCT__ "PCBDDCSetUseExactDirichlet"
289b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg)
2902b510759SStefano Zampini {
2912b510759SStefano Zampini   PetscErrorCode ierr;
2922b510759SStefano Zampini 
2932b510759SStefano Zampini   PetscFunctionBegin;
2942b510759SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
295b8ffe317SStefano Zampini   PetscValidLogicalCollectiveBool(pc,flg,2);
296b8ffe317SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetUseExactDirichlet_C",(PC,PetscBool),(pc,flg));CHKERRQ(ierr);
2972b510759SStefano Zampini   PetscFunctionReturn(0);
2982b510759SStefano Zampini }
2991e6b0712SBarry Smith 
3004fad6a16SStefano Zampini #undef __FUNCT__
3012b510759SStefano Zampini #define __FUNCT__ "PCBDDCSetLevel_BDDC"
3022b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc,PetscInt level)
3034fad6a16SStefano Zampini {
3044fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
3054fad6a16SStefano Zampini 
3064fad6a16SStefano Zampini   PetscFunctionBegin;
3072b510759SStefano Zampini   pcbddc->current_level = level;
3084fad6a16SStefano Zampini   PetscFunctionReturn(0);
3094fad6a16SStefano Zampini }
3101e6b0712SBarry Smith 
3114fad6a16SStefano Zampini #undef __FUNCT__
312b8ffe317SStefano Zampini #define __FUNCT__ "PCBDDCSetLevel"
313b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
314b8ffe317SStefano Zampini {
315b8ffe317SStefano Zampini   PetscErrorCode ierr;
316b8ffe317SStefano Zampini 
317b8ffe317SStefano Zampini   PetscFunctionBegin;
318b8ffe317SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
319b8ffe317SStefano Zampini   PetscValidLogicalCollectiveInt(pc,level,2);
320b8ffe317SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLevel_C",(PC,PetscInt),(pc,level));CHKERRQ(ierr);
321b8ffe317SStefano Zampini   PetscFunctionReturn(0);
322b8ffe317SStefano Zampini }
323b8ffe317SStefano Zampini 
324b8ffe317SStefano Zampini #undef __FUNCT__
3252b510759SStefano Zampini #define __FUNCT__ "PCBDDCSetLevels_BDDC"
3262b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc,PetscInt levels)
3272b510759SStefano Zampini {
3282b510759SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
3292b510759SStefano Zampini 
3302b510759SStefano Zampini   PetscFunctionBegin;
3312b510759SStefano Zampini   pcbddc->max_levels = levels;
3322b510759SStefano Zampini   PetscFunctionReturn(0);
3332b510759SStefano Zampini }
3342b510759SStefano Zampini 
3352b510759SStefano Zampini #undef __FUNCT__
3362b510759SStefano Zampini #define __FUNCT__ "PCBDDCSetLevels"
3374fad6a16SStefano Zampini /*@
33828509bceSStefano Zampini  PCBDDCSetLevels - Sets the maximum number of levels for multilevel
3394fad6a16SStefano Zampini 
3404fad6a16SStefano Zampini    Logically collective on PC
3414fad6a16SStefano Zampini 
3424fad6a16SStefano Zampini    Input Parameters:
3434fad6a16SStefano Zampini +  pc - the preconditioning context
34428509bceSStefano Zampini -  levels - the maximum number of levels (max 9)
3454fad6a16SStefano Zampini 
3460f202f7eSStefano Zampini    Options Database Keys:
3470f202f7eSStefano Zampini .    -pc_bddc_levels
3484fad6a16SStefano Zampini 
3494fad6a16SStefano Zampini    Level: intermediate
3504fad6a16SStefano Zampini 
3514fad6a16SStefano Zampini    Notes:
3520f202f7eSStefano Zampini      Default value is 0, i.e. traditional one-level BDDC
3534fad6a16SStefano Zampini 
3540f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetCoarseningRatio()
3554fad6a16SStefano Zampini @*/
3562b510759SStefano Zampini PetscErrorCode PCBDDCSetLevels(PC pc,PetscInt levels)
3574fad6a16SStefano Zampini {
3584fad6a16SStefano Zampini   PetscErrorCode ierr;
3594fad6a16SStefano Zampini 
3604fad6a16SStefano Zampini   PetscFunctionBegin;
3614fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
3622b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,levels,2);
363312be037SStefano Zampini   if (levels > 99) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Maximum number of levels for bddc is 99\n");
3642b510759SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLevels_C",(PC,PetscInt),(pc,levels));CHKERRQ(ierr);
3654fad6a16SStefano Zampini   PetscFunctionReturn(0);
3664fad6a16SStefano Zampini }
3674fad6a16SStefano Zampini /* -------------------------------------------------------------------------- */
3681e6b0712SBarry Smith 
3694fad6a16SStefano Zampini #undef __FUNCT__
3700bdf917eSStefano Zampini #define __FUNCT__ "PCBDDCSetNullSpace_BDDC"
3710bdf917eSStefano Zampini static PetscErrorCode PCBDDCSetNullSpace_BDDC(PC pc,MatNullSpace NullSpace)
3720bdf917eSStefano Zampini {
3730bdf917eSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
3740bdf917eSStefano Zampini   PetscErrorCode ierr;
3750bdf917eSStefano Zampini 
3760bdf917eSStefano Zampini   PetscFunctionBegin;
3770bdf917eSStefano Zampini   ierr = PetscObjectReference((PetscObject)NullSpace);CHKERRQ(ierr);
3780bdf917eSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
3790bdf917eSStefano Zampini   pcbddc->NullSpace = NullSpace;
3800bdf917eSStefano Zampini   PetscFunctionReturn(0);
3810bdf917eSStefano Zampini }
3821e6b0712SBarry Smith 
3830bdf917eSStefano Zampini #undef __FUNCT__
3840bdf917eSStefano Zampini #define __FUNCT__ "PCBDDCSetNullSpace"
3850bdf917eSStefano Zampini /*@
38628509bceSStefano Zampini  PCBDDCSetNullSpace - Set nullspace for BDDC operator
3870bdf917eSStefano Zampini 
3880bdf917eSStefano Zampini    Logically collective on PC and MatNullSpace
3890bdf917eSStefano Zampini 
3900bdf917eSStefano Zampini    Input Parameters:
3910bdf917eSStefano Zampini +  pc - the preconditioning context
39228509bceSStefano Zampini -  NullSpace - Null space of the linear operator to be preconditioned (Pmat)
3930bdf917eSStefano Zampini 
3940bdf917eSStefano Zampini    Level: intermediate
3950bdf917eSStefano Zampini 
3960bdf917eSStefano Zampini    Notes:
3970bdf917eSStefano Zampini 
3980bdf917eSStefano Zampini .seealso: PCBDDC
3990bdf917eSStefano Zampini @*/
4000bdf917eSStefano Zampini PetscErrorCode PCBDDCSetNullSpace(PC pc,MatNullSpace NullSpace)
4010bdf917eSStefano Zampini {
4020bdf917eSStefano Zampini   PetscErrorCode ierr;
4030bdf917eSStefano Zampini 
4040bdf917eSStefano Zampini   PetscFunctionBegin;
4050bdf917eSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
406674ae819SStefano Zampini   PetscValidHeaderSpecific(NullSpace,MAT_NULLSPACE_CLASSID,2);
4072b510759SStefano Zampini   PetscCheckSameComm(pc,1,NullSpace,2);
4080bdf917eSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNullSpace_C",(PC,MatNullSpace),(pc,NullSpace));CHKERRQ(ierr);
4090bdf917eSStefano Zampini   PetscFunctionReturn(0);
4100bdf917eSStefano Zampini }
4110bdf917eSStefano Zampini /* -------------------------------------------------------------------------- */
4121e6b0712SBarry Smith 
4130bdf917eSStefano Zampini #undef __FUNCT__
4143b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries_BDDC"
4153b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
4163b03a366Sstefano_zampini {
4173b03a366Sstefano_zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
4183b03a366Sstefano_zampini   PetscErrorCode ierr;
4193b03a366Sstefano_zampini 
4203b03a366Sstefano_zampini   PetscFunctionBegin;
421785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
422785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
4233b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
42436e030ebSStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
42536e030ebSStefano Zampini   pcbddc->DirichletBoundaries = DirichletBoundaries;
426fb180af4SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
4273b03a366Sstefano_zampini   PetscFunctionReturn(0);
4283b03a366Sstefano_zampini }
4291e6b0712SBarry Smith 
4303b03a366Sstefano_zampini #undef __FUNCT__
4313b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries"
4323b03a366Sstefano_zampini /*@
43328509bceSStefano Zampini  PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem.
4343b03a366Sstefano_zampini 
435785d1243SStefano Zampini    Collective
4363b03a366Sstefano_zampini 
4373b03a366Sstefano_zampini    Input Parameters:
4383b03a366Sstefano_zampini +  pc - the preconditioning context
439785d1243SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries
4403b03a366Sstefano_zampini 
4413b03a366Sstefano_zampini    Level: intermediate
4423b03a366Sstefano_zampini 
4430f202f7eSStefano Zampini    Notes:
4440f202f7eSStefano Zampini      Provide the information if you used MatZeroRows/Columns routines. Any process can list any global node
4453b03a366Sstefano_zampini 
4460f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundariesLocal(), MatZeroRows(), MatZeroRowsColumns()
4473b03a366Sstefano_zampini @*/
4483b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
4493b03a366Sstefano_zampini {
4503b03a366Sstefano_zampini   PetscErrorCode ierr;
4513b03a366Sstefano_zampini 
4523b03a366Sstefano_zampini   PetscFunctionBegin;
4533b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
454674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
455785d1243SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
4563b03a366Sstefano_zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
4573b03a366Sstefano_zampini   PetscFunctionReturn(0);
4583b03a366Sstefano_zampini }
4593b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
4601e6b0712SBarry Smith 
4613b03a366Sstefano_zampini #undef __FUNCT__
46282ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCSetDirichletBoundariesLocal_BDDC"
46382ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc,IS DirichletBoundaries)
4640c7d97c5SJed Brown {
4650c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
4660c7d97c5SJed Brown   PetscErrorCode ierr;
4670c7d97c5SJed Brown 
4680c7d97c5SJed Brown   PetscFunctionBegin;
469785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
470785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
4710c7d97c5SJed Brown   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
4720c7d97c5SJed Brown   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
473785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal = DirichletBoundaries;
4747d24d155SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
4750c7d97c5SJed Brown   PetscFunctionReturn(0);
4760c7d97c5SJed Brown }
4770c7d97c5SJed Brown 
4780c7d97c5SJed Brown #undef __FUNCT__
47982ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCSetDirichletBoundariesLocal"
4809c0446d6SStefano Zampini /*@
48182ba6b80SStefano Zampini  PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering.
4829c0446d6SStefano Zampini 
483785d1243SStefano Zampini    Collective
48453cdbc3dSStefano Zampini 
48553cdbc3dSStefano Zampini    Input Parameters:
48653cdbc3dSStefano Zampini +  pc - the preconditioning context
48782ba6b80SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering)
48853cdbc3dSStefano Zampini 
48953cdbc3dSStefano Zampini    Level: intermediate
49053cdbc3dSStefano Zampini 
4919c0446d6SStefano Zampini    Notes:
49253cdbc3dSStefano Zampini 
4930f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundaries(), MatZeroRows(), MatZeroRowsColumns()
49453cdbc3dSStefano Zampini @*/
49582ba6b80SStefano Zampini PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc,IS DirichletBoundaries)
4960c7d97c5SJed Brown {
4970c7d97c5SJed Brown   PetscErrorCode ierr;
4980c7d97c5SJed Brown 
4990c7d97c5SJed Brown   PetscFunctionBegin;
5000c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5010c7d97c5SJed Brown   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
50282ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
50382ba6b80SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundariesLocal_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
5040c7d97c5SJed Brown   PetscFunctionReturn(0);
5050c7d97c5SJed Brown }
5060c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
5070c7d97c5SJed Brown 
5080c7d97c5SJed Brown #undef __FUNCT__
5090c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
51053cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
5110c7d97c5SJed Brown {
5120c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
51353cdbc3dSStefano Zampini   PetscErrorCode ierr;
5140c7d97c5SJed Brown 
5150c7d97c5SJed Brown   PetscFunctionBegin;
516785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
517785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
51853cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
51936e030ebSStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
52036e030ebSStefano Zampini   pcbddc->NeumannBoundaries = NeumannBoundaries;
521fb180af4SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
5220c7d97c5SJed Brown   PetscFunctionReturn(0);
5230c7d97c5SJed Brown }
5241e6b0712SBarry Smith 
5250c7d97c5SJed Brown #undef __FUNCT__
5260c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
52757527edcSJed Brown /*@
52828509bceSStefano Zampini  PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem.
52957527edcSJed Brown 
530785d1243SStefano Zampini    Collective
53157527edcSJed Brown 
53257527edcSJed Brown    Input Parameters:
53357527edcSJed Brown +  pc - the preconditioning context
534785d1243SStefano Zampini -  NeumannBoundaries - parallel IS defining the Neumann boundaries
53557527edcSJed Brown 
53657527edcSJed Brown    Level: intermediate
53757527edcSJed Brown 
5380f202f7eSStefano Zampini    Notes:
5390f202f7eSStefano Zampini      Any process can list any global node
54057527edcSJed Brown 
5410f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundariesLocal()
54257527edcSJed Brown @*/
54353cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
5440c7d97c5SJed Brown {
5450c7d97c5SJed Brown   PetscErrorCode ierr;
5460c7d97c5SJed Brown 
5470c7d97c5SJed Brown   PetscFunctionBegin;
5480c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
549674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
550785d1243SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
55153cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
55253cdbc3dSStefano Zampini   PetscFunctionReturn(0);
55353cdbc3dSStefano Zampini }
55453cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
5551e6b0712SBarry Smith 
55653cdbc3dSStefano Zampini #undef __FUNCT__
55782ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCSetNeumannBoundariesLocal_BDDC"
55882ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc,IS NeumannBoundaries)
5590c7d97c5SJed Brown {
5600c7d97c5SJed Brown   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
5610c7d97c5SJed Brown   PetscErrorCode ierr;
5620c7d97c5SJed Brown 
5630c7d97c5SJed Brown   PetscFunctionBegin;
564785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
565785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
5660c7d97c5SJed Brown   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
5670c7d97c5SJed Brown   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
568785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal = NeumannBoundaries;
5697d24d155SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
5700c7d97c5SJed Brown   PetscFunctionReturn(0);
5710c7d97c5SJed Brown }
5720c7d97c5SJed Brown 
5730c7d97c5SJed Brown #undef __FUNCT__
57482ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCSetNeumannBoundariesLocal"
5750c7d97c5SJed Brown /*@
57682ba6b80SStefano Zampini  PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering.
5770c7d97c5SJed Brown 
578785d1243SStefano Zampini    Collective
5790c7d97c5SJed Brown 
5800c7d97c5SJed Brown    Input Parameters:
5810c7d97c5SJed Brown +  pc - the preconditioning context
58282ba6b80SStefano Zampini -  NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering)
5830c7d97c5SJed Brown 
5840c7d97c5SJed Brown    Level: intermediate
5850c7d97c5SJed Brown 
5860c7d97c5SJed Brown    Notes:
5870c7d97c5SJed Brown 
5880f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundaries()
5890c7d97c5SJed Brown @*/
59082ba6b80SStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc,IS NeumannBoundaries)
5910c7d97c5SJed Brown {
5920c7d97c5SJed Brown   PetscErrorCode ierr;
5930c7d97c5SJed Brown 
5940c7d97c5SJed Brown   PetscFunctionBegin;
5950c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5960c7d97c5SJed Brown   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
59782ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
59882ba6b80SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundariesLocal_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
59953cdbc3dSStefano Zampini   PetscFunctionReturn(0);
60053cdbc3dSStefano Zampini }
60153cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
60253cdbc3dSStefano Zampini 
60353cdbc3dSStefano Zampini #undef __FUNCT__
604da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries_BDDC"
605da1bb401SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
606da1bb401SStefano Zampini {
607da1bb401SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
608da1bb401SStefano Zampini 
609da1bb401SStefano Zampini   PetscFunctionBegin;
610da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
611da1bb401SStefano Zampini   PetscFunctionReturn(0);
612da1bb401SStefano Zampini }
6131e6b0712SBarry Smith 
614da1bb401SStefano Zampini #undef __FUNCT__
615da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries"
616da1bb401SStefano Zampini /*@
617785d1243SStefano Zampini  PCBDDCGetDirichletBoundaries - Get parallel IS for Dirichlet boundaries
618da1bb401SStefano Zampini 
619785d1243SStefano Zampini    Collective
620785d1243SStefano Zampini 
621785d1243SStefano Zampini    Input Parameters:
622785d1243SStefano Zampini .  pc - the preconditioning context
623785d1243SStefano Zampini 
624785d1243SStefano Zampini    Output Parameters:
625785d1243SStefano Zampini .  DirichletBoundaries - index set defining the Dirichlet boundaries
626785d1243SStefano Zampini 
627785d1243SStefano Zampini    Level: intermediate
628785d1243SStefano Zampini 
6290f202f7eSStefano Zampini    Notes:
6300f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetDirichletBoundaries
631785d1243SStefano Zampini 
632785d1243SStefano Zampini .seealso: PCBDDC
633785d1243SStefano Zampini @*/
634785d1243SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
635785d1243SStefano Zampini {
636785d1243SStefano Zampini   PetscErrorCode ierr;
637785d1243SStefano Zampini 
638785d1243SStefano Zampini   PetscFunctionBegin;
639785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
640785d1243SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
641785d1243SStefano Zampini   PetscFunctionReturn(0);
642785d1243SStefano Zampini }
643785d1243SStefano Zampini /* -------------------------------------------------------------------------- */
644785d1243SStefano Zampini 
645785d1243SStefano Zampini #undef __FUNCT__
646785d1243SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundariesLocal_BDDC"
647785d1243SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc,IS *DirichletBoundaries)
648785d1243SStefano Zampini {
649785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
650785d1243SStefano Zampini 
651785d1243SStefano Zampini   PetscFunctionBegin;
652785d1243SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundariesLocal;
653785d1243SStefano Zampini   PetscFunctionReturn(0);
654785d1243SStefano Zampini }
655785d1243SStefano Zampini 
656785d1243SStefano Zampini #undef __FUNCT__
65782ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundariesLocal"
658da1bb401SStefano Zampini /*@
65982ba6b80SStefano Zampini  PCBDDCGetDirichletBoundariesLocal - Get parallel IS for Dirichlet boundaries (in local ordering)
660da1bb401SStefano Zampini 
661785d1243SStefano Zampini    Collective
662da1bb401SStefano Zampini 
663da1bb401SStefano Zampini    Input Parameters:
66428509bceSStefano Zampini .  pc - the preconditioning context
665da1bb401SStefano Zampini 
666da1bb401SStefano Zampini    Output Parameters:
66728509bceSStefano Zampini .  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
668da1bb401SStefano Zampini 
669da1bb401SStefano Zampini    Level: intermediate
670da1bb401SStefano Zampini 
671da1bb401SStefano Zampini    Notes:
6720f202f7eSStefano Zampini      The IS returned could be the same passed in earlier by the user (if provided with PCBDDCSetDirichletBoundariesLocal) or a global-to-local map of the global IS (if provided with PCBDDCSetDirichletBoundaries).
6730f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
674da1bb401SStefano Zampini 
675da1bb401SStefano Zampini .seealso: PCBDDC
676da1bb401SStefano Zampini @*/
67782ba6b80SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc,IS *DirichletBoundaries)
678da1bb401SStefano Zampini {
679da1bb401SStefano Zampini   PetscErrorCode ierr;
680da1bb401SStefano Zampini 
681da1bb401SStefano Zampini   PetscFunctionBegin;
682da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
68382ba6b80SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundariesLocal_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
684da1bb401SStefano Zampini   PetscFunctionReturn(0);
685da1bb401SStefano Zampini }
686da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
6871e6b0712SBarry Smith 
688da1bb401SStefano Zampini #undef __FUNCT__
68953cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
69053cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
69153cdbc3dSStefano Zampini {
69253cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
69353cdbc3dSStefano Zampini 
69453cdbc3dSStefano Zampini   PetscFunctionBegin;
69553cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
69653cdbc3dSStefano Zampini   PetscFunctionReturn(0);
69753cdbc3dSStefano Zampini }
6981e6b0712SBarry Smith 
69953cdbc3dSStefano Zampini #undef __FUNCT__
70053cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
70153cdbc3dSStefano Zampini /*@
702785d1243SStefano Zampini  PCBDDCGetNeumannBoundaries - Get parallel IS for Neumann boundaries
70353cdbc3dSStefano Zampini 
704785d1243SStefano Zampini    Collective
705785d1243SStefano Zampini 
706785d1243SStefano Zampini    Input Parameters:
707785d1243SStefano Zampini .  pc - the preconditioning context
708785d1243SStefano Zampini 
709785d1243SStefano Zampini    Output Parameters:
710785d1243SStefano Zampini .  NeumannBoundaries - index set defining the Neumann boundaries
711785d1243SStefano Zampini 
712785d1243SStefano Zampini    Level: intermediate
713785d1243SStefano Zampini 
7140f202f7eSStefano Zampini    Notes:
7150f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetNeumannBoundaries
716785d1243SStefano Zampini 
717785d1243SStefano Zampini .seealso: PCBDDC
718785d1243SStefano Zampini @*/
719785d1243SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
720785d1243SStefano Zampini {
721785d1243SStefano Zampini   PetscErrorCode ierr;
722785d1243SStefano Zampini 
723785d1243SStefano Zampini   PetscFunctionBegin;
724785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
725785d1243SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
726785d1243SStefano Zampini   PetscFunctionReturn(0);
727785d1243SStefano Zampini }
728785d1243SStefano Zampini /* -------------------------------------------------------------------------- */
729785d1243SStefano Zampini 
730785d1243SStefano Zampini #undef __FUNCT__
731785d1243SStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundariesLocal_BDDC"
732785d1243SStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc,IS *NeumannBoundaries)
733785d1243SStefano Zampini {
734785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
735785d1243SStefano Zampini 
736785d1243SStefano Zampini   PetscFunctionBegin;
737785d1243SStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundariesLocal;
738785d1243SStefano Zampini   PetscFunctionReturn(0);
739785d1243SStefano Zampini }
740785d1243SStefano Zampini 
741785d1243SStefano Zampini #undef __FUNCT__
74282ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundariesLocal"
74353cdbc3dSStefano Zampini /*@
74482ba6b80SStefano Zampini  PCBDDCGetNeumannBoundariesLocal - Get parallel IS for Neumann boundaries (in local ordering)
74553cdbc3dSStefano Zampini 
746785d1243SStefano Zampini    Collective
74753cdbc3dSStefano Zampini 
74853cdbc3dSStefano Zampini    Input Parameters:
74928509bceSStefano Zampini .  pc - the preconditioning context
75053cdbc3dSStefano Zampini 
75153cdbc3dSStefano Zampini    Output Parameters:
75228509bceSStefano Zampini .  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
75353cdbc3dSStefano Zampini 
75453cdbc3dSStefano Zampini    Level: intermediate
75553cdbc3dSStefano Zampini 
75653cdbc3dSStefano Zampini    Notes:
7570f202f7eSStefano Zampini      The IS returned could be the same passed in earlier by the user (if provided with PCBDDCSetNeumannBoundariesLocal) or a global-to-local map of the global IS (if provided with PCBDDCSetNeumannBoundaries).
7580f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
75953cdbc3dSStefano Zampini 
76053cdbc3dSStefano Zampini .seealso: PCBDDC
76153cdbc3dSStefano Zampini @*/
76282ba6b80SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc,IS *NeumannBoundaries)
76353cdbc3dSStefano Zampini {
76453cdbc3dSStefano Zampini   PetscErrorCode ierr;
76553cdbc3dSStefano Zampini 
76653cdbc3dSStefano Zampini   PetscFunctionBegin;
76753cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
76882ba6b80SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundariesLocal_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
7690c7d97c5SJed Brown   PetscFunctionReturn(0);
7700c7d97c5SJed Brown }
77136e030ebSStefano Zampini /* -------------------------------------------------------------------------- */
7721e6b0712SBarry Smith 
77336e030ebSStefano Zampini #undef __FUNCT__
774da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph_BDDC"
7751a83f524SJed Brown static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
77636e030ebSStefano Zampini {
77736e030ebSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
778da1bb401SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
779da1bb401SStefano Zampini   PetscErrorCode ierr;
78036e030ebSStefano Zampini 
78136e030ebSStefano Zampini   PetscFunctionBegin;
782674ae819SStefano Zampini   /* free old CSR */
783674ae819SStefano Zampini   ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
784fb223d50SStefano Zampini   /* TODO: PCBDDCGraphSetAdjacency */
785674ae819SStefano Zampini   /* get CSR into graph structure */
786da1bb401SStefano Zampini   if (copymode == PETSC_COPY_VALUES) {
787854ce69bSBarry Smith     ierr = PetscMalloc1(nvtxs+1,&mat_graph->xadj);CHKERRQ(ierr);
788785e854fSJed Brown     ierr = PetscMalloc1(xadj[nvtxs],&mat_graph->adjncy);CHKERRQ(ierr);
789674ae819SStefano Zampini     ierr = PetscMemcpy(mat_graph->xadj,xadj,(nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
790674ae819SStefano Zampini     ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[nvtxs]*sizeof(PetscInt));CHKERRQ(ierr);
791da1bb401SStefano Zampini   } else if (copymode == PETSC_OWN_POINTER) {
7921a83f524SJed Brown     mat_graph->xadj = (PetscInt*)xadj;
7931a83f524SJed Brown     mat_graph->adjncy = (PetscInt*)adjncy;
794674ae819SStefano Zampini   }
795575ad6abSStefano Zampini   mat_graph->nvtxs_csr = nvtxs;
79636e030ebSStefano Zampini   PetscFunctionReturn(0);
79736e030ebSStefano Zampini }
7981e6b0712SBarry Smith 
79936e030ebSStefano Zampini #undef __FUNCT__
800da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph"
80136e030ebSStefano Zampini /*@
8020f202f7eSStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local matrix
80336e030ebSStefano Zampini 
80436e030ebSStefano Zampini    Not collective
80536e030ebSStefano Zampini 
80636e030ebSStefano Zampini    Input Parameters:
80736e030ebSStefano Zampini +  pc - the preconditioning context
8080f202f7eSStefano Zampini .  nvtxs - number of local vertices of the graph (i.e., the size of the local problem)
80928509bceSStefano Zampini .  xadj, adjncy - the CSR graph
81028509bceSStefano Zampini -  copymode - either PETSC_COPY_VALUES or PETSC_OWN_POINTER.
81136e030ebSStefano Zampini 
81236e030ebSStefano Zampini    Level: intermediate
81336e030ebSStefano Zampini 
81436e030ebSStefano Zampini    Notes:
81536e030ebSStefano Zampini 
81628509bceSStefano Zampini .seealso: PCBDDC,PetscCopyMode
81736e030ebSStefano Zampini @*/
8181a83f524SJed Brown PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
81936e030ebSStefano Zampini {
820575ad6abSStefano Zampini   void (*f)(void) = 0;
82136e030ebSStefano Zampini   PetscErrorCode ierr;
82236e030ebSStefano Zampini 
82336e030ebSStefano Zampini   PetscFunctionBegin;
82436e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
825674ae819SStefano Zampini   PetscValidIntPointer(xadj,3);
826d7de1dd9SStefano Zampini   PetscValidIntPointer(adjncy,4);
827674ae819SStefano Zampini   if (copymode != PETSC_COPY_VALUES && copymode != PETSC_OWN_POINTER) {
828674ae819SStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d in %s\n",copymode,__FUNCT__);
829da1bb401SStefano Zampini   }
83036e030ebSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
831575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
832575ad6abSStefano Zampini   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr);
833575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
834575ad6abSStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
835575ad6abSStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
83636e030ebSStefano Zampini   }
83736e030ebSStefano Zampini   PetscFunctionReturn(0);
83836e030ebSStefano Zampini }
8399c0446d6SStefano Zampini /* -------------------------------------------------------------------------- */
8401e6b0712SBarry Smith 
8419c0446d6SStefano Zampini #undef __FUNCT__
84263602bcaSStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplittingLocal_BDDC"
84363602bcaSStefano Zampini static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
84463602bcaSStefano Zampini {
84563602bcaSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
84663602bcaSStefano Zampini   PetscInt i;
84763602bcaSStefano Zampini   PetscErrorCode ierr;
84863602bcaSStefano Zampini 
84963602bcaSStefano Zampini   PetscFunctionBegin;
85063602bcaSStefano Zampini   /* Destroy ISes if they were already set */
85163602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
85263602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
85363602bcaSStefano Zampini   }
85463602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
85563602bcaSStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
85663602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
85763602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
85863602bcaSStefano Zampini   }
85963602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
86063602bcaSStefano Zampini   pcbddc->n_ISForDofs = 0;
86163602bcaSStefano Zampini   /* allocate space then set */
862d02579f5SStefano Zampini   if (n_is) {
863d02579f5SStefano Zampini     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
864d02579f5SStefano Zampini   }
86563602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
86663602bcaSStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
86763602bcaSStefano Zampini     pcbddc->ISForDofsLocal[i]=ISForDofs[i];
86863602bcaSStefano Zampini   }
86963602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal=n_is;
87063602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
8711a8a16d1SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
87263602bcaSStefano Zampini   PetscFunctionReturn(0);
87363602bcaSStefano Zampini }
87463602bcaSStefano Zampini 
87563602bcaSStefano Zampini #undef __FUNCT__
87663602bcaSStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplittingLocal"
87763602bcaSStefano Zampini /*@
87863602bcaSStefano Zampini  PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix
87963602bcaSStefano Zampini 
88063602bcaSStefano Zampini    Collective
88163602bcaSStefano Zampini 
88263602bcaSStefano Zampini    Input Parameters:
88363602bcaSStefano Zampini +  pc - the preconditioning context
8840f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
8850f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in local ordering
88663602bcaSStefano Zampini 
88763602bcaSStefano Zampini    Level: intermediate
88863602bcaSStefano Zampini 
8890f202f7eSStefano Zampini    Notes:
8900f202f7eSStefano Zampini      n_is should be the same among processes. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
89163602bcaSStefano Zampini 
89263602bcaSStefano Zampini .seealso: PCBDDC
89363602bcaSStefano Zampini @*/
89463602bcaSStefano Zampini PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc,PetscInt n_is, IS ISForDofs[])
89563602bcaSStefano Zampini {
89663602bcaSStefano Zampini   PetscInt       i;
89763602bcaSStefano Zampini   PetscErrorCode ierr;
89863602bcaSStefano Zampini 
89963602bcaSStefano Zampini   PetscFunctionBegin;
90063602bcaSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
90163602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
90263602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
90363602bcaSStefano Zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
90463602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
90563602bcaSStefano Zampini   }
906e71e7a71SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplittingLocal_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
90763602bcaSStefano Zampini   PetscFunctionReturn(0);
90863602bcaSStefano Zampini }
90963602bcaSStefano Zampini /* -------------------------------------------------------------------------- */
91063602bcaSStefano Zampini 
91163602bcaSStefano Zampini #undef __FUNCT__
9129c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
9139c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
9149c0446d6SStefano Zampini {
9159c0446d6SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
9169c0446d6SStefano Zampini   PetscInt i;
9179c0446d6SStefano Zampini   PetscErrorCode ierr;
9189c0446d6SStefano Zampini 
9199c0446d6SStefano Zampini   PetscFunctionBegin;
920da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
9219c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
9229c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
9239c0446d6SStefano Zampini   }
924d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
92563602bcaSStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
92663602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
92763602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
92863602bcaSStefano Zampini   }
92963602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
93063602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = 0;
931da1bb401SStefano Zampini   /* allocate space then set */
932d02579f5SStefano Zampini   if (n_is) {
933785e854fSJed Brown     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofs);CHKERRQ(ierr);
934d02579f5SStefano Zampini   }
9359c0446d6SStefano Zampini   for (i=0;i<n_is;i++) {
936da1bb401SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
937da1bb401SStefano Zampini     pcbddc->ISForDofs[i]=ISForDofs[i];
9389c0446d6SStefano Zampini   }
9399c0446d6SStefano Zampini   pcbddc->n_ISForDofs=n_is;
94063602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
9411a8a16d1SStefano Zampini   pcbddc->recompute_topography = PETSC_TRUE;
9429c0446d6SStefano Zampini   PetscFunctionReturn(0);
9439c0446d6SStefano Zampini }
9441e6b0712SBarry Smith 
9459c0446d6SStefano Zampini #undef __FUNCT__
9469c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting"
9479c0446d6SStefano Zampini /*@
94863602bcaSStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix
9499c0446d6SStefano Zampini 
95063602bcaSStefano Zampini    Collective
9519c0446d6SStefano Zampini 
9529c0446d6SStefano Zampini    Input Parameters:
9539c0446d6SStefano Zampini +  pc - the preconditioning context
9540f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
9550f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in global ordering
9569c0446d6SStefano Zampini 
9579c0446d6SStefano Zampini    Level: intermediate
9589c0446d6SStefano Zampini 
9590f202f7eSStefano Zampini    Notes:
9600f202f7eSStefano Zampini      Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
9619c0446d6SStefano Zampini 
9629c0446d6SStefano Zampini .seealso: PCBDDC
9639c0446d6SStefano Zampini @*/
9649c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
9659c0446d6SStefano Zampini {
9662b510759SStefano Zampini   PetscInt       i;
9679c0446d6SStefano Zampini   PetscErrorCode ierr;
9689c0446d6SStefano Zampini 
9699c0446d6SStefano Zampini   PetscFunctionBegin;
9709c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
97163602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
9722b510759SStefano Zampini   for (i=0;i<n_is;i++) {
97363602bcaSStefano Zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
97463602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
9752b510759SStefano Zampini   }
9769c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
9779c0446d6SStefano Zampini   PetscFunctionReturn(0);
9789c0446d6SStefano Zampini }
979906d46d4SStefano Zampini 
980da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
981534831adSStefano Zampini #undef __FUNCT__
982534831adSStefano Zampini #define __FUNCT__ "PCPreSolve_BDDC"
983534831adSStefano Zampini /* -------------------------------------------------------------------------- */
984534831adSStefano Zampini /*
985534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
986534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
9879c0446d6SStefano Zampini 
988534831adSStefano Zampini    Input Parameter:
989534831adSStefano Zampini +  pc - the preconditioner contex
990534831adSStefano Zampini 
991534831adSStefano Zampini    Application Interface Routine: PCPreSolve()
992534831adSStefano Zampini 
993534831adSStefano Zampini    Notes:
994534831adSStefano Zampini      The interface routine PCPreSolve() is not usually called directly by
995534831adSStefano Zampini    the user, but instead is called by KSPSolve().
996534831adSStefano Zampini */
997534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
998534831adSStefano Zampini {
999534831adSStefano Zampini   PetscErrorCode ierr;
1000534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1001534831adSStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
10023972b0daSStefano Zampini   Vec            used_vec;
10038d00608fSStefano Zampini   PetscBool      copy_rhs = PETSC_TRUE;
100451694757SStefano Zampini   PetscBool      benign_correction_is_zero = PETSC_FALSE;
1005a3df083aSStefano Zampini   PetscBool      iscg = PETSC_FALSE;
1006534831adSStefano Zampini 
1007534831adSStefano Zampini   PetscFunctionBegin;
100885c4d303SStefano Zampini   /* if we are working with cg, one dirichlet solve can be avoided during Krylov iterations */
100985c4d303SStefano Zampini   if (ksp) {
101085c4d303SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPCG,&iscg);CHKERRQ(ierr);
101185c4d303SStefano Zampini     if (!iscg) {
101285c4d303SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
101385c4d303SStefano Zampini     }
101485c4d303SStefano Zampini   }
101585c4d303SStefano Zampini   /* Creates parallel work vectors used in presolve */
101662a6ff1dSStefano Zampini   if (!pcbddc->original_rhs) {
101762a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
101862a6ff1dSStefano Zampini   }
101962a6ff1dSStefano Zampini   if (!pcbddc->temp_solution) {
102062a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
102162a6ff1dSStefano Zampini   }
10228d00608fSStefano Zampini 
10233972b0daSStefano Zampini   if (x) {
10243972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
10253972b0daSStefano Zampini     used_vec = x;
10268d00608fSStefano Zampini   } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */
10273972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
10283972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
10293972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
10303972b0daSStefano Zampini   }
10318efcfb23SStefano Zampini 
10328efcfb23SStefano Zampini   /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */
10333972b0daSStefano Zampini   if (ksp) {
1034a0cb1b98SStefano Zampini     /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */
10358efcfb23SStefano Zampini     ierr = KSPGetInitialGuessNonzero(ksp,&pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
10368efcfb23SStefano Zampini     if (!pcbddc->ksp_guess_nonzero) {
10373972b0daSStefano Zampini       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
10383972b0daSStefano Zampini     }
10393972b0daSStefano Zampini   }
10403308cffdSStefano Zampini 
10418d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
10423972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
1043a07ea27aSStefano Zampini   if (rhs) {
10443975b054SStefano Zampini     IS dirIS = NULL;
10453975b054SStefano Zampini 
1046a07ea27aSStefano Zampini     /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */
10473975b054SStefano Zampini     ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
10483975b054SStefano Zampini     if (dirIS) {
1049906d46d4SStefano Zampini       Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
1050785d1243SStefano Zampini       PetscInt          dirsize,i,*is_indices;
10512b095fd8SStefano Zampini       PetscScalar       *array_x;
10522b095fd8SStefano Zampini       const PetscScalar *array_diagonal;
1053785d1243SStefano Zampini 
10543972b0daSStefano Zampini       ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
10553972b0daSStefano Zampini       ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
1056e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1057e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1058e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1059e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
106082ba6b80SStefano Zampini       ierr = ISGetLocalSize(dirIS,&dirsize);CHKERRQ(ierr);
10613972b0daSStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
10622b095fd8SStefano Zampini       ierr = VecGetArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
10633972b0daSStefano Zampini       ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
10642fa5cd67SKarl Rupp       for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
10653972b0daSStefano Zampini       ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
10662b095fd8SStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
10673972b0daSStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
1068e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1069e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
10708d00608fSStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
10711b968477SStefano Zampini       ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
10728efcfb23SStefano Zampini     }
1073a07ea27aSStefano Zampini   }
1074b76ba322SStefano Zampini 
10758efcfb23SStefano Zampini   /* remove the computed solution or the initial guess from the rhs */
10768d00608fSStefano Zampini   if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero) ) {
10778d00608fSStefano Zampini     /* store the original rhs */
10788d00608fSStefano Zampini     if (copy_rhs) {
10798d00608fSStefano Zampini       ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
10808d00608fSStefano Zampini       copy_rhs = PETSC_FALSE;
10818d00608fSStefano Zampini     }
10828d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
10833972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
10840369aaf7SStefano Zampini     ierr = MatMultAdd(pc->mat,used_vec,rhs,rhs);CHKERRQ(ierr);
10853972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
10868efcfb23SStefano Zampini     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
10877acc28cbSStefano Zampini     if (ksp) {
10887acc28cbSStefano Zampini       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_FALSE);CHKERRQ(ierr);
10897acc28cbSStefano Zampini     }
10903308cffdSStefano Zampini   }
10918efcfb23SStefano Zampini   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
1092b76ba322SStefano Zampini 
10930369aaf7SStefano Zampini   /* When using the benign trick: (TODO: what about FETI-DP?)
10940369aaf7SStefano Zampini      - change rhs on pressures (iteration matrix is surely of type MATIS)
10950369aaf7SStefano Zampini      - compute initial vector in benign space
10960369aaf7SStefano Zampini   */
10970369aaf7SStefano Zampini   if (rhs && pcbddc->benign_saddle_point) {
109806f24817SStefano Zampini     Mat_IS   *matis = (Mat_IS*)(pc->mat->data);
10994f1b2e48SStefano Zampini     PetscInt i;
110006f24817SStefano Zampini 
110106f24817SStefano Zampini     /* store the original rhs */
110206f24817SStefano Zampini     if (copy_rhs) {
110306f24817SStefano Zampini       ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
110406f24817SStefano Zampini       copy_rhs = PETSC_FALSE;
110506f24817SStefano Zampini     }
110606f24817SStefano Zampini 
110706f24817SStefano Zampini     /* now change (locally) the basis */
110806f24817SStefano Zampini     ierr = VecScatterBegin(matis->rctx,rhs,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
110906f24817SStefano Zampini     ierr = VecScatterEnd(matis->rctx,rhs,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
111006f24817SStefano Zampini     if (pcbddc->benign_change) {
111106f24817SStefano Zampini       ierr = MatMultTranspose(pcbddc->benign_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
111206f24817SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
111306f24817SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
11145cfd9691SStefano Zampini       /* swap local iteration matrix (with the benign trick, amat == pmat) */
1115a3df083aSStefano Zampini       if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
1116a3df083aSStefano Zampini         /* benign shell mat mult for matis->A and pcis->A_IB*/
1117a3df083aSStefano Zampini         ierr = PCBDDCBenignShellMat(pc,PETSC_FALSE);CHKERRQ(ierr);
1118a3df083aSStefano Zampini       } else {
11195cfd9691SStefano Zampini         ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_FALSE);CHKERRQ(ierr);
112006f24817SStefano Zampini         pcbddc->benign_original_mat = matis->A;
112106f24817SStefano Zampini         matis->A = pcbddc->local_mat;
1122a3df083aSStefano Zampini       }
112306f24817SStefano Zampini     } else {
112406f24817SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
112506f24817SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
112677a2de6eSStefano Zampini       if (pcbddc->ChangeOfBasisMatrix) {
112777a2de6eSStefano Zampini         pcbddc->benign_original_mat = matis->A;
112877a2de6eSStefano Zampini         matis->A = pcbddc->local_mat;
112977a2de6eSStefano Zampini       }
113006f24817SStefano Zampini     }
113106f24817SStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
113206f24817SStefano Zampini 
11330369aaf7SStefano Zampini     /* compute u^*_h as in Xuemin Tu's thesis (see Section 4.8.1) */
11340369aaf7SStefano Zampini     /* TODO: what about Stokes? */
11350369aaf7SStefano Zampini     if (!pcbddc->benign_vec) {
11360369aaf7SStefano Zampini       ierr = VecDuplicate(rhs,&pcbddc->benign_vec);CHKERRQ(ierr);
11370369aaf7SStefano Zampini     }
11384f1b2e48SStefano Zampini     ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
11394f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
11400369aaf7SStefano Zampini       const PetscScalar *array;
11410369aaf7SStefano Zampini 
11420369aaf7SStefano Zampini       ierr = VecGetArrayRead(pcis->vec2_N,&array);CHKERRQ(ierr);
11434f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[pcbddc->benign_p0_lidx[i]];
11440369aaf7SStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec2_N,&array);CHKERRQ(ierr);
11450369aaf7SStefano Zampini     }
114651694757SStefano Zampini     if (pcbddc->benign_null && iscg) { /* this is a workaround, need to understand more */
11474f1b2e48SStefano Zampini       PetscBool iszero_l = PETSC_TRUE;
11484f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
11494f1b2e48SStefano Zampini         iszero_l = (iszero_l && (PetscAbsScalar(pcbddc->benign_p0[i]) < PETSC_SMALL ? PETSC_TRUE : PETSC_FALSE));
11504f1b2e48SStefano Zampini       }
115151694757SStefano Zampini       ierr = MPI_Allreduce(&iszero_l,&benign_correction_is_zero,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
115251694757SStefano Zampini     }
11534fee134fSStefano Zampini     if (!benign_correction_is_zero) { /* use the coarse solver only */
1154015636ebSStefano Zampini       ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
11554fee134fSStefano Zampini       pcbddc->benign_apply_coarse_only = PETSC_TRUE;
11560369aaf7SStefano Zampini       ierr = PCApply_BDDC(pc,pcis->vec1_global,pcbddc->benign_vec);CHKERRQ(ierr);
11574fee134fSStefano Zampini       pcbddc->benign_apply_coarse_only = PETSC_FALSE;
11584f1b2e48SStefano Zampini       ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
1159015636ebSStefano Zampini       ierr = PCBDDCBenignGetOrSetP0(pc,pcbddc->benign_vec,PETSC_FALSE);CHKERRQ(ierr);
1160b76ba322SStefano Zampini     }
116151694757SStefano Zampini   }
1162b76ba322SStefano Zampini 
11630369aaf7SStefano Zampini   /* change rhs and iteration matrix if using the change of basis */
1164b9b85e73SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1165906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
1166906d46d4SStefano Zampini 
1167906d46d4SStefano Zampini     /* get change ctx */
1168906d46d4SStefano Zampini     ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
1169906d46d4SStefano Zampini 
1170906d46d4SStefano Zampini     /* set current iteration matrix inside change context (change of basis has been already set into the ctx during PCSetUp) */
117177a2de6eSStefano Zampini     if (!pcbddc->benign_original_mat) {
1172906d46d4SStefano Zampini       ierr = MatDestroy(&change_ctx->original_mat);CHKERRQ(ierr);
1173906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pc->mat);CHKERRQ(ierr);
1174906d46d4SStefano Zampini       change_ctx->original_mat = pc->mat;
1175906d46d4SStefano Zampini 
1176906d46d4SStefano Zampini       /* change iteration matrix */
1177906d46d4SStefano Zampini       ierr = MatDestroy(&pc->mat);CHKERRQ(ierr);
1178906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->new_global_mat);CHKERRQ(ierr);
1179906d46d4SStefano Zampini       pc->mat = pcbddc->new_global_mat;
11809bd2e3c7SStefano Zampini     }
11818d00608fSStefano Zampini     /* store the original rhs */
11828d00608fSStefano Zampini     if (copy_rhs) {
11838d00608fSStefano Zampini       ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
11848d00608fSStefano Zampini       copy_rhs = PETSC_FALSE;
11858d00608fSStefano Zampini     }
11868d00608fSStefano Zampini 
1187906d46d4SStefano Zampini     /* change rhs */
1188906d46d4SStefano Zampini     ierr = MatMultTranspose(change_ctx->global_change,rhs,pcis->vec1_global);CHKERRQ(ierr);
1189906d46d4SStefano Zampini     ierr = VecCopy(pcis->vec1_global,rhs);CHKERRQ(ierr);
11908d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
119192e3dcfbSStefano Zampini   }
119292e3dcfbSStefano Zampini 
11930369aaf7SStefano Zampini   /* remove non-benign solution from the rhs */
11940369aaf7SStefano Zampini   if (pcbddc->benign_saddle_point) {
11950369aaf7SStefano Zampini     /* store the original rhs */
11960369aaf7SStefano Zampini     if (copy_rhs) {
11970369aaf7SStefano Zampini       ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
11980369aaf7SStefano Zampini       copy_rhs = PETSC_FALSE;
11990369aaf7SStefano Zampini     }
120051694757SStefano Zampini     if (benign_correction_is_zero) { /* still need to understand why it works great */
120151694757SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
120251694757SStefano Zampini       ierr = PCApply_BDDC(pc,rhs,pcbddc->benign_vec);CHKERRQ(ierr);
120351694757SStefano Zampini     }
12040369aaf7SStefano Zampini     ierr = VecScale(pcbddc->benign_vec,-1.0);CHKERRQ(ierr);
12050369aaf7SStefano Zampini     ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,rhs,rhs);CHKERRQ(ierr);
12060369aaf7SStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
12070369aaf7SStefano Zampini   }
12080369aaf7SStefano Zampini 
12090369aaf7SStefano Zampini   /* set initial guess if using PCG */
12100369aaf7SStefano Zampini   if (x && pcbddc->use_exact_dirichlet_trick) {
12110369aaf7SStefano Zampini     ierr = VecSet(x,0.0);CHKERRQ(ierr);
12120369aaf7SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12130369aaf7SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12140369aaf7SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
12150369aaf7SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
12160369aaf7SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
12170369aaf7SStefano Zampini     if (ksp) {
12180369aaf7SStefano Zampini       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
12190369aaf7SStefano Zampini     }
12200369aaf7SStefano Zampini   }
1221b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
1222b0f5fe93SStefano Zampini     MatNullSpace null_space;
1223b0f5fe93SStefano Zampini     Vec          nullv;
1224b0f5fe93SStefano Zampini     PetscBool    isnull;
12254f1b2e48SStefano Zampini     PetscInt     i;
1226b0f5fe93SStefano Zampini 
12274f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1.;
1228b0f5fe93SStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&nullv);CHKERRQ(ierr);
1229b0f5fe93SStefano Zampini     ierr = VecSet(nullv,0.);CHKERRQ(ierr);
1230b0f5fe93SStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,nullv,PETSC_FALSE);CHKERRQ(ierr);
1231b0f5fe93SStefano Zampini     ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
1232b0f5fe93SStefano Zampini     ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)pc),PETSC_FALSE,1,&nullv,&null_space);CHKERRQ(ierr);
1233b0f5fe93SStefano Zampini     ierr = MatNullSpaceTest(null_space,pc->mat,&isnull);CHKERRQ(ierr);
12344f1b2e48SStefano Zampini     if (isnull) {
1235b0f5fe93SStefano Zampini       ierr = MatSetNullSpace(pc->mat,null_space);CHKERRQ(ierr);
12364f1b2e48SStefano Zampini     }
1237b0f5fe93SStefano Zampini     ierr = MatNullSpaceDestroy(&null_space);CHKERRQ(ierr);
1238b0f5fe93SStefano Zampini     ierr = VecDestroy(&nullv);CHKERRQ(ierr);
1239b0f5fe93SStefano Zampini   }
1240b0f5fe93SStefano Zampini 
124192e3dcfbSStefano Zampini   /* remove nullspace if present */
12428efcfb23SStefano Zampini   if (ksp && x && pcbddc->NullSpace) {
12438efcfb23SStefano Zampini     ierr = MatNullSpaceRemove(pcbddc->NullSpace,x);CHKERRQ(ierr);
12448d00608fSStefano Zampini     /* store the original rhs */
12458d00608fSStefano Zampini     if (copy_rhs) {
12468d00608fSStefano Zampini       ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
12478d00608fSStefano Zampini       copy_rhs = PETSC_FALSE;
12488d00608fSStefano Zampini     }
12498d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
1250d0195637SJed Brown     ierr = MatNullSpaceRemove(pcbddc->NullSpace,rhs);CHKERRQ(ierr);
1251b76ba322SStefano Zampini   }
1252534831adSStefano Zampini   PetscFunctionReturn(0);
1253534831adSStefano Zampini }
1254906d46d4SStefano Zampini 
1255534831adSStefano Zampini /* -------------------------------------------------------------------------- */
1256534831adSStefano Zampini #undef __FUNCT__
1257534831adSStefano Zampini #define __FUNCT__ "PCPostSolve_BDDC"
1258534831adSStefano Zampini /* -------------------------------------------------------------------------- */
1259534831adSStefano Zampini /*
1260534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
1261534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
1262534831adSStefano Zampini 
1263534831adSStefano Zampini    Input Parameter:
1264534831adSStefano Zampini +  pc - the preconditioner contex
1265534831adSStefano Zampini 
1266534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
1267534831adSStefano Zampini 
1268534831adSStefano Zampini    Notes:
1269534831adSStefano Zampini      The interface routine PCPostSolve() is not usually called directly by
1270534831adSStefano Zampini      the user, but instead is called by KSPSolve().
1271534831adSStefano Zampini */
1272534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1273534831adSStefano Zampini {
1274534831adSStefano Zampini   PetscErrorCode ierr;
1275534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1276534831adSStefano Zampini 
1277534831adSStefano Zampini   PetscFunctionBegin;
127877a2de6eSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix && !pcbddc->benign_original_mat) {
1279906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
1280906d46d4SStefano Zampini 
1281906d46d4SStefano Zampini     /* get change ctx */
1282906d46d4SStefano Zampini     ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
1283906d46d4SStefano Zampini 
1284906d46d4SStefano Zampini     /* restore iteration matrix */
1285906d46d4SStefano Zampini     ierr = MatDestroy(&pc->mat);CHKERRQ(ierr);
1286906d46d4SStefano Zampini     ierr = PetscObjectReference((PetscObject)change_ctx->original_mat);CHKERRQ(ierr);
1287906d46d4SStefano Zampini     pc->mat = change_ctx->original_mat;
12889c6a02ceSStefano Zampini   }
1289906d46d4SStefano Zampini 
12908666afb4SStefano Zampini   /* need to restore the local matrices */
129177a2de6eSStefano Zampini   if (pcbddc->benign_original_mat) {
12928666afb4SStefano Zampini     Mat_IS *matis = (Mat_IS*)pc->mat->data;
12938666afb4SStefano Zampini 
1294a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
1295a3df083aSStefano Zampini       ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
1296a3df083aSStefano Zampini     } else {
12975cfd9691SStefano Zampini       pcbddc->local_mat = matis->A;
12988666afb4SStefano Zampini       matis->A = pcbddc->benign_original_mat;
12995cfd9691SStefano Zampini       pcbddc->benign_original_mat = NULL;
13008666afb4SStefano Zampini     }
1301a3df083aSStefano Zampini   }
13028666afb4SStefano Zampini 
1303906d46d4SStefano Zampini   /* get solution in original basis */
1304906d46d4SStefano Zampini   if (x) {
1305906d46d4SStefano Zampini     PC_IS *pcis = (PC_IS*)(pc->data);
130606f24817SStefano Zampini 
13072d3346b4SStefano Zampini     /* restore solution on pressures */
130806a4e24aSStefano Zampini     if (pcbddc->benign_saddle_point) {
13092d3346b4SStefano Zampini       Mat_IS *matis = (Mat_IS*)pc->mat->data;
13102d3346b4SStefano Zampini 
13110369aaf7SStefano Zampini       /* add non-benign solution */
13128666afb4SStefano Zampini       ierr = VecAXPY(x,-1.0,pcbddc->benign_vec);CHKERRQ(ierr);
13130369aaf7SStefano Zampini 
13140369aaf7SStefano Zampini       /* change basis on pressures for x */
131506f24817SStefano Zampini       ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
131606f24817SStefano Zampini       ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13172d3346b4SStefano Zampini       if (pcbddc->benign_change) {
13182d3346b4SStefano Zampini         ierr = MatMult(pcbddc->benign_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
131906f24817SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
132006f24817SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13212d3346b4SStefano Zampini       } else {
132206f24817SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
132306f24817SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13242d3346b4SStefano Zampini       }
13252d3346b4SStefano Zampini     }
13269c6a02ceSStefano Zampini 
13270369aaf7SStefano Zampini     /* change basis on x */
13289c6a02ceSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix) {
13299c6a02ceSStefano Zampini       PCBDDCChange_ctx change_ctx;
13309c6a02ceSStefano Zampini 
13319c6a02ceSStefano Zampini       ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
13320369aaf7SStefano Zampini       ierr = MatMult(change_ctx->global_change,x,pcis->vec1_global);CHKERRQ(ierr);
1333906d46d4SStefano Zampini       ierr = VecCopy(pcis->vec1_global,x);CHKERRQ(ierr);
13343425bc38SStefano Zampini     }
1335534831adSStefano Zampini   }
1336906d46d4SStefano Zampini 
13373972b0daSStefano Zampini   /* add solution removed in presolve */
13386bcfc461SStefano Zampini   if (x && pcbddc->rhs_change) {
13393425bc38SStefano Zampini     ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
13403425bc38SStefano Zampini   }
1341906d46d4SStefano Zampini 
1342fb223d50SStefano Zampini   /* restore rhs to its original state */
13438d00608fSStefano Zampini   if (rhs && pcbddc->rhs_change) {
1344fb223d50SStefano Zampini     ierr = VecCopy(pcbddc->original_rhs,rhs);CHKERRQ(ierr);
1345fb223d50SStefano Zampini   }
13468d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
13478efcfb23SStefano Zampini 
13488efcfb23SStefano Zampini   /* restore ksp guess state */
13498efcfb23SStefano Zampini   if (ksp) {
13508efcfb23SStefano Zampini     ierr = KSPSetInitialGuessNonzero(ksp,pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
13518efcfb23SStefano Zampini   }
1352534831adSStefano Zampini   PetscFunctionReturn(0);
1353534831adSStefano Zampini }
1354534831adSStefano Zampini /* -------------------------------------------------------------------------- */
135553cdbc3dSStefano Zampini #undef __FUNCT__
135653cdbc3dSStefano Zampini #define __FUNCT__ "PCSetUp_BDDC"
13570c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
13580c7d97c5SJed Brown /*
13590c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
13600c7d97c5SJed Brown                   by setting data structures and options.
13610c7d97c5SJed Brown 
13620c7d97c5SJed Brown    Input Parameter:
136353cdbc3dSStefano Zampini +  pc - the preconditioner context
13640c7d97c5SJed Brown 
13650c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
13660c7d97c5SJed Brown 
13670c7d97c5SJed Brown    Notes:
13680c7d97c5SJed Brown      The interface routine PCSetUp() is not usually called directly by
13690c7d97c5SJed Brown      the user, but instead is called by PCApply() if necessary.
13700c7d97c5SJed Brown */
137153cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
13720c7d97c5SJed Brown {
13730c7d97c5SJed Brown   PetscErrorCode ierr;
13740c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
13755e8657edSStefano Zampini   Mat_IS*        matis;
137608122e43SStefano Zampini   MatNullSpace   nearnullspace;
1377c9ed8603SStefano Zampini   IS             zerodiag = NULL;
137891e8d312SStefano Zampini   PetscInt       nrows,ncols;
137908122e43SStefano Zampini   PetscBool      computetopography,computesolvers,computesubschurs;
13808de1fae6SStefano Zampini   PetscBool      computeconstraintsmatrix;
13815e8657edSStefano Zampini   PetscBool      new_nearnullspace_provided,ismatis;
13820c7d97c5SJed Brown 
13830c7d97c5SJed Brown   PetscFunctionBegin;
13845e8657edSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATIS,&ismatis);CHKERRQ(ierr);
13855e8657edSStefano Zampini   if (!ismatis) {
13865e8657edSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner requires matrix of type MATIS");
13875e8657edSStefano Zampini   }
138891e8d312SStefano Zampini   ierr = MatGetSize(pc->pmat,&nrows,&ncols);CHKERRQ(ierr);
138991e8d312SStefano Zampini   if (nrows != ncols) {
139091e8d312SStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCBDDC preconditioner requires a square preconditioning matrix");
139191e8d312SStefano Zampini   }
13925e8657edSStefano Zampini   matis = (Mat_IS*)pc->pmat->data;
1393f4ddd8eeSStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
13943b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
1395fcd409f5SStefano Zampini      Also, BDDC directly build the Dirichlet problem */
1396f4ddd8eeSStefano Zampini   /* split work */
1397674ae819SStefano Zampini   if (pc->setupcalled) {
1398d1e9a80fSBarry Smith     if (pc->flag == SAME_NONZERO_PATTERN) {
1399674ae819SStefano Zampini       computetopography = PETSC_FALSE;
1400674ae819SStefano Zampini       computesolvers = PETSC_TRUE;
1401674ae819SStefano Zampini     } else { /* DIFFERENT_NONZERO_PATTERN */
1402674ae819SStefano Zampini       computetopography = PETSC_TRUE;
1403674ae819SStefano Zampini       computesolvers = PETSC_TRUE;
1404674ae819SStefano Zampini     }
1405674ae819SStefano Zampini   } else {
1406674ae819SStefano Zampini     computetopography = PETSC_TRUE;
1407674ae819SStefano Zampini     computesolvers = PETSC_TRUE;
1408674ae819SStefano Zampini   }
1409fb180af4SStefano Zampini   if (pcbddc->recompute_topography) {
1410fb180af4SStefano Zampini     computetopography = PETSC_TRUE;
1411fb180af4SStefano Zampini   }
14128de1fae6SStefano Zampini   computeconstraintsmatrix = PETSC_FALSE;
1413b087196eSStefano Zampini 
1414b087196eSStefano Zampini   /* check parameters' compatibility */
14155a95e1ceSStefano Zampini   if (pcbddc->adaptive_threshold > 0.0 && !pcbddc->use_deluxe_scaling) {
14165a95e1ceSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot compute adaptive constraints without deluxe scaling. Rerun with -pc_bddc_use_deluxe_scaling");
14175a95e1ceSStefano Zampini   }
14185a95e1ceSStefano Zampini   pcbddc->adaptive_selection = (PetscBool)(pcbddc->adaptive_threshold > 0.0 && pcbddc->use_deluxe_scaling);
1419*bf3a8328SStefano Zampini   pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined);
1420862806e4SStefano Zampini   if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE;
1421862806e4SStefano Zampini 
14225a95e1ceSStefano Zampini   computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling);
14236816873aSStefano Zampini   if (pcbddc->faster_deluxe && pcbddc->adaptive_selection && pcbddc->use_change_of_basis) {
14246816873aSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot compute faster deluxe if adaptivity and change of basis are both requested. Rerun with -pc_bddc_deluxe_faster false");
14256816873aSStefano Zampini   }
14262d3346b4SStefano Zampini 
14272d3346b4SStefano Zampini   /* check if the iteration matrix is of type MATIS in case the benign trick has been requested */
14282d3346b4SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc->mat,MATIS,&ismatis);CHKERRQ(ierr);
142906a4e24aSStefano Zampini   if (pcbddc->benign_saddle_point && !ismatis) {
14302d3346b4SStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner with benign subspace trick requires the iteration matrix to be of type MATIS");
14312d3346b4SStefano Zampini   }
14325cfd9691SStefano Zampini   if (pcbddc->benign_saddle_point && pc->mat != pc->pmat) {
143316e386b8SStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner with benign subspace trick requires Amat == Pmat");
14345cfd9691SStefano Zampini   }
14352d3346b4SStefano Zampini 
1436f4ddd8eeSStefano Zampini   /* Get stdout for dbg */
143770cf5478SStefano Zampini   if (pcbddc->dbg_flag) {
143870cf5478SStefano Zampini     if (!pcbddc->dbg_viewer) {
143958a03d70SStefano Zampini       pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
14401575c14dSBarry Smith       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
1441f4ddd8eeSStefano Zampini     }
144258a03d70SStefano Zampini     ierr = PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1443f4ddd8eeSStefano Zampini   }
1444f4ddd8eeSStefano Zampini 
14455e8657edSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) {
14465e8657edSStefano Zampini     /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
14475e8657edSStefano Zampini     pcbddc->use_change_of_basis = PETSC_FALSE;
14485e8657edSStefano Zampini     ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
14495e8657edSStefano Zampini   } else {
1450b96c3477SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
14515e8657edSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
14525e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
1453d16cbb6bSStefano Zampini   }
1454d16cbb6bSStefano Zampini 
14554f1b2e48SStefano Zampini   /* detect local disconnected subdomains if requested and not done before */
14564f1b2e48SStefano Zampini   if (pcbddc->detect_disconnected && !pcbddc->n_local_subs) {
14574f1b2e48SStefano Zampini     ierr = MatDetectDisconnectedComponents(pcbddc->local_mat,PETSC_FALSE,&pcbddc->n_local_subs,&pcbddc->local_subs);CHKERRQ(ierr);
14584f1b2e48SStefano Zampini   }
14594f1b2e48SStefano Zampini 
14604f1b2e48SStefano Zampini   /*
14614f1b2e48SStefano Zampini      change basis on local pressures (aka zerodiag dofs)
14624f1b2e48SStefano Zampini      This should come earlier then PCISSetUp for extracting the correct subdomain matrices
14634f1b2e48SStefano Zampini   */
1464d16cbb6bSStefano Zampini   if (pcbddc->benign_saddle_point) {
14659f47a83aSStefano Zampini     PC_IS* pcis = (PC_IS*)pc->data;
14669f47a83aSStefano Zampini 
1467a3df083aSStefano Zampini     if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis) pcbddc->benign_change_explicit = PETSC_TRUE;
1468339f8db1SStefano Zampini     /* detect local saddle point and change the basis in pcbddc->local_mat */
1469339f8db1SStefano Zampini     ierr = PCBDDCBenignDetectSaddlePoint(pc,&zerodiag);CHKERRQ(ierr);
1470a3df083aSStefano Zampini     /* pop B0 mat from local mat */
1471c263805aSStefano Zampini     ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
14729f47a83aSStefano Zampini     /* set flag in pcis to not reuse submatrices during PCISCreate */
1473a3df083aSStefano Zampini     if (pc->flag == SAME_NONZERO_PATTERN && pcbddc->benign_n && !pcbddc->benign_change_explicit && !pcbddc->dbg_flag) {
1474a3df083aSStefano Zampini       pcis->reusesubmatrices = PETSC_TRUE;
1475a3df083aSStefano Zampini     } else {
14769f47a83aSStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
1477674ae819SStefano Zampini     }
1478a3df083aSStefano Zampini   }
1479f1a72664SStefano Zampini   /* propagate relevant information */
14804f1b2e48SStefano Zampini #if !defined(PETSC_USE_COMPLEX) /* workaround for reals */
14813301b35fSStefano Zampini   if (matis->A->symmetric_set) {
14823301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
14833301b35fSStefano Zampini   }
1484e496cd5dSStefano Zampini #endif
148506a4e24aSStefano Zampini   if (matis->A->symmetric_set) {
148606a4e24aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
148706a4e24aSStefano Zampini   }
148806a4e24aSStefano Zampini   if (matis->A->spd_set) {
148906a4e24aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SPD,matis->A->spd);CHKERRQ(ierr);
149006a4e24aSStefano Zampini   }
1491e496cd5dSStefano Zampini 
14925e8657edSStefano Zampini   /* Set up all the "iterative substructuring" common block without computing solvers */
14935e8657edSStefano Zampini   {
14945e8657edSStefano Zampini     Mat temp_mat;
14955e8657edSStefano Zampini 
14965e8657edSStefano Zampini     temp_mat = matis->A;
14975e8657edSStefano Zampini     matis->A = pcbddc->local_mat;
14985e8657edSStefano Zampini     ierr = PCISSetUp(pc,PETSC_FALSE);CHKERRQ(ierr);
14995e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
15005e8657edSStefano Zampini     matis->A = temp_mat;
15015e8657edSStefano Zampini   }
1502684f6988SStefano Zampini 
150381d14e9dSStefano Zampini   /* Analyze interface */
1504674ae819SStefano Zampini   if (computetopography) {
1505674ae819SStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
15068de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1507674ae819SStefano Zampini   }
1508fb8d54d4SStefano Zampini 
15095408967cSStefano Zampini   /* check existence of a divergence free extension, i.e.
15105408967cSStefano Zampini      b(v_I,p_0) = 0 for all v_I (raise error if not).
15115408967cSStefano Zampini      Also, check that PCBDDCBenignGetOrSetP0 works */
15125408967cSStefano Zampini #if defined(PETSC_USE_DEBUG)
151309f581a4SStefano Zampini   if (pcbddc->benign_saddle_point) {
15145408967cSStefano Zampini     ierr = PCBDDCBenignCheck(pc,zerodiag);CHKERRQ(ierr);
151509f581a4SStefano Zampini   }
15165408967cSStefano Zampini #endif
15174f1b2e48SStefano Zampini   ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
151806f24817SStefano Zampini 
1519b96c3477SStefano Zampini   /* Setup local dirichlet solver ksp_D and sub_schurs solvers */
1520684f6988SStefano Zampini   if (computesolvers) {
1521d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
1522d5574798SStefano Zampini 
1523d5574798SStefano Zampini     if (computesubschurs && computetopography) {
152408122e43SStefano Zampini       ierr = PCBDDCInitSubSchurs(pc);CHKERRQ(ierr);
1525b1b3d7a2SStefano Zampini     }
1526df4d28bfSStefano Zampini     if (sub_schurs->schur_explicit) {
15272070dbb6SStefano Zampini       if (computesubschurs) {
152808122e43SStefano Zampini         ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
15292070dbb6SStefano Zampini       }
1530d5574798SStefano Zampini       ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
1531d5574798SStefano Zampini     } else {
1532d5574798SStefano Zampini       ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
15332070dbb6SStefano Zampini       if (computesubschurs) {
1534d5574798SStefano Zampini         ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
1535d5574798SStefano Zampini       }
15362070dbb6SStefano Zampini     }
153708122e43SStefano Zampini     if (pcbddc->adaptive_selection) {
153808122e43SStefano Zampini       ierr = PCBDDCAdaptiveSelection(pc);CHKERRQ(ierr);
15398de1fae6SStefano Zampini       computeconstraintsmatrix = PETSC_TRUE;
1540b7eb3628SStefano Zampini     }
1541b1b3d7a2SStefano Zampini   }
1542684f6988SStefano Zampini 
1543f4ddd8eeSStefano Zampini   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1544fb8d54d4SStefano Zampini   new_nearnullspace_provided = PETSC_FALSE;
1545f4ddd8eeSStefano Zampini   ierr = MatGetNearNullSpace(pc->pmat,&nearnullspace);CHKERRQ(ierr);
1546f4ddd8eeSStefano Zampini   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1547f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* near null space attached to mat has been destroyed */
1548f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1549f4ddd8eeSStefano Zampini     } else {
1550f4ddd8eeSStefano Zampini       /* determine if the two nullspaces are different (should be lightweight) */
1551f4ddd8eeSStefano Zampini       if (nearnullspace != pcbddc->onearnullspace) {
1552f4ddd8eeSStefano Zampini         new_nearnullspace_provided = PETSC_TRUE;
1553165b64e2SStefano Zampini       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1554f4ddd8eeSStefano Zampini         PetscInt         i;
1555165b64e2SStefano Zampini         const Vec        *nearnullvecs;
1556165b64e2SStefano Zampini         PetscObjectState state;
1557165b64e2SStefano Zampini         PetscInt         nnsp_size;
1558165b64e2SStefano Zampini         ierr = MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
1559f4ddd8eeSStefano Zampini         for (i=0;i<nnsp_size;i++) {
1560f4ddd8eeSStefano Zampini           ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&state);CHKERRQ(ierr);
1561165b64e2SStefano Zampini           if (pcbddc->onearnullvecs_state[i] != state) {
1562f4ddd8eeSStefano Zampini             new_nearnullspace_provided = PETSC_TRUE;
1563f4ddd8eeSStefano Zampini             break;
1564f4ddd8eeSStefano Zampini           }
1565f4ddd8eeSStefano Zampini         }
1566f4ddd8eeSStefano Zampini       }
1567f4ddd8eeSStefano Zampini     }
1568f4ddd8eeSStefano Zampini   } else {
1569f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* both nearnullspaces are null */
1570f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_FALSE;
1571f4ddd8eeSStefano Zampini     } else { /* nearnullspace attached later */
1572f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1573f4ddd8eeSStefano Zampini     }
1574f4ddd8eeSStefano Zampini   }
1575f4ddd8eeSStefano Zampini 
1576f4ddd8eeSStefano Zampini   /* Setup constraints and related work vectors */
1577727cdba6SStefano Zampini   /* reset primal space flags */
1578f4ddd8eeSStefano Zampini   pcbddc->new_primal_space = PETSC_FALSE;
1579727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_FALSE;
15808de1fae6SStefano Zampini   if (computeconstraintsmatrix || new_nearnullspace_provided) {
1581727cdba6SStefano Zampini     /* It also sets the primal space flags */
1582674ae819SStefano Zampini     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
1583e7b262bdSStefano Zampini     /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
1584f4ddd8eeSStefano Zampini     ierr = PCBDDCSetUpLocalWorkVectors(pc);CHKERRQ(ierr);
15853975b054SStefano Zampini   }
15865e8657edSStefano Zampini 
15873975b054SStefano Zampini   if (computesolvers || pcbddc->new_primal_space) {
15885e8657edSStefano Zampini     if (pcbddc->use_change_of_basis) {
15895e8657edSStefano Zampini       PC_IS *pcis = (PC_IS*)(pc->data);
1590c263805aSStefano Zampini       Mat   temp_mat = NULL;
15915e8657edSStefano Zampini 
15924f1b2e48SStefano Zampini       if (pcbddc->benign_change) {
1593c263805aSStefano Zampini         /* insert B0 in pcbddc->local_mat */
1594c263805aSStefano Zampini         ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_FALSE);CHKERRQ(ierr);
1595f1a72664SStefano Zampini         /* swap local matrices */
1596f1a72664SStefano Zampini         ierr = MatISGetLocalMat(pc->pmat,&temp_mat);CHKERRQ(ierr);
1597f1a72664SStefano Zampini         ierr = PetscObjectReference((PetscObject)temp_mat);CHKERRQ(ierr);
1598f1a72664SStefano Zampini         ierr = MatISSetLocalMat(pc->pmat,pcbddc->local_mat);CHKERRQ(ierr);
1599f1a72664SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1600c263805aSStefano Zampini       }
16015e8657edSStefano Zampini       ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
16024f1b2e48SStefano Zampini       if (pcbddc->benign_change) {
1603c263805aSStefano Zampini         /* restore original matrix */
1604f1a72664SStefano Zampini         ierr = MatISSetLocalMat(pc->pmat,temp_mat);CHKERRQ(ierr);
1605f1a72664SStefano Zampini         ierr = PetscObjectDereference((PetscObject)temp_mat);CHKERRQ(ierr);
1606c263805aSStefano Zampini         /* pop B0 from pcbddc->local_mat */
1607c263805aSStefano Zampini         ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
1608c263805aSStefano Zampini       }
16095e8657edSStefano Zampini       /* get submatrices */
16105e8657edSStefano Zampini       ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
16115e8657edSStefano Zampini       ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
16125e8657edSStefano Zampini       ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);
16135e8657edSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr);
16145e8657edSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr);
16155e8657edSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr);
16163975b054SStefano Zampini       /* set flag in pcis to not reuse submatrices during PCISCreate */
16173975b054SStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
16189c6a02ceSStefano Zampini     } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) {
1619b96c3477SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
16205e8657edSStefano Zampini       ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
16215e8657edSStefano Zampini       pcbddc->local_mat = matis->A;
16225e8657edSStefano Zampini     }
1623b96c3477SStefano Zampini     /* SetUp coarse and local Neumann solvers */
162499cc7994SStefano Zampini     ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr);
1625b96c3477SStefano Zampini     /* SetUp Scaling operator */
1626674ae819SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
16270c7d97c5SJed Brown   }
16280369aaf7SStefano Zampini 
162958a03d70SStefano Zampini   if (pcbddc->dbg_flag) {
163058a03d70SStefano Zampini     ierr = PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
16312b510759SStefano Zampini   }
16320c7d97c5SJed Brown   PetscFunctionReturn(0);
16330c7d97c5SJed Brown }
16340c7d97c5SJed Brown 
16350c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
16360c7d97c5SJed Brown /*
163750efa1b5SStefano Zampini    PCApply_BDDC - Applies the BDDC operator to a vector.
16380c7d97c5SJed Brown 
16390c7d97c5SJed Brown    Input Parameters:
16400f202f7eSStefano Zampini +  pc - the preconditioner context
16410f202f7eSStefano Zampini -  r - input vector (global)
16420c7d97c5SJed Brown 
16430c7d97c5SJed Brown    Output Parameter:
16440c7d97c5SJed Brown .  z - output vector (global)
16450c7d97c5SJed Brown 
16460c7d97c5SJed Brown    Application Interface Routine: PCApply()
16470c7d97c5SJed Brown  */
16480c7d97c5SJed Brown #undef __FUNCT__
16490c7d97c5SJed Brown #define __FUNCT__ "PCApply_BDDC"
165053cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
16510c7d97c5SJed Brown {
16520c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
16530c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1654b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
16550c7d97c5SJed Brown   PetscErrorCode    ierr;
16563b03a366Sstefano_zampini   const PetscScalar one = 1.0;
16573b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
16582617d88aSStefano Zampini   const PetscScalar zero = 0.0;
16590c7d97c5SJed Brown 
16600c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
16610c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
1662b097fa66SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */
16630c7d97c5SJed Brown 
16640c7d97c5SJed Brown   PetscFunctionBegin;
1665015636ebSStefano Zampini   if (pcbddc->benign_saddle_point) { /* get p0 from r */
1666015636ebSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
1667efc2fbd9SStefano Zampini   }
166885c4d303SStefano Zampini   if (!pcbddc->use_exact_dirichlet_trick) {
1669b097fa66SStefano Zampini     ierr = VecCopy(r,z);CHKERRQ(ierr);
16700c7d97c5SJed Brown     /* First Dirichlet solve */
16710c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16720c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
16730c7d97c5SJed Brown     /*
16740c7d97c5SJed Brown       Assembling right hand side for BDDC operator
1675b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1676674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
16770c7d97c5SJed Brown     */
1678b097fa66SStefano Zampini     if (n_D) {
1679b097fa66SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
16800c7d97c5SJed Brown       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
16818eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
1682b097fa66SStefano Zampini       ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
1683b097fa66SStefano Zampini     } else {
1684b097fa66SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1685b097fa66SStefano Zampini     }
16860c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
16870c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1688674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
1689b76ba322SStefano Zampini   } else {
16904fee134fSStefano Zampini     if (!pcbddc->benign_apply_coarse_only) {
1691b097fa66SStefano Zampini       if (pcbddc->switch_static) {
16920bdf917eSStefano Zampini         ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr);
1693b097fa66SStefano Zampini       }
1694674ae819SStefano Zampini       ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
1695b76ba322SStefano Zampini     }
16964fee134fSStefano Zampini   }
1697b76ba322SStefano Zampini 
16982617d88aSStefano Zampini   /* Apply interface preconditioner
16992617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
1700dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
17012617d88aSStefano Zampini 
1702674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
1703674ae819SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
17040c7d97c5SJed Brown 
17053b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
17060c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17070c7d97c5SJed Brown   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1708b097fa66SStefano Zampini   if (n_B) {
17090c7d97c5SJed Brown     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
17108eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
1711b097fa66SStefano Zampini   } else if (pcbddc->switch_static) {
1712b097fa66SStefano Zampini     ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
1713b097fa66SStefano Zampini   }
1714df187020SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
1715efc2fbd9SStefano Zampini 
1716b097fa66SStefano Zampini   if (!pcbddc->use_exact_dirichlet_trick) {
1717b097fa66SStefano Zampini     if (pcbddc->switch_static) {
1718b097fa66SStefano Zampini       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
1719b097fa66SStefano Zampini     } else {
1720b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
1721b097fa66SStefano Zampini     }
17220c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
17230c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1724b097fa66SStefano Zampini   } else {
1725b097fa66SStefano Zampini     if (pcbddc->switch_static) {
1726b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
1727b097fa66SStefano Zampini     } else {
1728b097fa66SStefano Zampini       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
1729b097fa66SStefano Zampini     }
1730b097fa66SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1731b097fa66SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1732b097fa66SStefano Zampini   }
1733efc2fbd9SStefano Zampini 
1734015636ebSStefano Zampini   if (pcbddc->benign_saddle_point) { /* set p0 (computed in PCBDDCApplyInterface) */
1735015636ebSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
1736efc2fbd9SStefano Zampini   }
17370c7d97c5SJed Brown   PetscFunctionReturn(0);
17380c7d97c5SJed Brown }
173950efa1b5SStefano Zampini 
174050efa1b5SStefano Zampini /* -------------------------------------------------------------------------- */
174150efa1b5SStefano Zampini /*
174250efa1b5SStefano Zampini    PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector.
174350efa1b5SStefano Zampini 
174450efa1b5SStefano Zampini    Input Parameters:
17450f202f7eSStefano Zampini +  pc - the preconditioner context
17460f202f7eSStefano Zampini -  r - input vector (global)
174750efa1b5SStefano Zampini 
174850efa1b5SStefano Zampini    Output Parameter:
174950efa1b5SStefano Zampini .  z - output vector (global)
175050efa1b5SStefano Zampini 
175150efa1b5SStefano Zampini    Application Interface Routine: PCApplyTranspose()
175250efa1b5SStefano Zampini  */
175350efa1b5SStefano Zampini #undef __FUNCT__
175450efa1b5SStefano Zampini #define __FUNCT__ "PCApplyTranspose_BDDC"
175550efa1b5SStefano Zampini PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z)
175650efa1b5SStefano Zampini {
175750efa1b5SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
175850efa1b5SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1759b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
176050efa1b5SStefano Zampini   PetscErrorCode    ierr;
176150efa1b5SStefano Zampini   const PetscScalar one = 1.0;
176250efa1b5SStefano Zampini   const PetscScalar m_one = -1.0;
176350efa1b5SStefano Zampini   const PetscScalar zero = 0.0;
176450efa1b5SStefano Zampini 
176550efa1b5SStefano Zampini   PetscFunctionBegin;
1766537c1cdfSStefano Zampini   if (pcbddc->benign_saddle_point) { /* get p0 from r */
1767537c1cdfSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
1768537c1cdfSStefano Zampini   }
176950efa1b5SStefano Zampini   if (!pcbddc->use_exact_dirichlet_trick) {
1770b097fa66SStefano Zampini     ierr = VecCopy(r,z);CHKERRQ(ierr);
177150efa1b5SStefano Zampini     /* First Dirichlet solve */
177250efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
177350efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
177450efa1b5SStefano Zampini     /*
177550efa1b5SStefano Zampini       Assembling right hand side for BDDC operator
1776b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
177750efa1b5SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
177850efa1b5SStefano Zampini     */
1779b097fa66SStefano Zampini     if (n_D) {
1780b097fa66SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
178150efa1b5SStefano Zampini       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
178250efa1b5SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
1783b097fa66SStefano Zampini       ierr = MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
1784b097fa66SStefano Zampini     } else {
1785b097fa66SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1786b097fa66SStefano Zampini     }
178750efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
178850efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
178950efa1b5SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
179050efa1b5SStefano Zampini   } else {
1791b097fa66SStefano Zampini     if (pcbddc->switch_static) {
179250efa1b5SStefano Zampini       ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr);
1793b097fa66SStefano Zampini     }
179450efa1b5SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
179550efa1b5SStefano Zampini   }
179650efa1b5SStefano Zampini 
179750efa1b5SStefano Zampini   /* Apply interface preconditioner
179850efa1b5SStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
1799dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE);CHKERRQ(ierr);
180050efa1b5SStefano Zampini 
180150efa1b5SStefano Zampini   /* Apply transpose of partition of unity operator */
180250efa1b5SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
180350efa1b5SStefano Zampini 
180450efa1b5SStefano Zampini   /* Second Dirichlet solve and assembling of output */
180550efa1b5SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
180650efa1b5SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1807b097fa66SStefano Zampini   if (n_B) {
180850efa1b5SStefano Zampini     ierr = MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
180950efa1b5SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
1810b097fa66SStefano Zampini   } else if (pcbddc->switch_static) {
1811b097fa66SStefano Zampini     ierr = MatMultTranspose(pcis->A_II,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
1812b097fa66SStefano Zampini   }
1813b0147a47SStefano Zampini   ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
1814b097fa66SStefano Zampini   if (!pcbddc->use_exact_dirichlet_trick) {
1815b097fa66SStefano Zampini     if (pcbddc->switch_static) {
1816b097fa66SStefano Zampini       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
1817b097fa66SStefano Zampini     } else {
1818b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
1819b097fa66SStefano Zampini     }
182050efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
182150efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1822b097fa66SStefano Zampini   } else {
1823b097fa66SStefano Zampini     if (pcbddc->switch_static) {
1824b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
1825b097fa66SStefano Zampini     } else {
1826b097fa66SStefano Zampini       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
1827b097fa66SStefano Zampini     }
1828b097fa66SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1829b097fa66SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1830b097fa66SStefano Zampini   }
1831537c1cdfSStefano Zampini   if (pcbddc->benign_saddle_point) { /* set p0 (computed in PCBDDCApplyInterface) */
1832537c1cdfSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
1833537c1cdfSStefano Zampini   }
183450efa1b5SStefano Zampini   PetscFunctionReturn(0);
183550efa1b5SStefano Zampini }
1836da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
1837674ae819SStefano Zampini 
1838da1bb401SStefano Zampini #undef __FUNCT__
1839da1bb401SStefano Zampini #define __FUNCT__ "PCDestroy_BDDC"
1840da1bb401SStefano Zampini PetscErrorCode PCDestroy_BDDC(PC pc)
1841da1bb401SStefano Zampini {
1842da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1843da1bb401SStefano Zampini   PetscErrorCode ierr;
1844da1bb401SStefano Zampini 
1845da1bb401SStefano Zampini   PetscFunctionBegin;
1846da1bb401SStefano Zampini   /* free data created by PCIS */
1847da1bb401SStefano Zampini   ierr = PCISDestroy(pc);CHKERRQ(ierr);
1848674ae819SStefano Zampini   /* free BDDC custom data  */
1849674ae819SStefano Zampini   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
1850674ae819SStefano Zampini   /* destroy objects related to topography */
1851674ae819SStefano Zampini   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
1852674ae819SStefano Zampini   /* free allocated graph structure */
1853da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr);
1854b96c3477SStefano Zampini   /* free allocated sub schurs structure */
1855b96c3477SStefano Zampini   ierr = PetscFree(pcbddc->sub_schurs);CHKERRQ(ierr);
185634a97f8cSStefano Zampini   /* destroy objects for scaling operator */
1857674ae819SStefano Zampini   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
185834a97f8cSStefano Zampini   ierr = PetscFree(pcbddc->deluxe_ctx);CHKERRQ(ierr);
1859674ae819SStefano Zampini   /* free solvers stuff */
1860674ae819SStefano Zampini   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
186162a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
186262a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr);
186362a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr);
1864906d46d4SStefano Zampini   /* free stuff for change of basis hooks */
1865906d46d4SStefano Zampini   if (pcbddc->new_global_mat) {
1866906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
1867906d46d4SStefano Zampini     ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
1868906d46d4SStefano Zampini     ierr = MatDestroy(&change_ctx->original_mat);CHKERRQ(ierr);
1869906d46d4SStefano Zampini     ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr);
1870906d46d4SStefano Zampini     ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr);
1871906d46d4SStefano Zampini     ierr = PetscFree(change_ctx);CHKERRQ(ierr);
1872906d46d4SStefano Zampini   }
1873906d46d4SStefano Zampini   ierr = MatDestroy(&pcbddc->new_global_mat);CHKERRQ(ierr);
18743425bc38SStefano Zampini   /* remove functions */
1875906d46d4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL);CHKERRQ(ierr);
1876674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr);
187730368db7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",NULL);CHKERRQ(ierr);
1878bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr);
18792b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL);CHKERRQ(ierr);
1880b8ffe317SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL);CHKERRQ(ierr);
18812b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL);CHKERRQ(ierr);
1882bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",NULL);CHKERRQ(ierr);
1883bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
188482ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
1885bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
188682ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
1887bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
188882ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
1889bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
1890785d1243SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
1891bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr);
189263602bcaSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL);CHKERRQ(ierr);
1893bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr);
1894bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr);
1895bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr);
1896bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr);
1897674ae819SStefano Zampini   /* Free the private data structure */
1898674ae819SStefano Zampini   ierr = PetscFree(pc->data);CHKERRQ(ierr);
1899da1bb401SStefano Zampini   PetscFunctionReturn(0);
1900da1bb401SStefano Zampini }
19013425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
19021e6b0712SBarry Smith 
19033425bc38SStefano Zampini #undef __FUNCT__
19043425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetRHS_BDDC"
19053425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
19063425bc38SStefano Zampini {
1907674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
1908c08af4c6SStefano Zampini   Vec            copy_standard_rhs;
19093425bc38SStefano Zampini   PC_IS*         pcis;
19103425bc38SStefano Zampini   PC_BDDC*       pcbddc;
19113425bc38SStefano Zampini   PetscErrorCode ierr;
19120c7d97c5SJed Brown 
19133425bc38SStefano Zampini   PetscFunctionBegin;
19143425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
19153425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
19163425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
19173425bc38SStefano Zampini 
1918c08af4c6SStefano Zampini   /*
1919c08af4c6SStefano Zampini      change of basis for physical rhs if needed
1920c08af4c6SStefano Zampini      It also changes the rhs in case of dirichlet boundaries
1921c08af4c6SStefano Zampini      TODO: better management when FETIDP will have its own class
1922c08af4c6SStefano Zampini   */
1923c08af4c6SStefano Zampini   ierr = VecDuplicate(standard_rhs,&copy_standard_rhs);CHKERRQ(ierr);
1924c08af4c6SStefano Zampini   ierr = VecCopy(standard_rhs,copy_standard_rhs);CHKERRQ(ierr);
1925c08af4c6SStefano Zampini   ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,copy_standard_rhs,NULL);CHKERRQ(ierr);
19263425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
1927c08af4c6SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,copy_standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1928c08af4c6SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,copy_standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1929fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
1930fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
1931c08af4c6SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1932c08af4c6SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1933674ae819SStefano Zampini   /* Apply partition of unity */
19343425bc38SStefano Zampini   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
1935c08af4c6SStefano Zampini   /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,copy_standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
19368eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
19373425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
19383425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
19393425bc38SStefano Zampini     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
19403425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
1941c08af4c6SStefano Zampini     ierr = VecSet(copy_standard_rhs,0.0);CHKERRQ(ierr);
1942c08af4c6SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,copy_standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1943c08af4c6SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,copy_standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1944c08af4c6SStefano Zampini     /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,copy_standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
1945c08af4c6SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1946c08af4c6SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19473425bc38SStefano Zampini     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
19483425bc38SStefano Zampini   }
1949c08af4c6SStefano Zampini   ierr = VecDestroy(&copy_standard_rhs);CHKERRQ(ierr);
19503425bc38SStefano Zampini   /* BDDC rhs */
19513425bc38SStefano Zampini   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
19528eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
19533425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
19543425bc38SStefano Zampini   }
19553425bc38SStefano Zampini   /* apply BDDC */
1956dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
19573425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
19583425bc38SStefano Zampini   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
19593425bc38SStefano Zampini   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
19603425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19613425bc38SStefano Zampini   ierr = VecScatterEnd(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
19623425bc38SStefano Zampini   PetscFunctionReturn(0);
19633425bc38SStefano Zampini }
19641e6b0712SBarry Smith 
19653425bc38SStefano Zampini #undef __FUNCT__
19663425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetRHS"
19673425bc38SStefano Zampini /*@
19680f202f7eSStefano Zampini  PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side
19693425bc38SStefano Zampini 
19703425bc38SStefano Zampini    Collective
19713425bc38SStefano Zampini 
19723425bc38SStefano Zampini    Input Parameters:
19730f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators
19740f202f7eSStefano Zampini -  standard_rhs    - the right-hand side of the original linear system
19753425bc38SStefano Zampini 
19763425bc38SStefano Zampini    Output Parameters:
19770f202f7eSStefano Zampini .  fetidp_flux_rhs - the right-hand side for the FETI-DP linear system
19783425bc38SStefano Zampini 
19793425bc38SStefano Zampini    Level: developer
19803425bc38SStefano Zampini 
19813425bc38SStefano Zampini    Notes:
19823425bc38SStefano Zampini 
19830f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetSolution
19843425bc38SStefano Zampini @*/
19853425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
19863425bc38SStefano Zampini {
1987674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
19883425bc38SStefano Zampini   PetscErrorCode ierr;
19893425bc38SStefano Zampini 
19903425bc38SStefano Zampini   PetscFunctionBegin;
19913425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
19923425bc38SStefano Zampini   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
19933425bc38SStefano Zampini   PetscFunctionReturn(0);
19943425bc38SStefano Zampini }
19953425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
19961e6b0712SBarry Smith 
19973425bc38SStefano Zampini #undef __FUNCT__
19983425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetSolution_BDDC"
19993425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
20003425bc38SStefano Zampini {
2001674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
20023425bc38SStefano Zampini   PC_IS*         pcis;
20033425bc38SStefano Zampini   PC_BDDC*       pcbddc;
20043425bc38SStefano Zampini   PetscErrorCode ierr;
20053425bc38SStefano Zampini 
20063425bc38SStefano Zampini   PetscFunctionBegin;
20073425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
20083425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
20093425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
20103425bc38SStefano Zampini 
20113425bc38SStefano Zampini   /* apply B_delta^T */
20123425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20133425bc38SStefano Zampini   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20143425bc38SStefano Zampini   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
20153425bc38SStefano Zampini   /* compute rhs for BDDC application */
20163425bc38SStefano Zampini   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
20178eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
20183425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
20193425bc38SStefano Zampini   }
20203425bc38SStefano Zampini   /* apply BDDC */
2021dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
20223425bc38SStefano Zampini   /* put values into standard global vector */
20233425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20243425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20258eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
20263425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
20273425bc38SStefano Zampini     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
20283425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_D,-1.0,pcis->vec1_D);CHKERRQ(ierr);
20293425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
20303425bc38SStefano Zampini   }
20313425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20323425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20333425bc38SStefano Zampini   /* final change of basis if needed
20343425bc38SStefano Zampini      Is also sums the dirichlet part removed during RHS assembling */
20353308cffdSStefano Zampini   ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr);
20363425bc38SStefano Zampini   PetscFunctionReturn(0);
20373425bc38SStefano Zampini }
20381e6b0712SBarry Smith 
20393425bc38SStefano Zampini #undef __FUNCT__
20403425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetSolution"
20413425bc38SStefano Zampini /*@
20420f202f7eSStefano Zampini  PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system
20433425bc38SStefano Zampini 
20443425bc38SStefano Zampini    Collective
20453425bc38SStefano Zampini 
20463425bc38SStefano Zampini    Input Parameters:
20470f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators
20480f202f7eSStefano Zampini -  fetidp_flux_sol - the solution of the FETI-DP linear system
20493425bc38SStefano Zampini 
20503425bc38SStefano Zampini    Output Parameters:
20510f202f7eSStefano Zampini .  standard_sol    - the solution defined on the physical domain
20523425bc38SStefano Zampini 
20533425bc38SStefano Zampini    Level: developer
20543425bc38SStefano Zampini 
20553425bc38SStefano Zampini    Notes:
20563425bc38SStefano Zampini 
20570f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetRHS
20583425bc38SStefano Zampini @*/
20593425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
20603425bc38SStefano Zampini {
2061674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
20623425bc38SStefano Zampini   PetscErrorCode ierr;
20633425bc38SStefano Zampini 
20643425bc38SStefano Zampini   PetscFunctionBegin;
20653425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
20663425bc38SStefano Zampini   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
20673425bc38SStefano Zampini   PetscFunctionReturn(0);
20683425bc38SStefano Zampini }
20693425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
20701e6b0712SBarry Smith 
2071f23aa3ddSBarry Smith extern PetscErrorCode FETIDPMatMult(Mat,Vec,Vec);
2072edf7251bSStefano Zampini extern PetscErrorCode FETIDPMatMultTranspose(Mat,Vec,Vec);
2073f23aa3ddSBarry Smith extern PetscErrorCode PCBDDCDestroyFETIDPMat(Mat);
2074f23aa3ddSBarry Smith extern PetscErrorCode FETIDPPCApply(PC,Vec,Vec);
2075edf7251bSStefano Zampini extern PetscErrorCode FETIDPPCApplyTranspose(PC,Vec,Vec);
2076f23aa3ddSBarry Smith extern PetscErrorCode PCBDDCDestroyFETIDPPC(PC);
2077674ae819SStefano Zampini 
20783425bc38SStefano Zampini #undef __FUNCT__
20793425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPOperators_BDDC"
20803425bc38SStefano Zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
20813425bc38SStefano Zampini {
2082674ae819SStefano Zampini 
2083674ae819SStefano Zampini   FETIDPMat_ctx  fetidpmat_ctx;
20843425bc38SStefano Zampini   Mat            newmat;
2085674ae819SStefano Zampini   FETIDPPC_ctx   fetidppc_ctx;
20863425bc38SStefano Zampini   PC             newpc;
2087ce94432eSBarry Smith   MPI_Comm       comm;
20883425bc38SStefano Zampini   PetscErrorCode ierr;
20893425bc38SStefano Zampini 
20903425bc38SStefano Zampini   PetscFunctionBegin;
2091ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
20923425bc38SStefano Zampini   /* FETIDP linear matrix */
20933425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr);
20943425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
20953425bc38SStefano Zampini   ierr = MatCreateShell(comm,PETSC_DECIDE,PETSC_DECIDE,fetidpmat_ctx->n_lambda,fetidpmat_ctx->n_lambda,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
20963425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
2097edf7251bSStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose);CHKERRQ(ierr);
20983425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
20993425bc38SStefano Zampini   ierr = MatSetUp(newmat);CHKERRQ(ierr);
21003425bc38SStefano Zampini   /* FETIDP preconditioner */
21013425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr);
21023425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
21033425bc38SStefano Zampini   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
21043425bc38SStefano Zampini   ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
21053425bc38SStefano Zampini   ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
21063425bc38SStefano Zampini   ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
2107edf7251bSStefano Zampini   ierr = PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose);CHKERRQ(ierr);
21083425bc38SStefano Zampini   ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
210923ee1639SBarry Smith   ierr = PCSetOperators(newpc,newmat,newmat);CHKERRQ(ierr);
21103425bc38SStefano Zampini   ierr = PCSetUp(newpc);CHKERRQ(ierr);
21113425bc38SStefano Zampini   /* return pointers for objects created */
21123425bc38SStefano Zampini   *fetidp_mat=newmat;
21133425bc38SStefano Zampini   *fetidp_pc=newpc;
21143425bc38SStefano Zampini   PetscFunctionReturn(0);
21153425bc38SStefano Zampini }
21161e6b0712SBarry Smith 
21173425bc38SStefano Zampini #undef __FUNCT__
21183425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPOperators"
21193425bc38SStefano Zampini /*@
21200f202f7eSStefano Zampini  PCBDDCCreateFETIDPOperators - Create FETI-DP operators
21213425bc38SStefano Zampini 
21223425bc38SStefano Zampini    Collective
21233425bc38SStefano Zampini 
21243425bc38SStefano Zampini    Input Parameters:
21250f202f7eSStefano Zampini .  pc - the BDDC preconditioning context (setup should have been called before)
212628509bceSStefano Zampini 
212728509bceSStefano Zampini    Output Parameters:
21280f202f7eSStefano Zampini +  fetidp_mat - shell FETI-DP matrix object
21290f202f7eSStefano Zampini -  fetidp_pc  - shell Dirichlet preconditioner for FETI-DP matrix
213028509bceSStefano Zampini 
213128509bceSStefano Zampini    Options Database Keys:
21320f202f7eSStefano Zampini .    -fetidp_fullyredundant <false> - use or not a fully redundant set of Lagrange multipliers
21333425bc38SStefano Zampini 
21343425bc38SStefano Zampini    Level: developer
21353425bc38SStefano Zampini 
21363425bc38SStefano Zampini    Notes:
21370f202f7eSStefano Zampini      Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose
21383425bc38SStefano Zampini 
21390f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCMatFETIDPGetRHS, PCBDDCMatFETIDPGetSolution
21403425bc38SStefano Zampini @*/
21413425bc38SStefano Zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
21423425bc38SStefano Zampini {
21433425bc38SStefano Zampini   PetscErrorCode ierr;
21443425bc38SStefano Zampini 
21453425bc38SStefano Zampini   PetscFunctionBegin;
21463425bc38SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
21473425bc38SStefano Zampini   if (pc->setupcalled) {
2148516d51a7SStefano Zampini     ierr = PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,Mat*,PC*),(pc,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
2149f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n");
21503425bc38SStefano Zampini   PetscFunctionReturn(0);
21513425bc38SStefano Zampini }
21520c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
2153da1bb401SStefano Zampini /*MC
2154da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
21550c7d97c5SJed Brown 
215628509bceSStefano Zampini    An implementation of the BDDC preconditioner based on
215728509bceSStefano Zampini 
215828509bceSStefano Zampini .vb
215928509bceSStefano Zampini    [1] C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
216028509bceSStefano Zampini    [2] A. Klawonn and O. B. Widlund. "Dual-Primal FETI Methods for Linear Elasticity", http://cs.nyu.edu/csweb/Research/TechReports/TR2004-855/TR2004-855.pdf
216128509bceSStefano Zampini    [3] J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", http://arxiv.org/abs/0712.3977
21620f202f7eSStefano Zampini    [4] C. Pechstein and C. R. Dohrmann. "Modern domain decomposition methods BDDC, deluxe scaling, and an algebraic approach", Seminar talk, Linz, December 2013, http://people.ricam.oeaw.ac.at/c.pechstein/pechstein-bddc2013.pdf
216328509bceSStefano Zampini .ve
216428509bceSStefano Zampini 
216528509bceSStefano Zampini    The matrix to be preconditioned (Pmat) must be of type MATIS.
216628509bceSStefano Zampini 
21670f202f7eSStefano Zampini    Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers.
216828509bceSStefano Zampini 
216928509bceSStefano Zampini    It also works with unsymmetric and indefinite problems.
217028509bceSStefano Zampini 
2171b6fdb6dfSStefano Zampini    Unlike 'conventional' interface preconditioners, PCBDDC iterates over all degrees of freedom, not just those on the interface. This allows the use of approximate solvers on the subdomains.
2172b6fdb6dfSStefano Zampini 
21730f202f7eSStefano Zampini    Approximate local solvers are automatically adapted for singular linear problems (see [1]) if the user has provided the nullspace using PCBDDCSetNullSpace()
217428509bceSStefano Zampini 
21750f202f7eSStefano Zampini    Boundary nodes are split in vertices, edges and faces classes using information from the local to global mapping of dofs and the local connectivity graph of nodes. The latter can be customized by using PCBDDCSetLocalAdjacencyGraph()
217630368db7SStefano Zampini    Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesIS() and their local counterparts.
217728509bceSStefano Zampini 
21780f202f7eSStefano Zampini    Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD.
217928509bceSStefano Zampini 
21800f202f7eSStefano Zampini    Change of basis is performed similarly to [2] when requested. When more than one constraint is present on a single connected component (i.e. an edge or a face), a robust method based on local QR factorizations is used.
21810f202f7eSStefano Zampini    User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat()
218228509bceSStefano Zampini 
21830f202f7eSStefano Zampini    The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object.
218428509bceSStefano Zampini 
2185df4d28bfSStefano Zampini    Adaptive selection of primal constraints [4] is supported for SPD systems with high-contrast in the coefficients if MUMPS or MKL_PARDISO are present. Future versions of the code will also consider using PASTIX.
218628509bceSStefano Zampini 
21870f202f7eSStefano Zampini    An experimental interface to the FETI-DP method is available. FETI-DP operators could be created using PCBDDCCreateFETIDPOperators(). A stand-alone class for the FETI-DP method will be provided in the next releases.
21880f202f7eSStefano Zampini    Deluxe scaling is not supported yet for FETI-DP.
21890f202f7eSStefano Zampini 
21900f202f7eSStefano Zampini    Options Database Keys (some of them, run with -h for a complete list):
21910f202f7eSStefano Zampini 
21920f202f7eSStefano Zampini .    -pc_bddc_use_vertices <true> - use or not vertices in primal space
21930f202f7eSStefano Zampini .    -pc_bddc_use_edges <true> - use or not edges in primal space
21940f202f7eSStefano Zampini .    -pc_bddc_use_faces <false> - use or not faces in primal space
21950f202f7eSStefano Zampini .    -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems
21960f202f7eSStefano Zampini .    -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only)
21970f202f7eSStefano Zampini .    -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested
21980f202f7eSStefano Zampini .    -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1])
219928509bceSStefano Zampini .    -pc_bddc_levels <0> - maximum number of levels for multilevel
22000f202f7eSStefano Zampini .    -pc_bddc_coarsening_ratio <8> - number of subdomains which will be aggregated together at the coarser level (e.g. H/h ratio at the coarser level, significative only in the multilevel case)
22010f202f7eSStefano Zampini .    -pc_bddc_redistribute <0> - size of a subset of processors where the coarse problem will be remapped (the value is ignored if not at the coarsest level)
22020f202f7eSStefano Zampini .    -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling
22030f202f7eSStefano Zampini .    -pc_bddc_schur_layers <-1> - select the economic version of deluxe scaling by specifying the number of layers (-1 corresponds to the original deluxe scaling)
2204df4d28bfSStefano Zampini .    -pc_bddc_adaptive_threshold <0.0> - when a value greater than one is specified, adaptive selection of constraints is performed on edges and faces (requires deluxe scaling and MUMPS or MKL_PARDISO installed)
220528509bceSStefano Zampini -    -pc_bddc_check_level <0> - set verbosity level of debugging output
220628509bceSStefano Zampini 
220728509bceSStefano Zampini    Options for Dirichlet, Neumann or coarse solver can be set with
220828509bceSStefano Zampini .vb
220928509bceSStefano Zampini       -pc_bddc_dirichlet_
221028509bceSStefano Zampini       -pc_bddc_neumann_
221128509bceSStefano Zampini       -pc_bddc_coarse_
221228509bceSStefano Zampini .ve
22130f202f7eSStefano Zampini    e.g -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KPSPREONLY and PCLU.
221428509bceSStefano Zampini 
22150f202f7eSStefano Zampini    When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as
221628509bceSStefano Zampini .vb
2217312be037SStefano Zampini       -pc_bddc_dirichlet_lN_
2218312be037SStefano Zampini       -pc_bddc_neumann_lN_
2219312be037SStefano Zampini       -pc_bddc_coarse_lN_
222028509bceSStefano Zampini .ve
22210f202f7eSStefano Zampini    Note that level number ranges from the finest (0) to the coarsest (N).
22220f202f7eSStefano Zampini    In order to specify options for the BDDC operators at the coarser levels (and not for the solvers), prepend -pc_bddc_coarse_ or -pc_bddc_coarse_l to the option, e.g.
22230f202f7eSStefano Zampini .vb
22240f202f7eSStefano Zampini      -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3
22250f202f7eSStefano Zampini .ve
22260f202f7eSStefano Zampini    will use a threshold of 5 for constraints' selection at the first coarse level and will redistribute the coarse problem of the first coarse level on 3 processors
2227da1bb401SStefano Zampini 
2228da1bb401SStefano Zampini    Level: intermediate
2229da1bb401SStefano Zampini 
2230b6fdb6dfSStefano Zampini    Developer notes:
2231da1bb401SStefano Zampini 
2232da1bb401SStefano Zampini    Contributed by Stefano Zampini
2233da1bb401SStefano Zampini 
2234da1bb401SStefano Zampini .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
2235da1bb401SStefano Zampini M*/
2236b2573a8aSBarry Smith 
2237da1bb401SStefano Zampini #undef __FUNCT__
2238da1bb401SStefano Zampini #define __FUNCT__ "PCCreate_BDDC"
22398cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
2240da1bb401SStefano Zampini {
2241da1bb401SStefano Zampini   PetscErrorCode      ierr;
2242da1bb401SStefano Zampini   PC_BDDC             *pcbddc;
2243da1bb401SStefano Zampini 
2244da1bb401SStefano Zampini   PetscFunctionBegin;
2245da1bb401SStefano Zampini   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
2246b00a9115SJed Brown   ierr      = PetscNewLog(pc,&pcbddc);CHKERRQ(ierr);
2247da1bb401SStefano Zampini   pc->data  = (void*)pcbddc;
2248da1bb401SStefano Zampini 
2249da1bb401SStefano Zampini   /* create PCIS data structure */
2250da1bb401SStefano Zampini   ierr = PCISCreate(pc);CHKERRQ(ierr);
2251da1bb401SStefano Zampini 
225247d04d0dSStefano Zampini   /* BDDC customization */
225308a5cf49SStefano Zampini   pcbddc->use_local_adj       = PETSC_TRUE;
225447d04d0dSStefano Zampini   pcbddc->use_vertices        = PETSC_TRUE;
225547d04d0dSStefano Zampini   pcbddc->use_edges           = PETSC_TRUE;
225647d04d0dSStefano Zampini   pcbddc->use_faces           = PETSC_FALSE;
225747d04d0dSStefano Zampini   pcbddc->use_change_of_basis = PETSC_FALSE;
225847d04d0dSStefano Zampini   pcbddc->use_change_on_faces = PETSC_FALSE;
225947d04d0dSStefano Zampini   pcbddc->switch_static       = PETSC_FALSE;
2260fa434743SStefano Zampini   pcbddc->use_nnsp_true       = PETSC_FALSE;
2261fa434743SStefano Zampini   pcbddc->use_qr_single       = PETSC_FALSE;
22623301b35fSStefano Zampini   pcbddc->symmetric_primal    = PETSC_TRUE;
226306a4e24aSStefano Zampini   pcbddc->benign_saddle_point = PETSC_FALSE;
226447d04d0dSStefano Zampini   pcbddc->dbg_flag            = 0;
2265b9d89cd5SStefano Zampini   /* private */
2266727cdba6SStefano Zampini   pcbddc->local_primal_size          = 0;
22670e6343abSStefano Zampini   pcbddc->local_primal_size_cc       = 0;
22680e6343abSStefano Zampini   pcbddc->local_primal_ref_node      = 0;
22690e6343abSStefano Zampini   pcbddc->local_primal_ref_mult      = 0;
2270e9189074SStefano Zampini   pcbddc->n_vertices                 = 0;
2271727cdba6SStefano Zampini   pcbddc->primal_indices_local_idxs  = 0;
2272fb180af4SStefano Zampini   pcbddc->recompute_topography       = PETSC_FALSE;
227368457ee5SStefano Zampini   pcbddc->coarse_size                = -1;
2274f4ddd8eeSStefano Zampini   pcbddc->new_primal_space           = PETSC_FALSE;
2275727cdba6SStefano Zampini   pcbddc->new_primal_space_local     = PETSC_FALSE;
2276f4ddd8eeSStefano Zampini   pcbddc->global_primal_indices      = 0;
2277f4ddd8eeSStefano Zampini   pcbddc->onearnullspace             = 0;
2278f4ddd8eeSStefano Zampini   pcbddc->onearnullvecs_state        = 0;
2279674ae819SStefano Zampini   pcbddc->user_primal_vertices       = 0;
228030368db7SStefano Zampini   pcbddc->user_primal_vertices_local = 0;
22810bdf917eSStefano Zampini   pcbddc->NullSpace                  = 0;
22823972b0daSStefano Zampini   pcbddc->temp_solution              = 0;
2283534831adSStefano Zampini   pcbddc->original_rhs               = 0;
2284534831adSStefano Zampini   pcbddc->local_mat                  = 0;
2285534831adSStefano Zampini   pcbddc->ChangeOfBasisMatrix        = 0;
2286b9b85e73SStefano Zampini   pcbddc->user_ChangeOfBasisMatrix   = 0;
2287906d46d4SStefano Zampini   pcbddc->new_global_mat             = 0;
2288da1bb401SStefano Zampini   pcbddc->coarse_vec                 = 0;
2289da1bb401SStefano Zampini   pcbddc->coarse_ksp                 = 0;
2290da1bb401SStefano Zampini   pcbddc->coarse_phi_B               = 0;
2291da1bb401SStefano Zampini   pcbddc->coarse_phi_D               = 0;
229215aaf578SStefano Zampini   pcbddc->coarse_psi_B               = 0;
229315aaf578SStefano Zampini   pcbddc->coarse_psi_D               = 0;
2294da1bb401SStefano Zampini   pcbddc->vec1_P                     = 0;
2295da1bb401SStefano Zampini   pcbddc->vec1_R                     = 0;
2296da1bb401SStefano Zampini   pcbddc->vec2_R                     = 0;
2297da1bb401SStefano Zampini   pcbddc->local_auxmat1              = 0;
2298da1bb401SStefano Zampini   pcbddc->local_auxmat2              = 0;
2299da1bb401SStefano Zampini   pcbddc->R_to_B                     = 0;
2300da1bb401SStefano Zampini   pcbddc->R_to_D                     = 0;
2301da1bb401SStefano Zampini   pcbddc->ksp_D                      = 0;
2302da1bb401SStefano Zampini   pcbddc->ksp_R                      = 0;
2303da1bb401SStefano Zampini   pcbddc->NeumannBoundaries          = 0;
2304785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal     = 0;
2305785d1243SStefano Zampini   pcbddc->DirichletBoundaries        = 0;
2306785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal   = 0;
230760d44989SStefano Zampini   pcbddc->user_provided_isfordofs    = PETSC_FALSE;
230860d44989SStefano Zampini   pcbddc->n_ISForDofs                = 0;
230963602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal           = 0;
2310da1bb401SStefano Zampini   pcbddc->ISForDofs                  = 0;
231163602bcaSStefano Zampini   pcbddc->ISForDofsLocal             = 0;
2312da1bb401SStefano Zampini   pcbddc->ConstraintMatrix           = 0;
231385c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick  = PETSC_TRUE;
231447d04d0dSStefano Zampini   pcbddc->coarse_loc_to_glob         = 0;
231547d04d0dSStefano Zampini   pcbddc->coarsening_ratio           = 8;
2316b0c7d250SStefano Zampini   pcbddc->coarse_adj_red             = 0;
23174fad6a16SStefano Zampini   pcbddc->current_level              = 0;
23182b510759SStefano Zampini   pcbddc->max_levels                 = 0;
2319323d395dSStefano Zampini   pcbddc->use_coarse_estimates       = PETSC_FALSE;
232074e2c79eSStefano Zampini   pcbddc->redistribute_coarse        = 0;
2321f3bde8b3SStefano Zampini   pcbddc->coarse_subassembling       = 0;
2322323d395dSStefano Zampini   pcbddc->coarse_subassembling_init  = 0;
23234f1b2e48SStefano Zampini   pcbddc->detect_disconnected        = PETSC_FALSE;
23244f1b2e48SStefano Zampini   pcbddc->n_local_subs               = 0;
23254f1b2e48SStefano Zampini   pcbddc->local_subs                 = NULL;
232681d14e9dSStefano Zampini 
232781d14e9dSStefano Zampini   /* benign subspace trick */
232881d14e9dSStefano Zampini   pcbddc->benign_change              = 0;
23290369aaf7SStefano Zampini   pcbddc->benign_vec                 = 0;
23300369aaf7SStefano Zampini   pcbddc->benign_original_mat        = 0;
23310369aaf7SStefano Zampini   pcbddc->benign_sf                  = 0;
23324f1b2e48SStefano Zampini   pcbddc->benign_B0                  = 0;
23334f1b2e48SStefano Zampini   pcbddc->benign_n                   = 0;
23344f1b2e48SStefano Zampini   pcbddc->benign_p0                  = NULL;
23354f1b2e48SStefano Zampini   pcbddc->benign_p0_lidx             = NULL;
23364f1b2e48SStefano Zampini   pcbddc->benign_p0_gidx             = NULL;
2337b0f5fe93SStefano Zampini   pcbddc->benign_null                = PETSC_FALSE;
233881d14e9dSStefano Zampini 
2339674ae819SStefano Zampini   /* create local graph structure */
2340674ae819SStefano Zampini   ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr);
2341674ae819SStefano Zampini 
2342674ae819SStefano Zampini   /* scaling */
2343674ae819SStefano Zampini   pcbddc->work_scaling          = 0;
234434a97f8cSStefano Zampini   pcbddc->use_deluxe_scaling    = PETSC_FALSE;
2345ac632422SStefano Zampini   pcbddc->faster_deluxe         = PETSC_FALSE;
2346b96c3477SStefano Zampini 
2347b96c3477SStefano Zampini   /* create sub schurs structure */
2348b96c3477SStefano Zampini   ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
2349b96c3477SStefano Zampini   pcbddc->sub_schurs_rebuild     = PETSC_FALSE;
2350b96c3477SStefano Zampini   pcbddc->sub_schurs_layers      = -1;
2351b96c3477SStefano Zampini   pcbddc->sub_schurs_use_useradj = PETSC_FALSE;
2352b96c3477SStefano Zampini 
2353b96c3477SStefano Zampini   pcbddc->computed_rowadj = PETSC_FALSE;
2354da1bb401SStefano Zampini 
2355b7eb3628SStefano Zampini   /* adaptivity */
2356f6f667cfSStefano Zampini   pcbddc->adaptive_threshold      = 0.0;
235708122e43SStefano Zampini   pcbddc->adaptive_nmax           = 0;
2358f6f667cfSStefano Zampini   pcbddc->adaptive_nmin           = 0;
2359b7eb3628SStefano Zampini 
2360da1bb401SStefano Zampini   /* function pointers */
2361da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
236293bd9ae7SStefano Zampini   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
2363da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
2364da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
2365da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
2366da1bb401SStefano Zampini   pc->ops->view                = 0;
2367da1bb401SStefano Zampini   pc->ops->applyrichardson     = 0;
2368da1bb401SStefano Zampini   pc->ops->applysymmetricleft  = 0;
2369da1bb401SStefano Zampini   pc->ops->applysymmetricright = 0;
2370534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
2371534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
2372da1bb401SStefano Zampini 
2373da1bb401SStefano Zampini   /* composing function */
2374906d46d4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC);CHKERRQ(ierr);
2375674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
237630368db7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",PCBDDCSetPrimalVerticesIS_BDDC);CHKERRQ(ierr);
2377bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
23782b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC);CHKERRQ(ierr);
2379b8ffe317SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC);CHKERRQ(ierr);
23802b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC);CHKERRQ(ierr);
2381bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",PCBDDCSetNullSpace_BDDC);CHKERRQ(ierr);
2382bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
238382ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
2384bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
238582ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
2386bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
238782ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
2388bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
238982ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
2390bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
239163602bcaSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC);CHKERRQ(ierr);
2392bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
2393bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
2394bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
2395bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
2396da1bb401SStefano Zampini   PetscFunctionReturn(0);
2397da1bb401SStefano Zampini }
23983425bc38SStefano Zampini 
2399