xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision 14f95afae526a56f44d755db4a3eba0ba2dd44ad)
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);
49*14f95afaSStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_vertex_size","Connected components smaller or equal to vertex size will be considered as primal vertices","none",pcbddc->vertex_size,&pcbddc->vertex_size,NULL);CHKERRQ(ierr);
506661aa1dSStefano 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);
51*14f95afaSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_use_qr_single","Use QR factorization for single constraints on cc (QR is always used when multiple constraints are present)","none",pcbddc->use_qr_single,&pcbddc->use_qr_single,NULL);CHKERRQ(ierr);
528eeda7d8SStefano Zampini   /* Change of basis */
53b9b85e73SStefano 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);
54b9b85e73SStefano 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);
55674ae819SStefano Zampini   if (!pcbddc->use_change_of_basis) {
56674ae819SStefano Zampini     pcbddc->use_change_on_faces = PETSC_FALSE;
57674ae819SStefano Zampini   }
588eeda7d8SStefano Zampini   /* Switch between M_2 (default) and M_3 preconditioners (as defined by C. Dohrmann in the ref. article) */
598eeda7d8SStefano 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);
6074e2c79eSStefano 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);
610298fd71SBarry Smith   ierr = PetscOptionsInt("-pc_bddc_coarsening_ratio","Set coarsening ratio used in multilevel coarsening","none",pcbddc->coarsening_ratio,&pcbddc->coarsening_ratio,NULL);CHKERRQ(ierr);
622b510759SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_levels","Set maximum number of levels for multilevel","none",pcbddc->max_levels,&pcbddc->max_levels,NULL);CHKERRQ(ierr);
63323d395dSStefano 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);
64674ae819SStefano 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);
65b96c3477SStefano 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);
66b96c3477SStefano 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);
67b96c3477SStefano 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);
68683d3df6SStefano 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);
69bf3a8328SStefano 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);
70ac632422SStefano 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);
71bf3a8328SStefano 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);
724c6709b3SStefano 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);
7308122e43SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_adaptive_nmin","Minimum number of constraints per connected components","none",pcbddc->adaptive_nmin,&pcbddc->adaptive_nmin,NULL);CHKERRQ(ierr);
7408122e43SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_adaptive_nmax","Maximum number of constraints per connected components","none",pcbddc->adaptive_nmax,&pcbddc->adaptive_nmax,NULL);CHKERRQ(ierr);
753301b35fSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_symmetric","Symmetric computation of primal basis functions","none",pcbddc->symmetric_primal,&pcbddc->symmetric_primal,NULL);CHKERRQ(ierr);
76b0c7d250SStefano 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);
7706a4e24aSStefano 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);
784f1b2e48SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_detect_disconnected","Detects disconnected subdomains","none",pcbddc->detect_disconnected,&pcbddc->detect_disconnected,NULL);CHKERRQ(ierr);
790c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
800c7d97c5SJed Brown   PetscFunctionReturn(0);
810c7d97c5SJed Brown }
820c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
83674ae819SStefano Zampini #undef __FUNCT__
84906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCSetChangeOfBasisMat_BDDC"
85906d46d4SStefano Zampini static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change)
86b9b85e73SStefano Zampini {
87b9b85e73SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
88b9b85e73SStefano Zampini   PetscErrorCode ierr;
89b9b85e73SStefano Zampini 
90b9b85e73SStefano Zampini   PetscFunctionBegin;
91b9b85e73SStefano Zampini   ierr = PetscObjectReference((PetscObject)change);CHKERRQ(ierr);
9256282151SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
93b9b85e73SStefano Zampini   pcbddc->user_ChangeOfBasisMatrix = change;
94b9b85e73SStefano Zampini   PetscFunctionReturn(0);
95b9b85e73SStefano Zampini }
96b9b85e73SStefano Zampini #undef __FUNCT__
97906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCSetChangeOfBasisMat"
98b9b85e73SStefano Zampini /*@
99906d46d4SStefano Zampini  PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs
100b9b85e73SStefano Zampini 
101b9b85e73SStefano Zampini    Collective on PC
102b9b85e73SStefano Zampini 
103b9b85e73SStefano Zampini    Input Parameters:
104b9b85e73SStefano Zampini +  pc - the preconditioning context
105906d46d4SStefano Zampini -  change - the change of basis matrix
106b9b85e73SStefano Zampini 
107b9b85e73SStefano Zampini    Level: intermediate
108b9b85e73SStefano Zampini 
109b9b85e73SStefano Zampini    Notes:
110b9b85e73SStefano Zampini 
111b9b85e73SStefano Zampini .seealso: PCBDDC
112b9b85e73SStefano Zampini @*/
113906d46d4SStefano Zampini PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change)
114b9b85e73SStefano Zampini {
115b9b85e73SStefano Zampini   PetscErrorCode ierr;
116b9b85e73SStefano Zampini 
117b9b85e73SStefano Zampini   PetscFunctionBegin;
118b9b85e73SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
119b9b85e73SStefano Zampini   PetscValidHeaderSpecific(change,MAT_CLASSID,2);
120906d46d4SStefano Zampini   PetscCheckSameComm(pc,1,change,2);
121906d46d4SStefano Zampini   if (pc->mat) {
122906d46d4SStefano Zampini     PetscInt rows_c,cols_c,rows,cols;
123906d46d4SStefano Zampini     ierr = MatGetSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
124906d46d4SStefano Zampini     ierr = MatGetSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
125906d46d4SStefano Zampini     if (rows_c != rows) {
126906d46d4SStefano Zampini       SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of rows for change of basis matrix! %d != %d",rows_c,rows);
127906d46d4SStefano Zampini     }
128906d46d4SStefano Zampini     if (cols_c != cols) {
129906d46d4SStefano Zampini       SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of columns for change of basis matrix! %d != %d",cols_c,cols);
130906d46d4SStefano Zampini     }
131906d46d4SStefano Zampini     ierr = MatGetLocalSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
132906d46d4SStefano Zampini     ierr = MatGetLocalSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
133906d46d4SStefano Zampini     if (rows_c != rows) {
134906d46d4SStefano Zampini       SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local rows for change of basis matrix! %d != %d",rows_c,rows);
135906d46d4SStefano Zampini     }
136906d46d4SStefano Zampini     if (cols_c != cols) {
137906d46d4SStefano Zampini       SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local columns for change of basis matrix! %d != %d",cols_c,cols);
138906d46d4SStefano Zampini     }
139906d46d4SStefano Zampini   }
140906d46d4SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetChangeOfBasisMat_C",(PC,Mat),(pc,change));CHKERRQ(ierr);
141b9b85e73SStefano Zampini   PetscFunctionReturn(0);
142b9b85e73SStefano Zampini }
143b9b85e73SStefano Zampini /* -------------------------------------------------------------------------- */
144b9b85e73SStefano Zampini #undef __FUNCT__
14530368db7SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesIS_BDDC"
14630368db7SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices)
14730368db7SStefano Zampini {
14830368db7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
14956282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
15030368db7SStefano Zampini   PetscErrorCode ierr;
15130368db7SStefano Zampini 
15230368db7SStefano Zampini   PetscFunctionBegin;
15356282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
15456282151SStefano Zampini   if (pcbddc->user_primal_vertices) {
15556282151SStefano Zampini     ierr = ISEqual(PrimalVertices,pcbddc->user_primal_vertices,&isequal);CHKERRQ(ierr);
15656282151SStefano Zampini   }
15730368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
15830368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
15930368db7SStefano Zampini   pcbddc->user_primal_vertices = PrimalVertices;
16056282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
16130368db7SStefano Zampini   PetscFunctionReturn(0);
16230368db7SStefano Zampini }
16330368db7SStefano Zampini #undef __FUNCT__
16430368db7SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesIS"
16530368db7SStefano Zampini /*@
16630368db7SStefano Zampini  PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in PCBDDC
16730368db7SStefano Zampini 
16830368db7SStefano Zampini    Collective
16930368db7SStefano Zampini 
17030368db7SStefano Zampini    Input Parameters:
17130368db7SStefano Zampini +  pc - the preconditioning context
17230368db7SStefano Zampini -  PrimalVertices - index set of primal vertices in global numbering (can be empty)
17330368db7SStefano Zampini 
17430368db7SStefano Zampini    Level: intermediate
17530368db7SStefano Zampini 
17630368db7SStefano Zampini    Notes:
17730368db7SStefano Zampini      Any process can list any global node
17830368db7SStefano Zampini 
17930368db7SStefano Zampini .seealso: PCBDDC
18030368db7SStefano Zampini @*/
18130368db7SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices)
18230368db7SStefano Zampini {
18330368db7SStefano Zampini   PetscErrorCode ierr;
18430368db7SStefano Zampini 
18530368db7SStefano Zampini   PetscFunctionBegin;
18630368db7SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
18730368db7SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
18830368db7SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
18930368db7SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
19030368db7SStefano Zampini   PetscFunctionReturn(0);
19130368db7SStefano Zampini }
19230368db7SStefano Zampini /* -------------------------------------------------------------------------- */
19330368db7SStefano Zampini #undef __FUNCT__
194674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS_BDDC"
195674ae819SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
196674ae819SStefano Zampini {
197674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
19856282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
199674ae819SStefano Zampini   PetscErrorCode ierr;
2001e6b0712SBarry Smith 
201674ae819SStefano Zampini   PetscFunctionBegin;
20256282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
20356282151SStefano Zampini   if (pcbddc->user_primal_vertices_local) {
20456282151SStefano Zampini     ierr = ISEqual(PrimalVertices,pcbddc->user_primal_vertices_local,&isequal);CHKERRQ(ierr);
20556282151SStefano Zampini   }
206674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
20730368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
20830368db7SStefano Zampini   pcbddc->user_primal_vertices_local = PrimalVertices;
20956282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
210674ae819SStefano Zampini   PetscFunctionReturn(0);
211674ae819SStefano Zampini }
212674ae819SStefano Zampini #undef __FUNCT__
213674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS"
214674ae819SStefano Zampini /*@
21528509bceSStefano Zampini  PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC
216674ae819SStefano Zampini 
21717eb1463SStefano Zampini    Collective
218674ae819SStefano Zampini 
219674ae819SStefano Zampini    Input Parameters:
220674ae819SStefano Zampini +  pc - the preconditioning context
22117eb1463SStefano Zampini -  PrimalVertices - index set of primal vertices in local numbering (can be empty)
222674ae819SStefano Zampini 
223674ae819SStefano Zampini    Level: intermediate
224674ae819SStefano Zampini 
225674ae819SStefano Zampini    Notes:
226674ae819SStefano Zampini 
227674ae819SStefano Zampini .seealso: PCBDDC
228674ae819SStefano Zampini @*/
229674ae819SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
230674ae819SStefano Zampini {
231674ae819SStefano Zampini   PetscErrorCode ierr;
232674ae819SStefano Zampini 
233674ae819SStefano Zampini   PetscFunctionBegin;
234674ae819SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
235674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
23617eb1463SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
237674ae819SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
238674ae819SStefano Zampini   PetscFunctionReturn(0);
239674ae819SStefano Zampini }
240674ae819SStefano Zampini /* -------------------------------------------------------------------------- */
2410c7d97c5SJed Brown #undef __FUNCT__
2424fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetCoarseningRatio_BDDC"
2434fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)
2444fad6a16SStefano Zampini {
2454fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
2464fad6a16SStefano Zampini 
2474fad6a16SStefano Zampini   PetscFunctionBegin;
2484fad6a16SStefano Zampini   pcbddc->coarsening_ratio = k;
2494fad6a16SStefano Zampini   PetscFunctionReturn(0);
2504fad6a16SStefano Zampini }
2511e6b0712SBarry Smith 
2524fad6a16SStefano Zampini #undef __FUNCT__
2534fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetCoarseningRatio"
2544fad6a16SStefano Zampini /*@
25528509bceSStefano Zampini  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel
2564fad6a16SStefano Zampini 
2574fad6a16SStefano Zampini    Logically collective on PC
2584fad6a16SStefano Zampini 
2594fad6a16SStefano Zampini    Input Parameters:
2604fad6a16SStefano Zampini +  pc - the preconditioning context
26128509bceSStefano Zampini -  k - coarsening ratio (H/h at the coarser level)
2624fad6a16SStefano Zampini 
2630f202f7eSStefano Zampini    Options Database Keys:
2640f202f7eSStefano Zampini .    -pc_bddc_coarsening_ratio
2654fad6a16SStefano Zampini 
2664fad6a16SStefano Zampini    Level: intermediate
2674fad6a16SStefano Zampini 
2684fad6a16SStefano Zampini    Notes:
2690f202f7eSStefano Zampini      Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level
2704fad6a16SStefano Zampini 
2710f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetLevels()
2724fad6a16SStefano Zampini @*/
2734fad6a16SStefano Zampini PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k)
2744fad6a16SStefano Zampini {
2754fad6a16SStefano Zampini   PetscErrorCode ierr;
2764fad6a16SStefano Zampini 
2774fad6a16SStefano Zampini   PetscFunctionBegin;
2784fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
2792b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,k,2);
2804fad6a16SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr);
2814fad6a16SStefano Zampini   PetscFunctionReturn(0);
2824fad6a16SStefano Zampini }
2832b510759SStefano Zampini 
284b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */
2852b510759SStefano Zampini #undef __FUNCT__
286b8ffe317SStefano Zampini #define __FUNCT__ "PCBDDCSetUseExactDirichlet_BDDC"
287b8ffe317SStefano Zampini static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg)
288b8ffe317SStefano Zampini {
289b8ffe317SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
290b8ffe317SStefano Zampini 
291b8ffe317SStefano Zampini   PetscFunctionBegin;
29285c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = flg;
293b8ffe317SStefano Zampini   PetscFunctionReturn(0);
294b8ffe317SStefano Zampini }
295b8ffe317SStefano Zampini 
296b8ffe317SStefano Zampini #undef __FUNCT__
297b8ffe317SStefano Zampini #define __FUNCT__ "PCBDDCSetUseExactDirichlet"
298b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg)
2992b510759SStefano Zampini {
3002b510759SStefano Zampini   PetscErrorCode ierr;
3012b510759SStefano Zampini 
3022b510759SStefano Zampini   PetscFunctionBegin;
3032b510759SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
304b8ffe317SStefano Zampini   PetscValidLogicalCollectiveBool(pc,flg,2);
305b8ffe317SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetUseExactDirichlet_C",(PC,PetscBool),(pc,flg));CHKERRQ(ierr);
3062b510759SStefano Zampini   PetscFunctionReturn(0);
3072b510759SStefano Zampini }
3081e6b0712SBarry Smith 
3094fad6a16SStefano Zampini #undef __FUNCT__
3102b510759SStefano Zampini #define __FUNCT__ "PCBDDCSetLevel_BDDC"
3112b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc,PetscInt level)
3124fad6a16SStefano Zampini {
3134fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
3144fad6a16SStefano Zampini 
3154fad6a16SStefano Zampini   PetscFunctionBegin;
3162b510759SStefano Zampini   pcbddc->current_level = level;
3174fad6a16SStefano Zampini   PetscFunctionReturn(0);
3184fad6a16SStefano Zampini }
3191e6b0712SBarry Smith 
3204fad6a16SStefano Zampini #undef __FUNCT__
321b8ffe317SStefano Zampini #define __FUNCT__ "PCBDDCSetLevel"
322b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
323b8ffe317SStefano Zampini {
324b8ffe317SStefano Zampini   PetscErrorCode ierr;
325b8ffe317SStefano Zampini 
326b8ffe317SStefano Zampini   PetscFunctionBegin;
327b8ffe317SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
328b8ffe317SStefano Zampini   PetscValidLogicalCollectiveInt(pc,level,2);
329b8ffe317SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLevel_C",(PC,PetscInt),(pc,level));CHKERRQ(ierr);
330b8ffe317SStefano Zampini   PetscFunctionReturn(0);
331b8ffe317SStefano Zampini }
332b8ffe317SStefano Zampini 
333b8ffe317SStefano Zampini #undef __FUNCT__
3342b510759SStefano Zampini #define __FUNCT__ "PCBDDCSetLevels_BDDC"
3352b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc,PetscInt levels)
3362b510759SStefano Zampini {
3372b510759SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
3382b510759SStefano Zampini 
3392b510759SStefano Zampini   PetscFunctionBegin;
3402b510759SStefano Zampini   pcbddc->max_levels = levels;
3412b510759SStefano Zampini   PetscFunctionReturn(0);
3422b510759SStefano Zampini }
3432b510759SStefano Zampini 
3442b510759SStefano Zampini #undef __FUNCT__
3452b510759SStefano Zampini #define __FUNCT__ "PCBDDCSetLevels"
3464fad6a16SStefano Zampini /*@
34728509bceSStefano Zampini  PCBDDCSetLevels - Sets the maximum number of levels for multilevel
3484fad6a16SStefano Zampini 
3494fad6a16SStefano Zampini    Logically collective on PC
3504fad6a16SStefano Zampini 
3514fad6a16SStefano Zampini    Input Parameters:
3524fad6a16SStefano Zampini +  pc - the preconditioning context
35328509bceSStefano Zampini -  levels - the maximum number of levels (max 9)
3544fad6a16SStefano Zampini 
3550f202f7eSStefano Zampini    Options Database Keys:
3560f202f7eSStefano Zampini .    -pc_bddc_levels
3574fad6a16SStefano Zampini 
3584fad6a16SStefano Zampini    Level: intermediate
3594fad6a16SStefano Zampini 
3604fad6a16SStefano Zampini    Notes:
3610f202f7eSStefano Zampini      Default value is 0, i.e. traditional one-level BDDC
3624fad6a16SStefano Zampini 
3630f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetCoarseningRatio()
3644fad6a16SStefano Zampini @*/
3652b510759SStefano Zampini PetscErrorCode PCBDDCSetLevels(PC pc,PetscInt levels)
3664fad6a16SStefano Zampini {
3674fad6a16SStefano Zampini   PetscErrorCode ierr;
3684fad6a16SStefano Zampini 
3694fad6a16SStefano Zampini   PetscFunctionBegin;
3704fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
3712b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,levels,2);
372312be037SStefano Zampini   if (levels > 99) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Maximum number of levels for bddc is 99\n");
3732b510759SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLevels_C",(PC,PetscInt),(pc,levels));CHKERRQ(ierr);
3744fad6a16SStefano Zampini   PetscFunctionReturn(0);
3754fad6a16SStefano Zampini }
3764fad6a16SStefano Zampini /* -------------------------------------------------------------------------- */
3771e6b0712SBarry Smith 
3784fad6a16SStefano Zampini #undef __FUNCT__
3790bdf917eSStefano Zampini #define __FUNCT__ "PCBDDCSetNullSpace_BDDC"
3800bdf917eSStefano Zampini static PetscErrorCode PCBDDCSetNullSpace_BDDC(PC pc,MatNullSpace NullSpace)
3810bdf917eSStefano Zampini {
3820bdf917eSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
3830bdf917eSStefano Zampini   PetscErrorCode ierr;
3840bdf917eSStefano Zampini 
3850bdf917eSStefano Zampini   PetscFunctionBegin;
3860bdf917eSStefano Zampini   ierr = PetscObjectReference((PetscObject)NullSpace);CHKERRQ(ierr);
3870bdf917eSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
3880bdf917eSStefano Zampini   pcbddc->NullSpace = NullSpace;
3890bdf917eSStefano Zampini   PetscFunctionReturn(0);
3900bdf917eSStefano Zampini }
3911e6b0712SBarry Smith 
3920bdf917eSStefano Zampini #undef __FUNCT__
3930bdf917eSStefano Zampini #define __FUNCT__ "PCBDDCSetNullSpace"
3940bdf917eSStefano Zampini /*@
39528509bceSStefano Zampini  PCBDDCSetNullSpace - Set nullspace for BDDC operator
3960bdf917eSStefano Zampini 
3970bdf917eSStefano Zampini    Logically collective on PC and MatNullSpace
3980bdf917eSStefano Zampini 
3990bdf917eSStefano Zampini    Input Parameters:
4000bdf917eSStefano Zampini +  pc - the preconditioning context
40128509bceSStefano Zampini -  NullSpace - Null space of the linear operator to be preconditioned (Pmat)
4020bdf917eSStefano Zampini 
4030bdf917eSStefano Zampini    Level: intermediate
4040bdf917eSStefano Zampini 
4050bdf917eSStefano Zampini    Notes:
4060bdf917eSStefano Zampini 
4070bdf917eSStefano Zampini .seealso: PCBDDC
4080bdf917eSStefano Zampini @*/
4090bdf917eSStefano Zampini PetscErrorCode PCBDDCSetNullSpace(PC pc,MatNullSpace NullSpace)
4100bdf917eSStefano Zampini {
4110bdf917eSStefano Zampini   PetscErrorCode ierr;
4120bdf917eSStefano Zampini 
4130bdf917eSStefano Zampini   PetscFunctionBegin;
4140bdf917eSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
415674ae819SStefano Zampini   PetscValidHeaderSpecific(NullSpace,MAT_NULLSPACE_CLASSID,2);
4162b510759SStefano Zampini   PetscCheckSameComm(pc,1,NullSpace,2);
4170bdf917eSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNullSpace_C",(PC,MatNullSpace),(pc,NullSpace));CHKERRQ(ierr);
4180bdf917eSStefano Zampini   PetscFunctionReturn(0);
4190bdf917eSStefano Zampini }
4200bdf917eSStefano Zampini /* -------------------------------------------------------------------------- */
4211e6b0712SBarry Smith 
4220bdf917eSStefano Zampini #undef __FUNCT__
4233b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries_BDDC"
4243b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
4253b03a366Sstefano_zampini {
4263b03a366Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
42756282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
4283b03a366Sstefano_zampini   PetscErrorCode ierr;
4293b03a366Sstefano_zampini 
4303b03a366Sstefano_zampini   PetscFunctionBegin;
43156282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
43256282151SStefano Zampini   if (pcbddc->DirichletBoundaries) {
43356282151SStefano Zampini     ierr = ISEqual(DirichletBoundaries,pcbddc->DirichletBoundaries,&isequal);CHKERRQ(ierr);
43456282151SStefano Zampini   }
435785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
436785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
4373b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
43836e030ebSStefano Zampini   pcbddc->DirichletBoundaries = DirichletBoundaries;
43956282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
4403b03a366Sstefano_zampini   PetscFunctionReturn(0);
4413b03a366Sstefano_zampini }
4421e6b0712SBarry Smith 
4433b03a366Sstefano_zampini #undef __FUNCT__
4443b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries"
4453b03a366Sstefano_zampini /*@
44628509bceSStefano Zampini  PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem.
4473b03a366Sstefano_zampini 
448785d1243SStefano Zampini    Collective
4493b03a366Sstefano_zampini 
4503b03a366Sstefano_zampini    Input Parameters:
4513b03a366Sstefano_zampini +  pc - the preconditioning context
452785d1243SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries
4533b03a366Sstefano_zampini 
4543b03a366Sstefano_zampini    Level: intermediate
4553b03a366Sstefano_zampini 
4560f202f7eSStefano Zampini    Notes:
4570f202f7eSStefano Zampini      Provide the information if you used MatZeroRows/Columns routines. Any process can list any global node
4583b03a366Sstefano_zampini 
4590f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundariesLocal(), MatZeroRows(), MatZeroRowsColumns()
4603b03a366Sstefano_zampini @*/
4613b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
4623b03a366Sstefano_zampini {
4633b03a366Sstefano_zampini   PetscErrorCode ierr;
4643b03a366Sstefano_zampini 
4653b03a366Sstefano_zampini   PetscFunctionBegin;
4663b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
467674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
468785d1243SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
4693b03a366Sstefano_zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
4703b03a366Sstefano_zampini   PetscFunctionReturn(0);
4713b03a366Sstefano_zampini }
4723b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
4731e6b0712SBarry Smith 
4743b03a366Sstefano_zampini #undef __FUNCT__
47582ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCSetDirichletBoundariesLocal_BDDC"
47682ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc,IS DirichletBoundaries)
4770c7d97c5SJed Brown {
4780c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
47956282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
4800c7d97c5SJed Brown   PetscErrorCode ierr;
4810c7d97c5SJed Brown 
4820c7d97c5SJed Brown   PetscFunctionBegin;
48356282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
48456282151SStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
48556282151SStefano Zampini     ierr = ISEqual(DirichletBoundaries,pcbddc->DirichletBoundariesLocal,&isequal);CHKERRQ(ierr);
48656282151SStefano Zampini   }
487785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
488785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
4890c7d97c5SJed Brown   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
490785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal = DirichletBoundaries;
49156282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
4920c7d97c5SJed Brown   PetscFunctionReturn(0);
4930c7d97c5SJed Brown }
4940c7d97c5SJed Brown 
4950c7d97c5SJed Brown #undef __FUNCT__
49682ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCSetDirichletBoundariesLocal"
4979c0446d6SStefano Zampini /*@
49882ba6b80SStefano Zampini  PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering.
4999c0446d6SStefano Zampini 
500785d1243SStefano Zampini    Collective
50153cdbc3dSStefano Zampini 
50253cdbc3dSStefano Zampini    Input Parameters:
50353cdbc3dSStefano Zampini +  pc - the preconditioning context
50482ba6b80SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering)
50553cdbc3dSStefano Zampini 
50653cdbc3dSStefano Zampini    Level: intermediate
50753cdbc3dSStefano Zampini 
5089c0446d6SStefano Zampini    Notes:
50953cdbc3dSStefano Zampini 
5100f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundaries(), MatZeroRows(), MatZeroRowsColumns()
51153cdbc3dSStefano Zampini @*/
51282ba6b80SStefano Zampini PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc,IS DirichletBoundaries)
5130c7d97c5SJed Brown {
5140c7d97c5SJed Brown   PetscErrorCode ierr;
5150c7d97c5SJed Brown 
5160c7d97c5SJed Brown   PetscFunctionBegin;
5170c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
5180c7d97c5SJed Brown   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
51982ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
52082ba6b80SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundariesLocal_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
5210c7d97c5SJed Brown   PetscFunctionReturn(0);
5220c7d97c5SJed Brown }
5230c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
5240c7d97c5SJed Brown 
5250c7d97c5SJed Brown #undef __FUNCT__
5260c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
52753cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
5280c7d97c5SJed Brown {
5290c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
53056282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
53153cdbc3dSStefano Zampini   PetscErrorCode ierr;
5320c7d97c5SJed Brown 
5330c7d97c5SJed Brown   PetscFunctionBegin;
53456282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
53556282151SStefano Zampini   if (pcbddc->NeumannBoundaries) {
53656282151SStefano Zampini     ierr = ISEqual(NeumannBoundaries,pcbddc->NeumannBoundaries,&isequal);CHKERRQ(ierr);
53756282151SStefano Zampini   }
538785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
539785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
54053cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
54136e030ebSStefano Zampini   pcbddc->NeumannBoundaries = NeumannBoundaries;
54256282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
5430c7d97c5SJed Brown   PetscFunctionReturn(0);
5440c7d97c5SJed Brown }
5451e6b0712SBarry Smith 
5460c7d97c5SJed Brown #undef __FUNCT__
5470c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
54857527edcSJed Brown /*@
54928509bceSStefano Zampini  PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem.
55057527edcSJed Brown 
551785d1243SStefano Zampini    Collective
55257527edcSJed Brown 
55357527edcSJed Brown    Input Parameters:
55457527edcSJed Brown +  pc - the preconditioning context
555785d1243SStefano Zampini -  NeumannBoundaries - parallel IS defining the Neumann boundaries
55657527edcSJed Brown 
55757527edcSJed Brown    Level: intermediate
55857527edcSJed Brown 
5590f202f7eSStefano Zampini    Notes:
5600f202f7eSStefano Zampini      Any process can list any global node
56157527edcSJed Brown 
5620f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundariesLocal()
56357527edcSJed Brown @*/
56453cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
5650c7d97c5SJed Brown {
5660c7d97c5SJed Brown   PetscErrorCode ierr;
5670c7d97c5SJed Brown 
5680c7d97c5SJed Brown   PetscFunctionBegin;
5690c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
570674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
571785d1243SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
57253cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
57353cdbc3dSStefano Zampini   PetscFunctionReturn(0);
57453cdbc3dSStefano Zampini }
57553cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
5761e6b0712SBarry Smith 
57753cdbc3dSStefano Zampini #undef __FUNCT__
57882ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCSetNeumannBoundariesLocal_BDDC"
57982ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc,IS NeumannBoundaries)
5800c7d97c5SJed Brown {
5810c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
58256282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
5830c7d97c5SJed Brown   PetscErrorCode ierr;
5840c7d97c5SJed Brown 
5850c7d97c5SJed Brown   PetscFunctionBegin;
58656282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
58756282151SStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
58856282151SStefano Zampini     ierr = ISEqual(NeumannBoundaries,pcbddc->NeumannBoundariesLocal,&isequal);CHKERRQ(ierr);
58956282151SStefano Zampini   }
590785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
591785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
5920c7d97c5SJed Brown   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
593785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal = NeumannBoundaries;
59456282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
5950c7d97c5SJed Brown   PetscFunctionReturn(0);
5960c7d97c5SJed Brown }
5970c7d97c5SJed Brown 
5980c7d97c5SJed Brown #undef __FUNCT__
59982ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCSetNeumannBoundariesLocal"
6000c7d97c5SJed Brown /*@
60182ba6b80SStefano Zampini  PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering.
6020c7d97c5SJed Brown 
603785d1243SStefano Zampini    Collective
6040c7d97c5SJed Brown 
6050c7d97c5SJed Brown    Input Parameters:
6060c7d97c5SJed Brown +  pc - the preconditioning context
60782ba6b80SStefano Zampini -  NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering)
6080c7d97c5SJed Brown 
6090c7d97c5SJed Brown    Level: intermediate
6100c7d97c5SJed Brown 
6110c7d97c5SJed Brown    Notes:
6120c7d97c5SJed Brown 
6130f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundaries()
6140c7d97c5SJed Brown @*/
61582ba6b80SStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc,IS NeumannBoundaries)
6160c7d97c5SJed Brown {
6170c7d97c5SJed Brown   PetscErrorCode ierr;
6180c7d97c5SJed Brown 
6190c7d97c5SJed Brown   PetscFunctionBegin;
6200c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
6210c7d97c5SJed Brown   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
62282ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
62382ba6b80SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundariesLocal_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
62453cdbc3dSStefano Zampini   PetscFunctionReturn(0);
62553cdbc3dSStefano Zampini }
62653cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
62753cdbc3dSStefano Zampini 
62853cdbc3dSStefano Zampini #undef __FUNCT__
629da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries_BDDC"
630da1bb401SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
631da1bb401SStefano Zampini {
632da1bb401SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
633da1bb401SStefano Zampini 
634da1bb401SStefano Zampini   PetscFunctionBegin;
635da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
636da1bb401SStefano Zampini   PetscFunctionReturn(0);
637da1bb401SStefano Zampini }
6381e6b0712SBarry Smith 
639da1bb401SStefano Zampini #undef __FUNCT__
640da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries"
641da1bb401SStefano Zampini /*@
642785d1243SStefano Zampini  PCBDDCGetDirichletBoundaries - Get parallel IS for Dirichlet boundaries
643da1bb401SStefano Zampini 
644785d1243SStefano Zampini    Collective
645785d1243SStefano Zampini 
646785d1243SStefano Zampini    Input Parameters:
647785d1243SStefano Zampini .  pc - the preconditioning context
648785d1243SStefano Zampini 
649785d1243SStefano Zampini    Output Parameters:
650785d1243SStefano Zampini .  DirichletBoundaries - index set defining the Dirichlet boundaries
651785d1243SStefano Zampini 
652785d1243SStefano Zampini    Level: intermediate
653785d1243SStefano Zampini 
6540f202f7eSStefano Zampini    Notes:
6550f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetDirichletBoundaries
656785d1243SStefano Zampini 
657785d1243SStefano Zampini .seealso: PCBDDC
658785d1243SStefano Zampini @*/
659785d1243SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
660785d1243SStefano Zampini {
661785d1243SStefano Zampini   PetscErrorCode ierr;
662785d1243SStefano Zampini 
663785d1243SStefano Zampini   PetscFunctionBegin;
664785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
665785d1243SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
666785d1243SStefano Zampini   PetscFunctionReturn(0);
667785d1243SStefano Zampini }
668785d1243SStefano Zampini /* -------------------------------------------------------------------------- */
669785d1243SStefano Zampini 
670785d1243SStefano Zampini #undef __FUNCT__
671785d1243SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundariesLocal_BDDC"
672785d1243SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc,IS *DirichletBoundaries)
673785d1243SStefano Zampini {
674785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
675785d1243SStefano Zampini 
676785d1243SStefano Zampini   PetscFunctionBegin;
677785d1243SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundariesLocal;
678785d1243SStefano Zampini   PetscFunctionReturn(0);
679785d1243SStefano Zampini }
680785d1243SStefano Zampini 
681785d1243SStefano Zampini #undef __FUNCT__
68282ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundariesLocal"
683da1bb401SStefano Zampini /*@
68482ba6b80SStefano Zampini  PCBDDCGetDirichletBoundariesLocal - Get parallel IS for Dirichlet boundaries (in local ordering)
685da1bb401SStefano Zampini 
686785d1243SStefano Zampini    Collective
687da1bb401SStefano Zampini 
688da1bb401SStefano Zampini    Input Parameters:
68928509bceSStefano Zampini .  pc - the preconditioning context
690da1bb401SStefano Zampini 
691da1bb401SStefano Zampini    Output Parameters:
69228509bceSStefano Zampini .  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
693da1bb401SStefano Zampini 
694da1bb401SStefano Zampini    Level: intermediate
695da1bb401SStefano Zampini 
696da1bb401SStefano Zampini    Notes:
6970f202f7eSStefano 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).
6980f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
699da1bb401SStefano Zampini 
700da1bb401SStefano Zampini .seealso: PCBDDC
701da1bb401SStefano Zampini @*/
70282ba6b80SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc,IS *DirichletBoundaries)
703da1bb401SStefano Zampini {
704da1bb401SStefano Zampini   PetscErrorCode ierr;
705da1bb401SStefano Zampini 
706da1bb401SStefano Zampini   PetscFunctionBegin;
707da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
70882ba6b80SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundariesLocal_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
709da1bb401SStefano Zampini   PetscFunctionReturn(0);
710da1bb401SStefano Zampini }
711da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
7121e6b0712SBarry Smith 
713da1bb401SStefano Zampini #undef __FUNCT__
71453cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
71553cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
71653cdbc3dSStefano Zampini {
71753cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
71853cdbc3dSStefano Zampini 
71953cdbc3dSStefano Zampini   PetscFunctionBegin;
72053cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
72153cdbc3dSStefano Zampini   PetscFunctionReturn(0);
72253cdbc3dSStefano Zampini }
7231e6b0712SBarry Smith 
72453cdbc3dSStefano Zampini #undef __FUNCT__
72553cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
72653cdbc3dSStefano Zampini /*@
727785d1243SStefano Zampini  PCBDDCGetNeumannBoundaries - Get parallel IS for Neumann boundaries
72853cdbc3dSStefano Zampini 
729785d1243SStefano Zampini    Collective
730785d1243SStefano Zampini 
731785d1243SStefano Zampini    Input Parameters:
732785d1243SStefano Zampini .  pc - the preconditioning context
733785d1243SStefano Zampini 
734785d1243SStefano Zampini    Output Parameters:
735785d1243SStefano Zampini .  NeumannBoundaries - index set defining the Neumann boundaries
736785d1243SStefano Zampini 
737785d1243SStefano Zampini    Level: intermediate
738785d1243SStefano Zampini 
7390f202f7eSStefano Zampini    Notes:
7400f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetNeumannBoundaries
741785d1243SStefano Zampini 
742785d1243SStefano Zampini .seealso: PCBDDC
743785d1243SStefano Zampini @*/
744785d1243SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
745785d1243SStefano Zampini {
746785d1243SStefano Zampini   PetscErrorCode ierr;
747785d1243SStefano Zampini 
748785d1243SStefano Zampini   PetscFunctionBegin;
749785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
750785d1243SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
751785d1243SStefano Zampini   PetscFunctionReturn(0);
752785d1243SStefano Zampini }
753785d1243SStefano Zampini /* -------------------------------------------------------------------------- */
754785d1243SStefano Zampini 
755785d1243SStefano Zampini #undef __FUNCT__
756785d1243SStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundariesLocal_BDDC"
757785d1243SStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc,IS *NeumannBoundaries)
758785d1243SStefano Zampini {
759785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
760785d1243SStefano Zampini 
761785d1243SStefano Zampini   PetscFunctionBegin;
762785d1243SStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundariesLocal;
763785d1243SStefano Zampini   PetscFunctionReturn(0);
764785d1243SStefano Zampini }
765785d1243SStefano Zampini 
766785d1243SStefano Zampini #undef __FUNCT__
76782ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundariesLocal"
76853cdbc3dSStefano Zampini /*@
76982ba6b80SStefano Zampini  PCBDDCGetNeumannBoundariesLocal - Get parallel IS for Neumann boundaries (in local ordering)
77053cdbc3dSStefano Zampini 
771785d1243SStefano Zampini    Collective
77253cdbc3dSStefano Zampini 
77353cdbc3dSStefano Zampini    Input Parameters:
77428509bceSStefano Zampini .  pc - the preconditioning context
77553cdbc3dSStefano Zampini 
77653cdbc3dSStefano Zampini    Output Parameters:
77728509bceSStefano Zampini .  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
77853cdbc3dSStefano Zampini 
77953cdbc3dSStefano Zampini    Level: intermediate
78053cdbc3dSStefano Zampini 
78153cdbc3dSStefano Zampini    Notes:
7820f202f7eSStefano 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).
7830f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
78453cdbc3dSStefano Zampini 
78553cdbc3dSStefano Zampini .seealso: PCBDDC
78653cdbc3dSStefano Zampini @*/
78782ba6b80SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc,IS *NeumannBoundaries)
78853cdbc3dSStefano Zampini {
78953cdbc3dSStefano Zampini   PetscErrorCode ierr;
79053cdbc3dSStefano Zampini 
79153cdbc3dSStefano Zampini   PetscFunctionBegin;
79253cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
79382ba6b80SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundariesLocal_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
7940c7d97c5SJed Brown   PetscFunctionReturn(0);
7950c7d97c5SJed Brown }
79636e030ebSStefano Zampini /* -------------------------------------------------------------------------- */
7971e6b0712SBarry Smith 
79836e030ebSStefano Zampini #undef __FUNCT__
799da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph_BDDC"
8001a83f524SJed Brown static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
80136e030ebSStefano Zampini {
80236e030ebSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
803da1bb401SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
80456282151SStefano Zampini   PetscBool      same_data = PETSC_FALSE;
805da1bb401SStefano Zampini   PetscErrorCode ierr;
80636e030ebSStefano Zampini 
80736e030ebSStefano Zampini   PetscFunctionBegin;
80856282151SStefano Zampini   if (mat_graph->nvtxs_csr == nvtxs) {
80956282151SStefano Zampini     if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE;
81056282151SStefano Zampini     if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) {
81156282151SStefano Zampini       ierr = PetscMemcmp(adjncy,mat_graph->adjncy,nvtxs*sizeof(PetscInt),&same_data);CHKERRQ(ierr);
81256282151SStefano Zampini     }
81356282151SStefano Zampini   }
81456282151SStefano Zampini   if (!same_data) {
815674ae819SStefano Zampini     /* free old CSR */
816674ae819SStefano Zampini     ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
817674ae819SStefano Zampini     /* get CSR into graph structure */
818da1bb401SStefano Zampini     if (copymode == PETSC_COPY_VALUES) {
819854ce69bSBarry Smith       ierr = PetscMalloc1(nvtxs+1,&mat_graph->xadj);CHKERRQ(ierr);
820785e854fSJed Brown       ierr = PetscMalloc1(xadj[nvtxs],&mat_graph->adjncy);CHKERRQ(ierr);
821674ae819SStefano Zampini       ierr = PetscMemcpy(mat_graph->xadj,xadj,(nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
822674ae819SStefano Zampini       ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[nvtxs]*sizeof(PetscInt));CHKERRQ(ierr);
823da1bb401SStefano Zampini     } else if (copymode == PETSC_OWN_POINTER) {
8241a83f524SJed Brown       mat_graph->xadj = (PetscInt*)xadj;
8251a83f524SJed Brown       mat_graph->adjncy = (PetscInt*)adjncy;
826674ae819SStefano Zampini     }
827575ad6abSStefano Zampini     mat_graph->nvtxs_csr = nvtxs;
82856282151SStefano Zampini     pcbddc->recompute_topography = PETSC_TRUE;
82956282151SStefano Zampini   }
83036e030ebSStefano Zampini   PetscFunctionReturn(0);
83136e030ebSStefano Zampini }
8321e6b0712SBarry Smith 
83336e030ebSStefano Zampini #undef __FUNCT__
834da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph"
83536e030ebSStefano Zampini /*@
8360f202f7eSStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local matrix
83736e030ebSStefano Zampini 
83836e030ebSStefano Zampini    Not collective
83936e030ebSStefano Zampini 
84036e030ebSStefano Zampini    Input Parameters:
84136e030ebSStefano Zampini +  pc - the preconditioning context
8420f202f7eSStefano Zampini .  nvtxs - number of local vertices of the graph (i.e., the size of the local problem)
84328509bceSStefano Zampini .  xadj, adjncy - the CSR graph
84428509bceSStefano Zampini -  copymode - either PETSC_COPY_VALUES or PETSC_OWN_POINTER.
84536e030ebSStefano Zampini 
84636e030ebSStefano Zampini    Level: intermediate
84736e030ebSStefano Zampini 
84836e030ebSStefano Zampini    Notes:
84936e030ebSStefano Zampini 
85028509bceSStefano Zampini .seealso: PCBDDC,PetscCopyMode
85136e030ebSStefano Zampini @*/
8521a83f524SJed Brown PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
85336e030ebSStefano Zampini {
854575ad6abSStefano Zampini   void (*f)(void) = 0;
85536e030ebSStefano Zampini   PetscErrorCode ierr;
85636e030ebSStefano Zampini 
85736e030ebSStefano Zampini   PetscFunctionBegin;
85836e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
859674ae819SStefano Zampini   PetscValidIntPointer(xadj,3);
860d7de1dd9SStefano Zampini   PetscValidIntPointer(adjncy,4);
861674ae819SStefano Zampini   if (copymode != PETSC_COPY_VALUES && copymode != PETSC_OWN_POINTER) {
862674ae819SStefano Zampini     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d in %s\n",copymode,__FUNCT__);
863da1bb401SStefano Zampini   }
86436e030ebSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
865575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
866575ad6abSStefano Zampini   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr);
867575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
868575ad6abSStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
869575ad6abSStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
87036e030ebSStefano Zampini   }
87136e030ebSStefano Zampini   PetscFunctionReturn(0);
87236e030ebSStefano Zampini }
8739c0446d6SStefano Zampini /* -------------------------------------------------------------------------- */
8741e6b0712SBarry Smith 
8759c0446d6SStefano Zampini #undef __FUNCT__
87663602bcaSStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplittingLocal_BDDC"
87763602bcaSStefano Zampini static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
87863602bcaSStefano Zampini {
87963602bcaSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
88063602bcaSStefano Zampini   PetscInt       i;
88156282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
88263602bcaSStefano Zampini   PetscErrorCode ierr;
88363602bcaSStefano Zampini 
88463602bcaSStefano Zampini   PetscFunctionBegin;
88556282151SStefano Zampini   if (pcbddc->n_ISForDofsLocal == n_is) {
88656282151SStefano Zampini     for (i=0;i<n_is;i++) {
88756282151SStefano Zampini       PetscBool isequalt;
88856282151SStefano Zampini       ierr = ISEqual(ISForDofs[i],pcbddc->ISForDofsLocal[i],&isequalt);CHKERRQ(ierr);
88956282151SStefano Zampini       if (!isequalt) break;
89056282151SStefano Zampini     }
89156282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
89256282151SStefano Zampini   }
89356282151SStefano Zampini   for (i=0;i<n_is;i++) {
89456282151SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
89556282151SStefano Zampini   }
89663602bcaSStefano Zampini   /* Destroy ISes if they were already set */
89763602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
89863602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
89963602bcaSStefano Zampini   }
90063602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
90163602bcaSStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
90263602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
90363602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
90463602bcaSStefano Zampini   }
90563602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
90663602bcaSStefano Zampini   pcbddc->n_ISForDofs = 0;
90763602bcaSStefano Zampini   /* allocate space then set */
908d02579f5SStefano Zampini   if (n_is) {
909d02579f5SStefano Zampini     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
910d02579f5SStefano Zampini   }
91163602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
91263602bcaSStefano Zampini     pcbddc->ISForDofsLocal[i] = ISForDofs[i];
91363602bcaSStefano Zampini   }
91463602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = n_is;
91563602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
91656282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
91763602bcaSStefano Zampini   PetscFunctionReturn(0);
91863602bcaSStefano Zampini }
91963602bcaSStefano Zampini 
92063602bcaSStefano Zampini #undef __FUNCT__
92163602bcaSStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplittingLocal"
92263602bcaSStefano Zampini /*@
92363602bcaSStefano Zampini  PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix
92463602bcaSStefano Zampini 
92563602bcaSStefano Zampini    Collective
92663602bcaSStefano Zampini 
92763602bcaSStefano Zampini    Input Parameters:
92863602bcaSStefano Zampini +  pc - the preconditioning context
9290f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
9300f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in local ordering
93163602bcaSStefano Zampini 
93263602bcaSStefano Zampini    Level: intermediate
93363602bcaSStefano Zampini 
9340f202f7eSStefano Zampini    Notes:
9350f202f7eSStefano Zampini      n_is should be the same among processes. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
93663602bcaSStefano Zampini 
93763602bcaSStefano Zampini .seealso: PCBDDC
93863602bcaSStefano Zampini @*/
93963602bcaSStefano Zampini PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc,PetscInt n_is, IS ISForDofs[])
94063602bcaSStefano Zampini {
94163602bcaSStefano Zampini   PetscInt       i;
94263602bcaSStefano Zampini   PetscErrorCode ierr;
94363602bcaSStefano Zampini 
94463602bcaSStefano Zampini   PetscFunctionBegin;
94563602bcaSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
94663602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
94763602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
94863602bcaSStefano Zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
94963602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
95063602bcaSStefano Zampini   }
951e71e7a71SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplittingLocal_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
95263602bcaSStefano Zampini   PetscFunctionReturn(0);
95363602bcaSStefano Zampini }
95463602bcaSStefano Zampini /* -------------------------------------------------------------------------- */
95563602bcaSStefano Zampini 
95663602bcaSStefano Zampini #undef __FUNCT__
9579c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
9589c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
9599c0446d6SStefano Zampini {
9609c0446d6SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
9619c0446d6SStefano Zampini   PetscInt       i;
96256282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
9639c0446d6SStefano Zampini   PetscErrorCode ierr;
9649c0446d6SStefano Zampini 
9659c0446d6SStefano Zampini   PetscFunctionBegin;
96656282151SStefano Zampini   if (pcbddc->n_ISForDofs == n_is) {
96756282151SStefano Zampini     for (i=0;i<n_is;i++) {
96856282151SStefano Zampini       PetscBool isequalt;
96956282151SStefano Zampini       ierr = ISEqual(ISForDofs[i],pcbddc->ISForDofs[i],&isequalt);CHKERRQ(ierr);
97056282151SStefano Zampini       if (!isequalt) break;
97156282151SStefano Zampini     }
97256282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
97356282151SStefano Zampini   }
97456282151SStefano Zampini   for (i=0;i<n_is;i++) {
97556282151SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
97656282151SStefano Zampini   }
977da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
9789c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
9799c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
9809c0446d6SStefano Zampini   }
981d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
98263602bcaSStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
98363602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
98463602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
98563602bcaSStefano Zampini   }
98663602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
98763602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = 0;
988da1bb401SStefano Zampini   /* allocate space then set */
989d02579f5SStefano Zampini   if (n_is) {
990785e854fSJed Brown     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofs);CHKERRQ(ierr);
991d02579f5SStefano Zampini   }
9929c0446d6SStefano Zampini   for (i=0;i<n_is;i++) {
993da1bb401SStefano Zampini     pcbddc->ISForDofs[i] = ISForDofs[i];
9949c0446d6SStefano Zampini   }
9959c0446d6SStefano Zampini   pcbddc->n_ISForDofs = n_is;
99663602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
99756282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
9989c0446d6SStefano Zampini   PetscFunctionReturn(0);
9999c0446d6SStefano Zampini }
10001e6b0712SBarry Smith 
10019c0446d6SStefano Zampini #undef __FUNCT__
10029c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting"
10039c0446d6SStefano Zampini /*@
100463602bcaSStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix
10059c0446d6SStefano Zampini 
100663602bcaSStefano Zampini    Collective
10079c0446d6SStefano Zampini 
10089c0446d6SStefano Zampini    Input Parameters:
10099c0446d6SStefano Zampini +  pc - the preconditioning context
10100f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
10110f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in global ordering
10129c0446d6SStefano Zampini 
10139c0446d6SStefano Zampini    Level: intermediate
10149c0446d6SStefano Zampini 
10150f202f7eSStefano Zampini    Notes:
10160f202f7eSStefano Zampini      Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
10179c0446d6SStefano Zampini 
10189c0446d6SStefano Zampini .seealso: PCBDDC
10199c0446d6SStefano Zampini @*/
10209c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
10219c0446d6SStefano Zampini {
10222b510759SStefano Zampini   PetscInt       i;
10239c0446d6SStefano Zampini   PetscErrorCode ierr;
10249c0446d6SStefano Zampini 
10259c0446d6SStefano Zampini   PetscFunctionBegin;
10269c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
102763602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
10282b510759SStefano Zampini   for (i=0;i<n_is;i++) {
102963602bcaSStefano Zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
103063602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
10312b510759SStefano Zampini   }
10329c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
10339c0446d6SStefano Zampini   PetscFunctionReturn(0);
10349c0446d6SStefano Zampini }
1035906d46d4SStefano Zampini 
1036da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
1037534831adSStefano Zampini #undef __FUNCT__
1038534831adSStefano Zampini #define __FUNCT__ "PCPreSolve_BDDC"
1039534831adSStefano Zampini /* -------------------------------------------------------------------------- */
1040534831adSStefano Zampini /*
1041534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
1042534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
10439c0446d6SStefano Zampini 
1044534831adSStefano Zampini    Input Parameter:
1045534831adSStefano Zampini +  pc - the preconditioner contex
1046534831adSStefano Zampini 
1047534831adSStefano Zampini    Application Interface Routine: PCPreSolve()
1048534831adSStefano Zampini 
1049534831adSStefano Zampini    Notes:
1050534831adSStefano Zampini      The interface routine PCPreSolve() is not usually called directly by
1051534831adSStefano Zampini    the user, but instead is called by KSPSolve().
1052534831adSStefano Zampini */
1053534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1054534831adSStefano Zampini {
1055534831adSStefano Zampini   PetscErrorCode ierr;
1056534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1057534831adSStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
10583972b0daSStefano Zampini   Vec            used_vec;
10598d00608fSStefano Zampini   PetscBool      copy_rhs = PETSC_TRUE;
106051694757SStefano Zampini   PetscBool      benign_correction_is_zero = PETSC_FALSE;
1061a3df083aSStefano Zampini   PetscBool      iscg = PETSC_FALSE;
1062534831adSStefano Zampini 
1063534831adSStefano Zampini   PetscFunctionBegin;
106485c4d303SStefano Zampini   /* if we are working with cg, one dirichlet solve can be avoided during Krylov iterations */
106585c4d303SStefano Zampini   if (ksp) {
106685c4d303SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPCG,&iscg);CHKERRQ(ierr);
106785c4d303SStefano Zampini     if (!iscg) {
106885c4d303SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
106985c4d303SStefano Zampini     }
107085c4d303SStefano Zampini   }
107185c4d303SStefano Zampini   /* Creates parallel work vectors used in presolve */
107262a6ff1dSStefano Zampini   if (!pcbddc->original_rhs) {
107362a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
107462a6ff1dSStefano Zampini   }
107562a6ff1dSStefano Zampini   if (!pcbddc->temp_solution) {
107662a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
107762a6ff1dSStefano Zampini   }
10788d00608fSStefano Zampini 
10793972b0daSStefano Zampini   if (x) {
10803972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
10813972b0daSStefano Zampini     used_vec = x;
10828d00608fSStefano Zampini   } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */
10833972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
10843972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
10853972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
10863972b0daSStefano Zampini   }
10878efcfb23SStefano Zampini 
10888efcfb23SStefano Zampini   /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */
10893972b0daSStefano Zampini   if (ksp) {
1090a0cb1b98SStefano Zampini     /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */
10918efcfb23SStefano Zampini     ierr = KSPGetInitialGuessNonzero(ksp,&pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
10928efcfb23SStefano Zampini     if (!pcbddc->ksp_guess_nonzero) {
10933972b0daSStefano Zampini       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
10943972b0daSStefano Zampini     }
10953972b0daSStefano Zampini   }
10963308cffdSStefano Zampini 
10978d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
10983972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
1099a07ea27aSStefano Zampini   if (rhs) {
11003975b054SStefano Zampini     IS dirIS = NULL;
11013975b054SStefano Zampini 
1102a07ea27aSStefano Zampini     /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */
11033975b054SStefano Zampini     ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
11043975b054SStefano Zampini     if (dirIS) {
1105906d46d4SStefano Zampini       Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
1106785d1243SStefano Zampini       PetscInt          dirsize,i,*is_indices;
11072b095fd8SStefano Zampini       PetscScalar       *array_x;
11082b095fd8SStefano Zampini       const PetscScalar *array_diagonal;
1109785d1243SStefano Zampini 
11103972b0daSStefano Zampini       ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
11113972b0daSStefano Zampini       ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
1112e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1113e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1114e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1115e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
111682ba6b80SStefano Zampini       ierr = ISGetLocalSize(dirIS,&dirsize);CHKERRQ(ierr);
11173972b0daSStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
11182b095fd8SStefano Zampini       ierr = VecGetArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
11193972b0daSStefano Zampini       ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
11202fa5cd67SKarl Rupp       for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
11213972b0daSStefano Zampini       ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
11222b095fd8SStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
11233972b0daSStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
1124e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1125e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
11268d00608fSStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
11271b968477SStefano Zampini       ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
11288efcfb23SStefano Zampini     }
1129a07ea27aSStefano Zampini   }
1130b76ba322SStefano Zampini 
11318efcfb23SStefano Zampini   /* remove the computed solution or the initial guess from the rhs */
11328d00608fSStefano Zampini   if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero) ) {
11338d00608fSStefano Zampini     /* store the original rhs */
11348d00608fSStefano Zampini     if (copy_rhs) {
11358d00608fSStefano Zampini       ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
11368d00608fSStefano Zampini       copy_rhs = PETSC_FALSE;
11378d00608fSStefano Zampini     }
11388d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
11393972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
11400369aaf7SStefano Zampini     ierr = MatMultAdd(pc->mat,used_vec,rhs,rhs);CHKERRQ(ierr);
11413972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
11428efcfb23SStefano Zampini     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
11437acc28cbSStefano Zampini     if (ksp) {
11447acc28cbSStefano Zampini       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_FALSE);CHKERRQ(ierr);
11457acc28cbSStefano Zampini     }
11463308cffdSStefano Zampini   }
11478efcfb23SStefano Zampini   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
1148b76ba322SStefano Zampini 
11490369aaf7SStefano Zampini   /* When using the benign trick: (TODO: what about FETI-DP?)
11500369aaf7SStefano Zampini      - change rhs on pressures (iteration matrix is surely of type MATIS)
11510369aaf7SStefano Zampini      - compute initial vector in benign space
11520369aaf7SStefano Zampini   */
11530369aaf7SStefano Zampini   if (rhs && pcbddc->benign_saddle_point) {
115406f24817SStefano Zampini     Mat_IS   *matis = (Mat_IS*)(pc->mat->data);
11554f1b2e48SStefano Zampini     PetscInt i;
115606f24817SStefano Zampini 
115706f24817SStefano Zampini     /* store the original rhs */
115806f24817SStefano Zampini     if (copy_rhs) {
115906f24817SStefano Zampini       ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
116006f24817SStefano Zampini       copy_rhs = PETSC_FALSE;
116106f24817SStefano Zampini     }
116206f24817SStefano Zampini 
116306f24817SStefano Zampini     /* now change (locally) the basis */
116406f24817SStefano Zampini     ierr = VecScatterBegin(matis->rctx,rhs,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
116506f24817SStefano Zampini     ierr = VecScatterEnd(matis->rctx,rhs,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
116606f24817SStefano Zampini     if (pcbddc->benign_change) {
116706f24817SStefano Zampini       ierr = MatMultTranspose(pcbddc->benign_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
116806f24817SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
116906f24817SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
11705cfd9691SStefano Zampini       /* swap local iteration matrix (with the benign trick, amat == pmat) */
1171a3df083aSStefano Zampini       if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
1172a3df083aSStefano Zampini         /* benign shell mat mult for matis->A and pcis->A_IB*/
1173a3df083aSStefano Zampini         ierr = PCBDDCBenignShellMat(pc,PETSC_FALSE);CHKERRQ(ierr);
1174a3df083aSStefano Zampini       } else {
11755cfd9691SStefano Zampini         ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_FALSE);CHKERRQ(ierr);
117606f24817SStefano Zampini         pcbddc->benign_original_mat = matis->A;
117706f24817SStefano Zampini         matis->A = pcbddc->local_mat;
1178a3df083aSStefano Zampini       }
117906f24817SStefano Zampini     } else {
118006f24817SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
118106f24817SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,rhs,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
118277a2de6eSStefano Zampini       if (pcbddc->ChangeOfBasisMatrix) {
118377a2de6eSStefano Zampini         pcbddc->benign_original_mat = matis->A;
118477a2de6eSStefano Zampini         matis->A = pcbddc->local_mat;
118577a2de6eSStefano Zampini       }
118606f24817SStefano Zampini     }
118706f24817SStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
118806f24817SStefano Zampini 
11890369aaf7SStefano Zampini     /* compute u^*_h as in Xuemin Tu's thesis (see Section 4.8.1) */
11900369aaf7SStefano Zampini     /* TODO: what about Stokes? */
11910369aaf7SStefano Zampini     if (!pcbddc->benign_vec) {
11920369aaf7SStefano Zampini       ierr = VecDuplicate(rhs,&pcbddc->benign_vec);CHKERRQ(ierr);
11930369aaf7SStefano Zampini     }
11944f1b2e48SStefano Zampini     ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
11954f1b2e48SStefano Zampini     if (pcbddc->benign_n) {
11960369aaf7SStefano Zampini       const PetscScalar *array;
11970369aaf7SStefano Zampini 
11980369aaf7SStefano Zampini       ierr = VecGetArrayRead(pcis->vec2_N,&array);CHKERRQ(ierr);
11994f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = array[pcbddc->benign_p0_lidx[i]];
12000369aaf7SStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec2_N,&array);CHKERRQ(ierr);
12010369aaf7SStefano Zampini     }
120251694757SStefano Zampini     if (pcbddc->benign_null && iscg) { /* this is a workaround, need to understand more */
12034f1b2e48SStefano Zampini       PetscBool iszero_l = PETSC_TRUE;
12044f1b2e48SStefano Zampini       for (i=0;i<pcbddc->benign_n;i++) {
12054f1b2e48SStefano Zampini         iszero_l = (iszero_l && (PetscAbsScalar(pcbddc->benign_p0[i]) < PETSC_SMALL ? PETSC_TRUE : PETSC_FALSE));
12064f1b2e48SStefano Zampini       }
120751694757SStefano Zampini       ierr = MPI_Allreduce(&iszero_l,&benign_correction_is_zero,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
120851694757SStefano Zampini     }
12094fee134fSStefano Zampini     if (!benign_correction_is_zero) { /* use the coarse solver only */
1210015636ebSStefano Zampini       ierr = PCBDDCBenignGetOrSetP0(pc,pcis->vec1_global,PETSC_FALSE);CHKERRQ(ierr);
12114fee134fSStefano Zampini       pcbddc->benign_apply_coarse_only = PETSC_TRUE;
12120369aaf7SStefano Zampini       ierr = PCApply_BDDC(pc,pcis->vec1_global,pcbddc->benign_vec);CHKERRQ(ierr);
12134fee134fSStefano Zampini       pcbddc->benign_apply_coarse_only = PETSC_FALSE;
12144f1b2e48SStefano Zampini       ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
1215015636ebSStefano Zampini       ierr = PCBDDCBenignGetOrSetP0(pc,pcbddc->benign_vec,PETSC_FALSE);CHKERRQ(ierr);
1216b76ba322SStefano Zampini     }
121751694757SStefano Zampini   }
1218b76ba322SStefano Zampini 
12190369aaf7SStefano Zampini   /* change rhs and iteration matrix if using the change of basis */
1220b9b85e73SStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
1221906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
1222906d46d4SStefano Zampini 
1223906d46d4SStefano Zampini     /* get change ctx */
1224906d46d4SStefano Zampini     ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
1225906d46d4SStefano Zampini 
1226906d46d4SStefano Zampini     /* set current iteration matrix inside change context (change of basis has been already set into the ctx during PCSetUp) */
122777a2de6eSStefano Zampini     if (!pcbddc->benign_original_mat) {
1228906d46d4SStefano Zampini       ierr = MatDestroy(&change_ctx->original_mat);CHKERRQ(ierr);
1229906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pc->mat);CHKERRQ(ierr);
1230906d46d4SStefano Zampini       change_ctx->original_mat = pc->mat;
1231906d46d4SStefano Zampini 
1232906d46d4SStefano Zampini       /* change iteration matrix */
1233906d46d4SStefano Zampini       ierr = MatDestroy(&pc->mat);CHKERRQ(ierr);
1234906d46d4SStefano Zampini       ierr = PetscObjectReference((PetscObject)pcbddc->new_global_mat);CHKERRQ(ierr);
1235906d46d4SStefano Zampini       pc->mat = pcbddc->new_global_mat;
12369bd2e3c7SStefano Zampini     }
12378d00608fSStefano Zampini     /* store the original rhs */
12388d00608fSStefano Zampini     if (copy_rhs) {
12398d00608fSStefano Zampini       ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
12408d00608fSStefano Zampini       copy_rhs = PETSC_FALSE;
12418d00608fSStefano Zampini     }
12428d00608fSStefano Zampini 
1243906d46d4SStefano Zampini     /* change rhs */
1244906d46d4SStefano Zampini     ierr = MatMultTranspose(change_ctx->global_change,rhs,pcis->vec1_global);CHKERRQ(ierr);
1245906d46d4SStefano Zampini     ierr = VecCopy(pcis->vec1_global,rhs);CHKERRQ(ierr);
12468d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
124792e3dcfbSStefano Zampini   }
124892e3dcfbSStefano Zampini 
12490369aaf7SStefano Zampini   /* remove non-benign solution from the rhs */
12500369aaf7SStefano Zampini   if (pcbddc->benign_saddle_point) {
12510369aaf7SStefano Zampini     /* store the original rhs */
12520369aaf7SStefano Zampini     if (copy_rhs) {
12530369aaf7SStefano Zampini       ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
12540369aaf7SStefano Zampini       copy_rhs = PETSC_FALSE;
12550369aaf7SStefano Zampini     }
125651694757SStefano Zampini     if (benign_correction_is_zero) { /* still need to understand why it works great */
125751694757SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
125851694757SStefano Zampini       ierr = PCApply_BDDC(pc,rhs,pcbddc->benign_vec);CHKERRQ(ierr);
125951694757SStefano Zampini     }
12600369aaf7SStefano Zampini     ierr = VecScale(pcbddc->benign_vec,-1.0);CHKERRQ(ierr);
12610369aaf7SStefano Zampini     ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,rhs,rhs);CHKERRQ(ierr);
12620369aaf7SStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
12630369aaf7SStefano Zampini   }
12640369aaf7SStefano Zampini 
12650369aaf7SStefano Zampini   /* set initial guess if using PCG */
12660369aaf7SStefano Zampini   if (x && pcbddc->use_exact_dirichlet_trick) {
12670369aaf7SStefano Zampini     ierr = VecSet(x,0.0);CHKERRQ(ierr);
12680369aaf7SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12690369aaf7SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12700369aaf7SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
12710369aaf7SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
12720369aaf7SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
12730369aaf7SStefano Zampini     if (ksp) {
12740369aaf7SStefano Zampini       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
12750369aaf7SStefano Zampini     }
12760369aaf7SStefano Zampini   }
1277b0f5fe93SStefano Zampini   if (pcbddc->benign_null) {
1278b0f5fe93SStefano Zampini     MatNullSpace null_space;
1279b0f5fe93SStefano Zampini     Vec          nullv;
1280b0f5fe93SStefano Zampini     PetscBool    isnull;
12814f1b2e48SStefano Zampini     PetscInt     i;
1282b0f5fe93SStefano Zampini 
12834f1b2e48SStefano Zampini     for (i=0;i<pcbddc->benign_n;i++) pcbddc->benign_p0[i] = 1.;
1284b0f5fe93SStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&nullv);CHKERRQ(ierr);
1285b0f5fe93SStefano Zampini     ierr = VecSet(nullv,0.);CHKERRQ(ierr);
1286b0f5fe93SStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,nullv,PETSC_FALSE);CHKERRQ(ierr);
1287b0f5fe93SStefano Zampini     ierr = VecNormalize(nullv,NULL);CHKERRQ(ierr);
1288b0f5fe93SStefano Zampini     ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)pc),PETSC_FALSE,1,&nullv,&null_space);CHKERRQ(ierr);
1289b0f5fe93SStefano Zampini     ierr = MatNullSpaceTest(null_space,pc->mat,&isnull);CHKERRQ(ierr);
12904f1b2e48SStefano Zampini     if (isnull) {
1291b0f5fe93SStefano Zampini       ierr = MatSetNullSpace(pc->mat,null_space);CHKERRQ(ierr);
12924f1b2e48SStefano Zampini     }
1293b0f5fe93SStefano Zampini     ierr = MatNullSpaceDestroy(&null_space);CHKERRQ(ierr);
1294b0f5fe93SStefano Zampini     ierr = VecDestroy(&nullv);CHKERRQ(ierr);
1295b0f5fe93SStefano Zampini   }
1296b0f5fe93SStefano Zampini 
129792e3dcfbSStefano Zampini   /* remove nullspace if present */
12988efcfb23SStefano Zampini   if (ksp && x && pcbddc->NullSpace) {
12998efcfb23SStefano Zampini     ierr = MatNullSpaceRemove(pcbddc->NullSpace,x);CHKERRQ(ierr);
13008d00608fSStefano Zampini     /* store the original rhs */
13018d00608fSStefano Zampini     if (copy_rhs) {
13028d00608fSStefano Zampini       ierr = VecCopy(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
13038d00608fSStefano Zampini       copy_rhs = PETSC_FALSE;
13048d00608fSStefano Zampini     }
13058d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
1306d0195637SJed Brown     ierr = MatNullSpaceRemove(pcbddc->NullSpace,rhs);CHKERRQ(ierr);
1307b76ba322SStefano Zampini   }
1308534831adSStefano Zampini   PetscFunctionReturn(0);
1309534831adSStefano Zampini }
1310906d46d4SStefano Zampini 
1311534831adSStefano Zampini /* -------------------------------------------------------------------------- */
1312534831adSStefano Zampini #undef __FUNCT__
1313534831adSStefano Zampini #define __FUNCT__ "PCPostSolve_BDDC"
1314534831adSStefano Zampini /* -------------------------------------------------------------------------- */
1315534831adSStefano Zampini /*
1316534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
1317534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
1318534831adSStefano Zampini 
1319534831adSStefano Zampini    Input Parameter:
1320534831adSStefano Zampini +  pc - the preconditioner contex
1321534831adSStefano Zampini 
1322534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
1323534831adSStefano Zampini 
1324534831adSStefano Zampini    Notes:
1325534831adSStefano Zampini      The interface routine PCPostSolve() is not usually called directly by
1326534831adSStefano Zampini      the user, but instead is called by KSPSolve().
1327534831adSStefano Zampini */
1328534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1329534831adSStefano Zampini {
1330534831adSStefano Zampini   PetscErrorCode ierr;
1331534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1332534831adSStefano Zampini 
1333534831adSStefano Zampini   PetscFunctionBegin;
133477a2de6eSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix && !pcbddc->benign_original_mat) {
1335906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
1336906d46d4SStefano Zampini 
1337906d46d4SStefano Zampini     /* get change ctx */
1338906d46d4SStefano Zampini     ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
1339906d46d4SStefano Zampini 
1340906d46d4SStefano Zampini     /* restore iteration matrix */
1341906d46d4SStefano Zampini     ierr = MatDestroy(&pc->mat);CHKERRQ(ierr);
1342906d46d4SStefano Zampini     ierr = PetscObjectReference((PetscObject)change_ctx->original_mat);CHKERRQ(ierr);
1343906d46d4SStefano Zampini     pc->mat = change_ctx->original_mat;
13449c6a02ceSStefano Zampini   }
1345906d46d4SStefano Zampini 
13468666afb4SStefano Zampini   /* need to restore the local matrices */
134777a2de6eSStefano Zampini   if (pcbddc->benign_original_mat) {
13488666afb4SStefano Zampini     Mat_IS *matis = (Mat_IS*)pc->mat->data;
13498666afb4SStefano Zampini 
1350a3df083aSStefano Zampini     if (pcbddc->benign_n && !pcbddc->benign_change_explicit) {
1351a3df083aSStefano Zampini       ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
1352a3df083aSStefano Zampini     } else {
13535cfd9691SStefano Zampini       pcbddc->local_mat = matis->A;
13548666afb4SStefano Zampini       matis->A = pcbddc->benign_original_mat;
13555cfd9691SStefano Zampini       pcbddc->benign_original_mat = NULL;
13568666afb4SStefano Zampini     }
1357a3df083aSStefano Zampini   }
13588666afb4SStefano Zampini 
1359906d46d4SStefano Zampini   /* get solution in original basis */
1360906d46d4SStefano Zampini   if (x) {
1361906d46d4SStefano Zampini     PC_IS *pcis = (PC_IS*)(pc->data);
136206f24817SStefano Zampini 
13632d3346b4SStefano Zampini     /* restore solution on pressures */
136406a4e24aSStefano Zampini     if (pcbddc->benign_saddle_point) {
13652d3346b4SStefano Zampini       Mat_IS *matis = (Mat_IS*)pc->mat->data;
13662d3346b4SStefano Zampini 
13670369aaf7SStefano Zampini       /* add non-benign solution */
13688666afb4SStefano Zampini       ierr = VecAXPY(x,-1.0,pcbddc->benign_vec);CHKERRQ(ierr);
13690369aaf7SStefano Zampini 
13700369aaf7SStefano Zampini       /* change basis on pressures for x */
137106f24817SStefano Zampini       ierr = VecScatterBegin(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
137206f24817SStefano Zampini       ierr = VecScatterEnd(matis->rctx,x,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13732d3346b4SStefano Zampini       if (pcbddc->benign_change) {
13742d3346b4SStefano Zampini         ierr = MatMult(pcbddc->benign_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
137506f24817SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
137606f24817SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec2_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13772d3346b4SStefano Zampini       } else {
137806f24817SStefano Zampini         ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
137906f24817SStefano Zampini         ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13802d3346b4SStefano Zampini       }
13812d3346b4SStefano Zampini     }
13829c6a02ceSStefano Zampini 
13830369aaf7SStefano Zampini     /* change basis on x */
13849c6a02ceSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix) {
13859c6a02ceSStefano Zampini       PCBDDCChange_ctx change_ctx;
13869c6a02ceSStefano Zampini 
13879c6a02ceSStefano Zampini       ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
13880369aaf7SStefano Zampini       ierr = MatMult(change_ctx->global_change,x,pcis->vec1_global);CHKERRQ(ierr);
1389906d46d4SStefano Zampini       ierr = VecCopy(pcis->vec1_global,x);CHKERRQ(ierr);
13903425bc38SStefano Zampini     }
1391534831adSStefano Zampini   }
1392906d46d4SStefano Zampini 
13933972b0daSStefano Zampini   /* add solution removed in presolve */
13946bcfc461SStefano Zampini   if (x && pcbddc->rhs_change) {
13953425bc38SStefano Zampini     ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
13963425bc38SStefano Zampini   }
1397906d46d4SStefano Zampini 
1398fb223d50SStefano Zampini   /* restore rhs to its original state */
13998d00608fSStefano Zampini   if (rhs && pcbddc->rhs_change) {
1400fb223d50SStefano Zampini     ierr = VecCopy(pcbddc->original_rhs,rhs);CHKERRQ(ierr);
1401fb223d50SStefano Zampini   }
14028d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
14038efcfb23SStefano Zampini 
14048efcfb23SStefano Zampini   /* restore ksp guess state */
14058efcfb23SStefano Zampini   if (ksp) {
14068efcfb23SStefano Zampini     ierr = KSPSetInitialGuessNonzero(ksp,pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
14078efcfb23SStefano Zampini   }
1408534831adSStefano Zampini   PetscFunctionReturn(0);
1409534831adSStefano Zampini }
1410534831adSStefano Zampini /* -------------------------------------------------------------------------- */
141153cdbc3dSStefano Zampini #undef __FUNCT__
141253cdbc3dSStefano Zampini #define __FUNCT__ "PCSetUp_BDDC"
14130c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
14140c7d97c5SJed Brown /*
14150c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
14160c7d97c5SJed Brown                   by setting data structures and options.
14170c7d97c5SJed Brown 
14180c7d97c5SJed Brown    Input Parameter:
141953cdbc3dSStefano Zampini +  pc - the preconditioner context
14200c7d97c5SJed Brown 
14210c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
14220c7d97c5SJed Brown 
14230c7d97c5SJed Brown    Notes:
14240c7d97c5SJed Brown      The interface routine PCSetUp() is not usually called directly by
14250c7d97c5SJed Brown      the user, but instead is called by PCApply() if necessary.
14260c7d97c5SJed Brown */
142753cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
14280c7d97c5SJed Brown {
14290c7d97c5SJed Brown   PetscErrorCode ierr;
14300c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
14315e8657edSStefano Zampini   Mat_IS*        matis;
143208122e43SStefano Zampini   MatNullSpace   nearnullspace;
1433c9ed8603SStefano Zampini   IS             zerodiag = NULL;
143491e8d312SStefano Zampini   PetscInt       nrows,ncols;
143508122e43SStefano Zampini   PetscBool      computetopography,computesolvers,computesubschurs;
14368de1fae6SStefano Zampini   PetscBool      computeconstraintsmatrix;
14375e8657edSStefano Zampini   PetscBool      new_nearnullspace_provided,ismatis;
14380c7d97c5SJed Brown 
14390c7d97c5SJed Brown   PetscFunctionBegin;
14405e8657edSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATIS,&ismatis);CHKERRQ(ierr);
14415e8657edSStefano Zampini   if (!ismatis) {
14425e8657edSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner requires matrix of type MATIS");
14435e8657edSStefano Zampini   }
144491e8d312SStefano Zampini   ierr = MatGetSize(pc->pmat,&nrows,&ncols);CHKERRQ(ierr);
144591e8d312SStefano Zampini   if (nrows != ncols) {
144691e8d312SStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCBDDC preconditioner requires a square preconditioning matrix");
144791e8d312SStefano Zampini   }
14485e8657edSStefano Zampini   matis = (Mat_IS*)pc->pmat->data;
1449f4ddd8eeSStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
14503b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
1451fcd409f5SStefano Zampini      Also, BDDC directly build the Dirichlet problem */
1452f4ddd8eeSStefano Zampini   /* split work */
1453674ae819SStefano Zampini   if (pc->setupcalled) {
1454d1e9a80fSBarry Smith     if (pc->flag == SAME_NONZERO_PATTERN) {
1455674ae819SStefano Zampini       computetopography = PETSC_FALSE;
1456674ae819SStefano Zampini       computesolvers = PETSC_TRUE;
1457674ae819SStefano Zampini     } else { /* DIFFERENT_NONZERO_PATTERN */
1458674ae819SStefano Zampini       computetopography = PETSC_TRUE;
1459674ae819SStefano Zampini       computesolvers = PETSC_TRUE;
1460674ae819SStefano Zampini     }
1461674ae819SStefano Zampini   } else {
1462674ae819SStefano Zampini     computetopography = PETSC_TRUE;
1463674ae819SStefano Zampini     computesolvers = PETSC_TRUE;
1464674ae819SStefano Zampini   }
1465fb180af4SStefano Zampini   if (pcbddc->recompute_topography) {
1466fb180af4SStefano Zampini     computetopography = PETSC_TRUE;
1467fb180af4SStefano Zampini   }
146856282151SStefano Zampini   pcbddc->recompute_topography = computetopography;
14698de1fae6SStefano Zampini   computeconstraintsmatrix = PETSC_FALSE;
1470b087196eSStefano Zampini 
1471b087196eSStefano Zampini   /* check parameters' compatibility */
14725a95e1ceSStefano Zampini   if (pcbddc->adaptive_threshold > 0.0 && !pcbddc->use_deluxe_scaling) {
14735a95e1ceSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Cannot compute adaptive constraints without deluxe scaling. Rerun with -pc_bddc_use_deluxe_scaling");
14745a95e1ceSStefano Zampini   }
14755a95e1ceSStefano Zampini   pcbddc->adaptive_selection = (PetscBool)(pcbddc->adaptive_threshold > 0.0 && pcbddc->use_deluxe_scaling);
1476bf3a8328SStefano Zampini   pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined);
1477862806e4SStefano Zampini   if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE;
1478862806e4SStefano Zampini 
14795a95e1ceSStefano Zampini   computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling);
14806816873aSStefano Zampini   if (pcbddc->faster_deluxe && pcbddc->adaptive_selection && pcbddc->use_change_of_basis) {
14816816873aSStefano 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");
14826816873aSStefano Zampini   }
1483*14f95afaSStefano Zampini   if (pcbddc->benign_saddle_point && pcbddc->switch_static) {
1484*14f95afaSStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Benign subspace trick cannot be used with M_3");
1485*14f95afaSStefano Zampini   }
14862d3346b4SStefano Zampini 
14872d3346b4SStefano Zampini   /* check if the iteration matrix is of type MATIS in case the benign trick has been requested */
14882d3346b4SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc->mat,MATIS,&ismatis);CHKERRQ(ierr);
148906a4e24aSStefano Zampini   if (pcbddc->benign_saddle_point && !ismatis) {
14902d3346b4SStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner with benign subspace trick requires the iteration matrix to be of type MATIS");
14912d3346b4SStefano Zampini   }
14925cfd9691SStefano Zampini   if (pcbddc->benign_saddle_point && pc->mat != pc->pmat) {
149316e386b8SStefano Zampini     SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner with benign subspace trick requires Amat == Pmat");
14945cfd9691SStefano Zampini   }
14952d3346b4SStefano Zampini 
1496f4ddd8eeSStefano Zampini   /* Get stdout for dbg */
149770cf5478SStefano Zampini   if (pcbddc->dbg_flag) {
149870cf5478SStefano Zampini     if (!pcbddc->dbg_viewer) {
149958a03d70SStefano Zampini       pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
15001575c14dSBarry Smith       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
1501f4ddd8eeSStefano Zampini     }
150258a03d70SStefano Zampini     ierr = PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1503f4ddd8eeSStefano Zampini   }
1504f4ddd8eeSStefano Zampini 
15055e8657edSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) {
15065e8657edSStefano Zampini     /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
15075e8657edSStefano Zampini     pcbddc->use_change_of_basis = PETSC_FALSE;
15085e8657edSStefano Zampini     ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
15095e8657edSStefano Zampini   } else {
1510b96c3477SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
15115e8657edSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
15125e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
1513d16cbb6bSStefano Zampini   }
1514d16cbb6bSStefano Zampini 
15154f1b2e48SStefano Zampini   /* detect local disconnected subdomains if requested and not done before */
15164f1b2e48SStefano Zampini   if (pcbddc->detect_disconnected && !pcbddc->n_local_subs) {
15174f1b2e48SStefano Zampini     ierr = MatDetectDisconnectedComponents(pcbddc->local_mat,PETSC_FALSE,&pcbddc->n_local_subs,&pcbddc->local_subs);CHKERRQ(ierr);
15184f1b2e48SStefano Zampini   }
15194f1b2e48SStefano Zampini 
15204f1b2e48SStefano Zampini   /*
15214f1b2e48SStefano Zampini      change basis on local pressures (aka zerodiag dofs)
15224f1b2e48SStefano Zampini      This should come earlier then PCISSetUp for extracting the correct subdomain matrices
15234f1b2e48SStefano Zampini   */
1524d16cbb6bSStefano Zampini   if (pcbddc->benign_saddle_point) {
15259f47a83aSStefano Zampini     PC_IS* pcis = (PC_IS*)pc->data;
15269f47a83aSStefano Zampini 
152705b28244SStefano Zampini     if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE;
1528339f8db1SStefano Zampini     /* detect local saddle point and change the basis in pcbddc->local_mat */
1529339f8db1SStefano Zampini     ierr = PCBDDCBenignDetectSaddlePoint(pc,&zerodiag);CHKERRQ(ierr);
1530a3df083aSStefano Zampini     /* pop B0 mat from local mat */
1531c263805aSStefano Zampini     ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
15329f47a83aSStefano Zampini     /* set flag in pcis to not reuse submatrices during PCISCreate */
1533a3df083aSStefano Zampini     if (pc->flag == SAME_NONZERO_PATTERN && pcbddc->benign_n && !pcbddc->benign_change_explicit && !pcbddc->dbg_flag) {
1534a3df083aSStefano Zampini       pcis->reusesubmatrices = PETSC_TRUE;
1535a3df083aSStefano Zampini     } else {
15369f47a83aSStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
1537674ae819SStefano Zampini     }
1538a3df083aSStefano Zampini   }
1539f1a72664SStefano Zampini   /* propagate relevant information */
15404f1b2e48SStefano Zampini #if !defined(PETSC_USE_COMPLEX) /* workaround for reals */
15413301b35fSStefano Zampini   if (matis->A->symmetric_set) {
15423301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
15433301b35fSStefano Zampini   }
1544e496cd5dSStefano Zampini #endif
154506a4e24aSStefano Zampini   if (matis->A->symmetric_set) {
154606a4e24aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
154706a4e24aSStefano Zampini   }
154806a4e24aSStefano Zampini   if (matis->A->spd_set) {
154906a4e24aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SPD,matis->A->spd);CHKERRQ(ierr);
155006a4e24aSStefano Zampini   }
1551e496cd5dSStefano Zampini 
15525e8657edSStefano Zampini   /* Set up all the "iterative substructuring" common block without computing solvers */
15535e8657edSStefano Zampini   {
15545e8657edSStefano Zampini     Mat temp_mat;
15555e8657edSStefano Zampini 
15565e8657edSStefano Zampini     temp_mat = matis->A;
15575e8657edSStefano Zampini     matis->A = pcbddc->local_mat;
15585e8657edSStefano Zampini     ierr = PCISSetUp(pc,PETSC_FALSE);CHKERRQ(ierr);
15595e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
15605e8657edSStefano Zampini     matis->A = temp_mat;
15615e8657edSStefano Zampini   }
1562684f6988SStefano Zampini 
156381d14e9dSStefano Zampini   /* Analyze interface */
1564674ae819SStefano Zampini   if (computetopography) {
1565674ae819SStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
15668de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1567674ae819SStefano Zampini   }
1568fb8d54d4SStefano Zampini 
15695408967cSStefano Zampini   /* check existence of a divergence free extension, i.e.
15705408967cSStefano Zampini      b(v_I,p_0) = 0 for all v_I (raise error if not).
15715408967cSStefano Zampini      Also, check that PCBDDCBenignGetOrSetP0 works */
15725408967cSStefano Zampini #if defined(PETSC_USE_DEBUG)
157309f581a4SStefano Zampini   if (pcbddc->benign_saddle_point) {
15745408967cSStefano Zampini     ierr = PCBDDCBenignCheck(pc,zerodiag);CHKERRQ(ierr);
157509f581a4SStefano Zampini   }
15765408967cSStefano Zampini #endif
15774f1b2e48SStefano Zampini   ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
157806f24817SStefano Zampini 
1579b96c3477SStefano Zampini   /* Setup local dirichlet solver ksp_D and sub_schurs solvers */
1580684f6988SStefano Zampini   if (computesolvers) {
1581d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
1582d5574798SStefano Zampini 
1583d5574798SStefano Zampini     if (computesubschurs && computetopography) {
158408122e43SStefano Zampini       ierr = PCBDDCInitSubSchurs(pc);CHKERRQ(ierr);
1585b1b3d7a2SStefano Zampini     }
1586df4d28bfSStefano Zampini     if (sub_schurs->schur_explicit) {
15872070dbb6SStefano Zampini       if (computesubschurs) {
158808122e43SStefano Zampini         ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
15892070dbb6SStefano Zampini       }
1590d5574798SStefano Zampini       ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
1591d5574798SStefano Zampini     } else {
1592d5574798SStefano Zampini       ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
15932070dbb6SStefano Zampini       if (computesubschurs) {
1594d5574798SStefano Zampini         ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
1595d5574798SStefano Zampini       }
15962070dbb6SStefano Zampini     }
159708122e43SStefano Zampini     if (pcbddc->adaptive_selection) {
159808122e43SStefano Zampini       ierr = PCBDDCAdaptiveSelection(pc);CHKERRQ(ierr);
15998de1fae6SStefano Zampini       computeconstraintsmatrix = PETSC_TRUE;
1600b7eb3628SStefano Zampini     }
1601b1b3d7a2SStefano Zampini   }
1602684f6988SStefano Zampini 
1603f4ddd8eeSStefano Zampini   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1604fb8d54d4SStefano Zampini   new_nearnullspace_provided = PETSC_FALSE;
1605f4ddd8eeSStefano Zampini   ierr = MatGetNearNullSpace(pc->pmat,&nearnullspace);CHKERRQ(ierr);
1606f4ddd8eeSStefano Zampini   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1607f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* near null space attached to mat has been destroyed */
1608f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1609f4ddd8eeSStefano Zampini     } else {
1610f4ddd8eeSStefano Zampini       /* determine if the two nullspaces are different (should be lightweight) */
1611f4ddd8eeSStefano Zampini       if (nearnullspace != pcbddc->onearnullspace) {
1612f4ddd8eeSStefano Zampini         new_nearnullspace_provided = PETSC_TRUE;
1613165b64e2SStefano Zampini       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1614f4ddd8eeSStefano Zampini         PetscInt         i;
1615165b64e2SStefano Zampini         const Vec        *nearnullvecs;
1616165b64e2SStefano Zampini         PetscObjectState state;
1617165b64e2SStefano Zampini         PetscInt         nnsp_size;
1618165b64e2SStefano Zampini         ierr = MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
1619f4ddd8eeSStefano Zampini         for (i=0;i<nnsp_size;i++) {
1620f4ddd8eeSStefano Zampini           ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&state);CHKERRQ(ierr);
1621165b64e2SStefano Zampini           if (pcbddc->onearnullvecs_state[i] != state) {
1622f4ddd8eeSStefano Zampini             new_nearnullspace_provided = PETSC_TRUE;
1623f4ddd8eeSStefano Zampini             break;
1624f4ddd8eeSStefano Zampini           }
1625f4ddd8eeSStefano Zampini         }
1626f4ddd8eeSStefano Zampini       }
1627f4ddd8eeSStefano Zampini     }
1628f4ddd8eeSStefano Zampini   } else {
1629f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* both nearnullspaces are null */
1630f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_FALSE;
1631f4ddd8eeSStefano Zampini     } else { /* nearnullspace attached later */
1632f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1633f4ddd8eeSStefano Zampini     }
1634f4ddd8eeSStefano Zampini   }
1635f4ddd8eeSStefano Zampini 
1636f4ddd8eeSStefano Zampini   /* Setup constraints and related work vectors */
1637727cdba6SStefano Zampini   /* reset primal space flags */
1638f4ddd8eeSStefano Zampini   pcbddc->new_primal_space = PETSC_FALSE;
1639727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_FALSE;
16408de1fae6SStefano Zampini   if (computeconstraintsmatrix || new_nearnullspace_provided) {
1641727cdba6SStefano Zampini     /* It also sets the primal space flags */
1642674ae819SStefano Zampini     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
1643e7b262bdSStefano Zampini     /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
1644f4ddd8eeSStefano Zampini     ierr = PCBDDCSetUpLocalWorkVectors(pc);CHKERRQ(ierr);
16453975b054SStefano Zampini   }
16465e8657edSStefano Zampini 
16473975b054SStefano Zampini   if (computesolvers || pcbddc->new_primal_space) {
16485e8657edSStefano Zampini     if (pcbddc->use_change_of_basis) {
16495e8657edSStefano Zampini       PC_IS *pcis = (PC_IS*)(pc->data);
1650c263805aSStefano Zampini       Mat   temp_mat = NULL;
16515e8657edSStefano Zampini 
16524f1b2e48SStefano Zampini       if (pcbddc->benign_change) {
1653c263805aSStefano Zampini         /* insert B0 in pcbddc->local_mat */
1654c263805aSStefano Zampini         ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_FALSE);CHKERRQ(ierr);
1655f1a72664SStefano Zampini         /* swap local matrices */
1656f1a72664SStefano Zampini         ierr = MatISGetLocalMat(pc->pmat,&temp_mat);CHKERRQ(ierr);
1657f1a72664SStefano Zampini         ierr = PetscObjectReference((PetscObject)temp_mat);CHKERRQ(ierr);
1658f1a72664SStefano Zampini         ierr = MatISSetLocalMat(pc->pmat,pcbddc->local_mat);CHKERRQ(ierr);
1659f1a72664SStefano Zampini         ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
1660c263805aSStefano Zampini       }
16615e8657edSStefano Zampini       ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
16624f1b2e48SStefano Zampini       if (pcbddc->benign_change) {
1663c263805aSStefano Zampini         /* restore original matrix */
1664f1a72664SStefano Zampini         ierr = MatISSetLocalMat(pc->pmat,temp_mat);CHKERRQ(ierr);
1665f1a72664SStefano Zampini         ierr = PetscObjectDereference((PetscObject)temp_mat);CHKERRQ(ierr);
1666c263805aSStefano Zampini         /* pop B0 from pcbddc->local_mat */
1667c263805aSStefano Zampini         ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
1668c263805aSStefano Zampini       }
16695e8657edSStefano Zampini       /* get submatrices */
16705e8657edSStefano Zampini       ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
16715e8657edSStefano Zampini       ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
16725e8657edSStefano Zampini       ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);
16735e8657edSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr);
16745e8657edSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr);
16755e8657edSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr);
16763975b054SStefano Zampini       /* set flag in pcis to not reuse submatrices during PCISCreate */
16773975b054SStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
16789c6a02ceSStefano Zampini     } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) {
1679b96c3477SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
16805e8657edSStefano Zampini       ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
16815e8657edSStefano Zampini       pcbddc->local_mat = matis->A;
16825e8657edSStefano Zampini     }
1683b96c3477SStefano Zampini     /* SetUp coarse and local Neumann solvers */
168499cc7994SStefano Zampini     ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr);
1685b96c3477SStefano Zampini     /* SetUp Scaling operator */
1686674ae819SStefano Zampini     ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
16870c7d97c5SJed Brown   }
168856282151SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
16890369aaf7SStefano Zampini 
169058a03d70SStefano Zampini   if (pcbddc->dbg_flag) {
169158a03d70SStefano Zampini     ierr = PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
16922b510759SStefano Zampini   }
16930c7d97c5SJed Brown   PetscFunctionReturn(0);
16940c7d97c5SJed Brown }
16950c7d97c5SJed Brown 
16960c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
16970c7d97c5SJed Brown /*
169850efa1b5SStefano Zampini    PCApply_BDDC - Applies the BDDC operator to a vector.
16990c7d97c5SJed Brown 
17000c7d97c5SJed Brown    Input Parameters:
17010f202f7eSStefano Zampini +  pc - the preconditioner context
17020f202f7eSStefano Zampini -  r - input vector (global)
17030c7d97c5SJed Brown 
17040c7d97c5SJed Brown    Output Parameter:
17050c7d97c5SJed Brown .  z - output vector (global)
17060c7d97c5SJed Brown 
17070c7d97c5SJed Brown    Application Interface Routine: PCApply()
17080c7d97c5SJed Brown  */
17090c7d97c5SJed Brown #undef __FUNCT__
17100c7d97c5SJed Brown #define __FUNCT__ "PCApply_BDDC"
171153cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
17120c7d97c5SJed Brown {
17130c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
17140c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1715b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
17160c7d97c5SJed Brown   PetscErrorCode    ierr;
17173b03a366Sstefano_zampini   const PetscScalar one = 1.0;
17183b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
17192617d88aSStefano Zampini   const PetscScalar zero = 0.0;
17200c7d97c5SJed Brown 
17210c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
17220c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
1723b097fa66SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */
17240c7d97c5SJed Brown 
17250c7d97c5SJed Brown   PetscFunctionBegin;
1726015636ebSStefano Zampini   if (pcbddc->benign_saddle_point) { /* get p0 from r */
1727015636ebSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
1728efc2fbd9SStefano Zampini   }
172985c4d303SStefano Zampini   if (!pcbddc->use_exact_dirichlet_trick) {
1730b097fa66SStefano Zampini     ierr = VecCopy(r,z);CHKERRQ(ierr);
17310c7d97c5SJed Brown     /* First Dirichlet solve */
17320c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17330c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17340c7d97c5SJed Brown     /*
17350c7d97c5SJed Brown       Assembling right hand side for BDDC operator
1736b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1737674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
17380c7d97c5SJed Brown     */
1739b097fa66SStefano Zampini     if (n_D) {
1740b097fa66SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
17410c7d97c5SJed Brown       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
17428eeda7d8SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
1743b097fa66SStefano Zampini       ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
1744b097fa66SStefano Zampini     } else {
1745b097fa66SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1746b097fa66SStefano Zampini     }
17470c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
17480c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1749674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
1750b76ba322SStefano Zampini   } else {
17514fee134fSStefano Zampini     if (!pcbddc->benign_apply_coarse_only) {
1752b097fa66SStefano Zampini       if (pcbddc->switch_static) {
17530bdf917eSStefano Zampini         ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr);
1754b097fa66SStefano Zampini       }
1755674ae819SStefano Zampini       ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
1756b76ba322SStefano Zampini     }
17574fee134fSStefano Zampini   }
1758b76ba322SStefano Zampini 
17592617d88aSStefano Zampini   /* Apply interface preconditioner
17602617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
1761dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
17622617d88aSStefano Zampini 
1763674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
1764674ae819SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
17650c7d97c5SJed Brown 
17663b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
17670c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17680c7d97c5SJed Brown   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1769b097fa66SStefano Zampini   if (n_B) {
17700c7d97c5SJed Brown     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
17718eeda7d8SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
1772b097fa66SStefano Zampini   } else if (pcbddc->switch_static) {
1773b097fa66SStefano Zampini     ierr = MatMult(pcis->A_II,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
1774b097fa66SStefano Zampini   }
1775df187020SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
1776efc2fbd9SStefano Zampini 
1777b097fa66SStefano Zampini   if (!pcbddc->use_exact_dirichlet_trick) {
1778b097fa66SStefano Zampini     if (pcbddc->switch_static) {
1779b097fa66SStefano Zampini       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
1780b097fa66SStefano Zampini     } else {
1781b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
1782b097fa66SStefano Zampini     }
17830c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
17840c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1785b097fa66SStefano Zampini   } else {
1786b097fa66SStefano Zampini     if (pcbddc->switch_static) {
1787b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
1788b097fa66SStefano Zampini     } else {
1789b097fa66SStefano Zampini       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
1790b097fa66SStefano Zampini     }
1791b097fa66SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1792b097fa66SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1793b097fa66SStefano Zampini   }
1794efc2fbd9SStefano Zampini 
1795015636ebSStefano Zampini   if (pcbddc->benign_saddle_point) { /* set p0 (computed in PCBDDCApplyInterface) */
1796015636ebSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
1797efc2fbd9SStefano Zampini   }
17980c7d97c5SJed Brown   PetscFunctionReturn(0);
17990c7d97c5SJed Brown }
180050efa1b5SStefano Zampini 
180150efa1b5SStefano Zampini /* -------------------------------------------------------------------------- */
180250efa1b5SStefano Zampini /*
180350efa1b5SStefano Zampini    PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector.
180450efa1b5SStefano Zampini 
180550efa1b5SStefano Zampini    Input Parameters:
18060f202f7eSStefano Zampini +  pc - the preconditioner context
18070f202f7eSStefano Zampini -  r - input vector (global)
180850efa1b5SStefano Zampini 
180950efa1b5SStefano Zampini    Output Parameter:
181050efa1b5SStefano Zampini .  z - output vector (global)
181150efa1b5SStefano Zampini 
181250efa1b5SStefano Zampini    Application Interface Routine: PCApplyTranspose()
181350efa1b5SStefano Zampini  */
181450efa1b5SStefano Zampini #undef __FUNCT__
181550efa1b5SStefano Zampini #define __FUNCT__ "PCApplyTranspose_BDDC"
181650efa1b5SStefano Zampini PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z)
181750efa1b5SStefano Zampini {
181850efa1b5SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
181950efa1b5SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1820b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
182150efa1b5SStefano Zampini   PetscErrorCode    ierr;
182250efa1b5SStefano Zampini   const PetscScalar one = 1.0;
182350efa1b5SStefano Zampini   const PetscScalar m_one = -1.0;
182450efa1b5SStefano Zampini   const PetscScalar zero = 0.0;
182550efa1b5SStefano Zampini 
182650efa1b5SStefano Zampini   PetscFunctionBegin;
1827537c1cdfSStefano Zampini   if (pcbddc->benign_saddle_point) { /* get p0 from r */
1828537c1cdfSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
1829537c1cdfSStefano Zampini   }
183050efa1b5SStefano Zampini   if (!pcbddc->use_exact_dirichlet_trick) {
1831b097fa66SStefano Zampini     ierr = VecCopy(r,z);CHKERRQ(ierr);
183250efa1b5SStefano Zampini     /* First Dirichlet solve */
183350efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
183450efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
183550efa1b5SStefano Zampini     /*
183650efa1b5SStefano Zampini       Assembling right hand side for BDDC operator
1837b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
183850efa1b5SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
183950efa1b5SStefano Zampini     */
1840b097fa66SStefano Zampini     if (n_D) {
1841b097fa66SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
184250efa1b5SStefano Zampini       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
184350efa1b5SStefano Zampini       if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcis->A_II,pcis->vec2_D,pcis->vec1_D,pcis->vec1_D);CHKERRQ(ierr); }
1844b097fa66SStefano Zampini       ierr = MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
1845b097fa66SStefano Zampini     } else {
1846b097fa66SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1847b097fa66SStefano Zampini     }
184850efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
184950efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
185050efa1b5SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
185150efa1b5SStefano Zampini   } else {
1852b097fa66SStefano Zampini     if (pcbddc->switch_static) {
185350efa1b5SStefano Zampini       ierr = VecSet(pcis->vec1_D,zero);CHKERRQ(ierr);
1854b097fa66SStefano Zampini     }
185550efa1b5SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
185650efa1b5SStefano Zampini   }
185750efa1b5SStefano Zampini 
185850efa1b5SStefano Zampini   /* Apply interface preconditioner
185950efa1b5SStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
1860dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE);CHKERRQ(ierr);
186150efa1b5SStefano Zampini 
186250efa1b5SStefano Zampini   /* Apply transpose of partition of unity operator */
186350efa1b5SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
186450efa1b5SStefano Zampini 
186550efa1b5SStefano Zampini   /* Second Dirichlet solve and assembling of output */
186650efa1b5SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
186750efa1b5SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1868b097fa66SStefano Zampini   if (n_B) {
186950efa1b5SStefano Zampini     ierr = MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
187050efa1b5SStefano Zampini     if (pcbddc->switch_static) { ierr = MatMultTransposeAdd(pcis->A_II,pcis->vec1_D,pcis->vec3_D,pcis->vec3_D);CHKERRQ(ierr); }
1871b097fa66SStefano Zampini   } else if (pcbddc->switch_static) {
1872b097fa66SStefano Zampini     ierr = MatMultTranspose(pcis->A_II,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
1873b097fa66SStefano Zampini   }
1874b0147a47SStefano Zampini   ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
1875b097fa66SStefano Zampini   if (!pcbddc->use_exact_dirichlet_trick) {
1876b097fa66SStefano Zampini     if (pcbddc->switch_static) {
1877b097fa66SStefano Zampini       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
1878b097fa66SStefano Zampini     } else {
1879b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
1880b097fa66SStefano Zampini     }
188150efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
188250efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1883b097fa66SStefano Zampini   } else {
1884b097fa66SStefano Zampini     if (pcbddc->switch_static) {
1885b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
1886b097fa66SStefano Zampini     } else {
1887b097fa66SStefano Zampini       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
1888b097fa66SStefano Zampini     }
1889b097fa66SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1890b097fa66SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1891b097fa66SStefano Zampini   }
1892537c1cdfSStefano Zampini   if (pcbddc->benign_saddle_point) { /* set p0 (computed in PCBDDCApplyInterface) */
1893537c1cdfSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
1894537c1cdfSStefano Zampini   }
189550efa1b5SStefano Zampini   PetscFunctionReturn(0);
189650efa1b5SStefano Zampini }
1897da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
1898674ae819SStefano Zampini 
1899da1bb401SStefano Zampini #undef __FUNCT__
1900da1bb401SStefano Zampini #define __FUNCT__ "PCDestroy_BDDC"
1901da1bb401SStefano Zampini PetscErrorCode PCDestroy_BDDC(PC pc)
1902da1bb401SStefano Zampini {
1903da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1904da1bb401SStefano Zampini   PetscErrorCode ierr;
1905da1bb401SStefano Zampini 
1906da1bb401SStefano Zampini   PetscFunctionBegin;
1907da1bb401SStefano Zampini   /* free data created by PCIS */
1908da1bb401SStefano Zampini   ierr = PCISDestroy(pc);CHKERRQ(ierr);
1909674ae819SStefano Zampini   /* free BDDC custom data  */
1910674ae819SStefano Zampini   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
1911674ae819SStefano Zampini   /* destroy objects related to topography */
1912674ae819SStefano Zampini   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
1913674ae819SStefano Zampini   /* free allocated graph structure */
1914da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr);
1915b96c3477SStefano Zampini   /* free allocated sub schurs structure */
1916b96c3477SStefano Zampini   ierr = PetscFree(pcbddc->sub_schurs);CHKERRQ(ierr);
191734a97f8cSStefano Zampini   /* destroy objects for scaling operator */
1918674ae819SStefano Zampini   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
191934a97f8cSStefano Zampini   ierr = PetscFree(pcbddc->deluxe_ctx);CHKERRQ(ierr);
1920674ae819SStefano Zampini   /* free solvers stuff */
1921674ae819SStefano Zampini   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
192262a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
192362a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr);
192462a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr);
1925906d46d4SStefano Zampini   /* free stuff for change of basis hooks */
1926906d46d4SStefano Zampini   if (pcbddc->new_global_mat) {
1927906d46d4SStefano Zampini     PCBDDCChange_ctx change_ctx;
1928906d46d4SStefano Zampini     ierr = MatShellGetContext(pcbddc->new_global_mat,&change_ctx);CHKERRQ(ierr);
1929906d46d4SStefano Zampini     ierr = MatDestroy(&change_ctx->original_mat);CHKERRQ(ierr);
1930906d46d4SStefano Zampini     ierr = MatDestroy(&change_ctx->global_change);CHKERRQ(ierr);
1931906d46d4SStefano Zampini     ierr = VecDestroyVecs(2,&change_ctx->work);CHKERRQ(ierr);
1932906d46d4SStefano Zampini     ierr = PetscFree(change_ctx);CHKERRQ(ierr);
1933906d46d4SStefano Zampini   }
1934906d46d4SStefano Zampini   ierr = MatDestroy(&pcbddc->new_global_mat);CHKERRQ(ierr);
19353425bc38SStefano Zampini   /* remove functions */
1936906d46d4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL);CHKERRQ(ierr);
1937674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr);
193830368db7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",NULL);CHKERRQ(ierr);
1939bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr);
19402b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL);CHKERRQ(ierr);
1941b8ffe317SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL);CHKERRQ(ierr);
19422b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL);CHKERRQ(ierr);
1943bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",NULL);CHKERRQ(ierr);
1944bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
194582ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
1946bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
194782ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
1948bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
194982ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
1950bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
1951785d1243SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
1952bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr);
195363602bcaSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL);CHKERRQ(ierr);
1954bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr);
1955bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr);
1956bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr);
1957bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr);
1958674ae819SStefano Zampini   /* Free the private data structure */
1959674ae819SStefano Zampini   ierr = PetscFree(pc->data);CHKERRQ(ierr);
1960da1bb401SStefano Zampini   PetscFunctionReturn(0);
1961da1bb401SStefano Zampini }
19623425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
19631e6b0712SBarry Smith 
19643425bc38SStefano Zampini #undef __FUNCT__
19653425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetRHS_BDDC"
19663425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
19673425bc38SStefano Zampini {
1968674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
1969c08af4c6SStefano Zampini   Vec            copy_standard_rhs;
19703425bc38SStefano Zampini   PC_IS*         pcis;
19713425bc38SStefano Zampini   PC_BDDC*       pcbddc;
19723425bc38SStefano Zampini   PetscErrorCode ierr;
19730c7d97c5SJed Brown 
19743425bc38SStefano Zampini   PetscFunctionBegin;
19753425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
19763425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
19773425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
19783425bc38SStefano Zampini 
1979c08af4c6SStefano Zampini   /*
1980c08af4c6SStefano Zampini      change of basis for physical rhs if needed
1981c08af4c6SStefano Zampini      It also changes the rhs in case of dirichlet boundaries
1982c08af4c6SStefano Zampini      TODO: better management when FETIDP will have its own class
1983c08af4c6SStefano Zampini   */
1984c08af4c6SStefano Zampini   ierr = VecDuplicate(standard_rhs,&copy_standard_rhs);CHKERRQ(ierr);
1985c08af4c6SStefano Zampini   ierr = VecCopy(standard_rhs,copy_standard_rhs);CHKERRQ(ierr);
1986c08af4c6SStefano Zampini   ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,copy_standard_rhs,NULL);CHKERRQ(ierr);
19873425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
1988c08af4c6SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,copy_standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1989c08af4c6SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,copy_standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1990fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
1991fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
1992c08af4c6SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1993c08af4c6SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1994674ae819SStefano Zampini   /* Apply partition of unity */
19953425bc38SStefano Zampini   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
1996c08af4c6SStefano Zampini   /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,copy_standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
19978eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
19983425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
19993425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
20003425bc38SStefano Zampini     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
20013425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
2002c08af4c6SStefano Zampini     ierr = VecSet(copy_standard_rhs,0.0);CHKERRQ(ierr);
2003c08af4c6SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,copy_standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2004c08af4c6SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,copy_standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2005c08af4c6SStefano Zampini     /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,copy_standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
2006c08af4c6SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2007c08af4c6SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20083425bc38SStefano Zampini     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
20093425bc38SStefano Zampini   }
2010c08af4c6SStefano Zampini   ierr = VecDestroy(&copy_standard_rhs);CHKERRQ(ierr);
20113425bc38SStefano Zampini   /* BDDC rhs */
20123425bc38SStefano Zampini   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
20138eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
20143425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
20153425bc38SStefano Zampini   }
20163425bc38SStefano Zampini   /* apply BDDC */
2017dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
20183425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
20193425bc38SStefano Zampini   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
20203425bc38SStefano Zampini   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
20213425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20223425bc38SStefano Zampini   ierr = VecScatterEnd(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20233425bc38SStefano Zampini   PetscFunctionReturn(0);
20243425bc38SStefano Zampini }
20251e6b0712SBarry Smith 
20263425bc38SStefano Zampini #undef __FUNCT__
20273425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetRHS"
20283425bc38SStefano Zampini /*@
20290f202f7eSStefano Zampini  PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side
20303425bc38SStefano Zampini 
20313425bc38SStefano Zampini    Collective
20323425bc38SStefano Zampini 
20333425bc38SStefano Zampini    Input Parameters:
20340f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators
20350f202f7eSStefano Zampini -  standard_rhs    - the right-hand side of the original linear system
20363425bc38SStefano Zampini 
20373425bc38SStefano Zampini    Output Parameters:
20380f202f7eSStefano Zampini .  fetidp_flux_rhs - the right-hand side for the FETI-DP linear system
20393425bc38SStefano Zampini 
20403425bc38SStefano Zampini    Level: developer
20413425bc38SStefano Zampini 
20423425bc38SStefano Zampini    Notes:
20433425bc38SStefano Zampini 
20440f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetSolution
20453425bc38SStefano Zampini @*/
20463425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
20473425bc38SStefano Zampini {
2048674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
20493425bc38SStefano Zampini   PetscErrorCode ierr;
20503425bc38SStefano Zampini 
20513425bc38SStefano Zampini   PetscFunctionBegin;
20523425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
20533425bc38SStefano Zampini   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
20543425bc38SStefano Zampini   PetscFunctionReturn(0);
20553425bc38SStefano Zampini }
20563425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
20571e6b0712SBarry Smith 
20583425bc38SStefano Zampini #undef __FUNCT__
20593425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetSolution_BDDC"
20603425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
20613425bc38SStefano Zampini {
2062674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
20633425bc38SStefano Zampini   PC_IS*         pcis;
20643425bc38SStefano Zampini   PC_BDDC*       pcbddc;
20653425bc38SStefano Zampini   PetscErrorCode ierr;
20663425bc38SStefano Zampini 
20673425bc38SStefano Zampini   PetscFunctionBegin;
20683425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
20693425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
20703425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
20713425bc38SStefano Zampini 
20723425bc38SStefano Zampini   /* apply B_delta^T */
20733425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20743425bc38SStefano Zampini   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20753425bc38SStefano Zampini   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
20763425bc38SStefano Zampini   /* compute rhs for BDDC application */
20773425bc38SStefano Zampini   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
20788eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
20793425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
20803425bc38SStefano Zampini   }
20813425bc38SStefano Zampini   /* apply BDDC */
2082dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
20833425bc38SStefano Zampini   /* put values into standard global vector */
20843425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20853425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20868eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
20873425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
20883425bc38SStefano Zampini     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
20893425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_D,-1.0,pcis->vec1_D);CHKERRQ(ierr);
20903425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
20913425bc38SStefano Zampini   }
20923425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20933425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
20943425bc38SStefano Zampini   /* final change of basis if needed
20953425bc38SStefano Zampini      Is also sums the dirichlet part removed during RHS assembling */
20963308cffdSStefano Zampini   ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr);
20973425bc38SStefano Zampini   PetscFunctionReturn(0);
20983425bc38SStefano Zampini }
20991e6b0712SBarry Smith 
21003425bc38SStefano Zampini #undef __FUNCT__
21013425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetSolution"
21023425bc38SStefano Zampini /*@
21030f202f7eSStefano Zampini  PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system
21043425bc38SStefano Zampini 
21053425bc38SStefano Zampini    Collective
21063425bc38SStefano Zampini 
21073425bc38SStefano Zampini    Input Parameters:
21080f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators
21090f202f7eSStefano Zampini -  fetidp_flux_sol - the solution of the FETI-DP linear system
21103425bc38SStefano Zampini 
21113425bc38SStefano Zampini    Output Parameters:
21120f202f7eSStefano Zampini .  standard_sol    - the solution defined on the physical domain
21133425bc38SStefano Zampini 
21143425bc38SStefano Zampini    Level: developer
21153425bc38SStefano Zampini 
21163425bc38SStefano Zampini    Notes:
21173425bc38SStefano Zampini 
21180f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetRHS
21193425bc38SStefano Zampini @*/
21203425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
21213425bc38SStefano Zampini {
2122674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
21233425bc38SStefano Zampini   PetscErrorCode ierr;
21243425bc38SStefano Zampini 
21253425bc38SStefano Zampini   PetscFunctionBegin;
21263425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
21273425bc38SStefano Zampini   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
21283425bc38SStefano Zampini   PetscFunctionReturn(0);
21293425bc38SStefano Zampini }
21303425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
21311e6b0712SBarry Smith 
2132f23aa3ddSBarry Smith extern PetscErrorCode FETIDPMatMult(Mat,Vec,Vec);
2133edf7251bSStefano Zampini extern PetscErrorCode FETIDPMatMultTranspose(Mat,Vec,Vec);
2134f23aa3ddSBarry Smith extern PetscErrorCode PCBDDCDestroyFETIDPMat(Mat);
2135f23aa3ddSBarry Smith extern PetscErrorCode FETIDPPCApply(PC,Vec,Vec);
2136edf7251bSStefano Zampini extern PetscErrorCode FETIDPPCApplyTranspose(PC,Vec,Vec);
2137f23aa3ddSBarry Smith extern PetscErrorCode PCBDDCDestroyFETIDPPC(PC);
2138674ae819SStefano Zampini 
21393425bc38SStefano Zampini #undef __FUNCT__
21403425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPOperators_BDDC"
21413425bc38SStefano Zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
21423425bc38SStefano Zampini {
2143674ae819SStefano Zampini 
2144674ae819SStefano Zampini   FETIDPMat_ctx  fetidpmat_ctx;
21453425bc38SStefano Zampini   Mat            newmat;
2146674ae819SStefano Zampini   FETIDPPC_ctx   fetidppc_ctx;
21473425bc38SStefano Zampini   PC             newpc;
2148ce94432eSBarry Smith   MPI_Comm       comm;
21493425bc38SStefano Zampini   PetscErrorCode ierr;
21503425bc38SStefano Zampini 
21513425bc38SStefano Zampini   PetscFunctionBegin;
2152ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
21533425bc38SStefano Zampini   /* FETIDP linear matrix */
21543425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr);
21553425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
21563425bc38SStefano Zampini   ierr = MatCreateShell(comm,PETSC_DECIDE,PETSC_DECIDE,fetidpmat_ctx->n_lambda,fetidpmat_ctx->n_lambda,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
21573425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
2158edf7251bSStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose);CHKERRQ(ierr);
21593425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
21603425bc38SStefano Zampini   ierr = MatSetUp(newmat);CHKERRQ(ierr);
21613425bc38SStefano Zampini   /* FETIDP preconditioner */
21623425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr);
21633425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
21643425bc38SStefano Zampini   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
21653425bc38SStefano Zampini   ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
21663425bc38SStefano Zampini   ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
21673425bc38SStefano Zampini   ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
2168edf7251bSStefano Zampini   ierr = PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose);CHKERRQ(ierr);
21693425bc38SStefano Zampini   ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
217023ee1639SBarry Smith   ierr = PCSetOperators(newpc,newmat,newmat);CHKERRQ(ierr);
21713425bc38SStefano Zampini   ierr = PCSetUp(newpc);CHKERRQ(ierr);
21723425bc38SStefano Zampini   /* return pointers for objects created */
21733425bc38SStefano Zampini   *fetidp_mat=newmat;
21743425bc38SStefano Zampini   *fetidp_pc=newpc;
21753425bc38SStefano Zampini   PetscFunctionReturn(0);
21763425bc38SStefano Zampini }
21771e6b0712SBarry Smith 
21783425bc38SStefano Zampini #undef __FUNCT__
21793425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPOperators"
21803425bc38SStefano Zampini /*@
21810f202f7eSStefano Zampini  PCBDDCCreateFETIDPOperators - Create FETI-DP operators
21823425bc38SStefano Zampini 
21833425bc38SStefano Zampini    Collective
21843425bc38SStefano Zampini 
21853425bc38SStefano Zampini    Input Parameters:
21860f202f7eSStefano Zampini .  pc - the BDDC preconditioning context (setup should have been called before)
218728509bceSStefano Zampini 
218828509bceSStefano Zampini    Output Parameters:
21890f202f7eSStefano Zampini +  fetidp_mat - shell FETI-DP matrix object
21900f202f7eSStefano Zampini -  fetidp_pc  - shell Dirichlet preconditioner for FETI-DP matrix
219128509bceSStefano Zampini 
219228509bceSStefano Zampini    Options Database Keys:
21930f202f7eSStefano Zampini .    -fetidp_fullyredundant <false> - use or not a fully redundant set of Lagrange multipliers
21943425bc38SStefano Zampini 
21953425bc38SStefano Zampini    Level: developer
21963425bc38SStefano Zampini 
21973425bc38SStefano Zampini    Notes:
21980f202f7eSStefano Zampini      Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose
21993425bc38SStefano Zampini 
22000f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCMatFETIDPGetRHS, PCBDDCMatFETIDPGetSolution
22013425bc38SStefano Zampini @*/
22023425bc38SStefano Zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
22033425bc38SStefano Zampini {
22043425bc38SStefano Zampini   PetscErrorCode ierr;
22053425bc38SStefano Zampini 
22063425bc38SStefano Zampini   PetscFunctionBegin;
22073425bc38SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
22083425bc38SStefano Zampini   if (pc->setupcalled) {
2209516d51a7SStefano Zampini     ierr = PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,Mat*,PC*),(pc,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
2210f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n");
22113425bc38SStefano Zampini   PetscFunctionReturn(0);
22123425bc38SStefano Zampini }
22130c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
2214da1bb401SStefano Zampini /*MC
2215da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
22160c7d97c5SJed Brown 
221728509bceSStefano Zampini    An implementation of the BDDC preconditioner based on
221828509bceSStefano Zampini 
221928509bceSStefano Zampini .vb
222028509bceSStefano Zampini    [1] C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
222128509bceSStefano 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
222228509bceSStefano Zampini    [3] J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", http://arxiv.org/abs/0712.3977
22230f202f7eSStefano 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
222428509bceSStefano Zampini .ve
222528509bceSStefano Zampini 
222628509bceSStefano Zampini    The matrix to be preconditioned (Pmat) must be of type MATIS.
222728509bceSStefano Zampini 
22280f202f7eSStefano Zampini    Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers.
222928509bceSStefano Zampini 
223028509bceSStefano Zampini    It also works with unsymmetric and indefinite problems.
223128509bceSStefano Zampini 
2232b6fdb6dfSStefano 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.
2233b6fdb6dfSStefano Zampini 
22340f202f7eSStefano Zampini    Approximate local solvers are automatically adapted for singular linear problems (see [1]) if the user has provided the nullspace using PCBDDCSetNullSpace()
223528509bceSStefano Zampini 
22360f202f7eSStefano 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()
223730368db7SStefano Zampini    Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesIS() and their local counterparts.
223828509bceSStefano Zampini 
22390f202f7eSStefano Zampini    Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD.
224028509bceSStefano Zampini 
22410f202f7eSStefano 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.
22420f202f7eSStefano Zampini    User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat()
224328509bceSStefano Zampini 
22440f202f7eSStefano Zampini    The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object.
224528509bceSStefano Zampini 
2246df4d28bfSStefano 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.
224728509bceSStefano Zampini 
22480f202f7eSStefano 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.
22490f202f7eSStefano Zampini    Deluxe scaling is not supported yet for FETI-DP.
22500f202f7eSStefano Zampini 
22510f202f7eSStefano Zampini    Options Database Keys (some of them, run with -h for a complete list):
22520f202f7eSStefano Zampini 
22530f202f7eSStefano Zampini .    -pc_bddc_use_vertices <true> - use or not vertices in primal space
22540f202f7eSStefano Zampini .    -pc_bddc_use_edges <true> - use or not edges in primal space
22550f202f7eSStefano Zampini .    -pc_bddc_use_faces <false> - use or not faces in primal space
22560f202f7eSStefano Zampini .    -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems
22570f202f7eSStefano Zampini .    -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only)
22580f202f7eSStefano Zampini .    -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested
22590f202f7eSStefano Zampini .    -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1])
226028509bceSStefano Zampini .    -pc_bddc_levels <0> - maximum number of levels for multilevel
22610f202f7eSStefano 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)
22620f202f7eSStefano 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)
22630f202f7eSStefano Zampini .    -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling
22640f202f7eSStefano 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)
2265df4d28bfSStefano 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)
226628509bceSStefano Zampini -    -pc_bddc_check_level <0> - set verbosity level of debugging output
226728509bceSStefano Zampini 
226828509bceSStefano Zampini    Options for Dirichlet, Neumann or coarse solver can be set with
226928509bceSStefano Zampini .vb
227028509bceSStefano Zampini       -pc_bddc_dirichlet_
227128509bceSStefano Zampini       -pc_bddc_neumann_
227228509bceSStefano Zampini       -pc_bddc_coarse_
227328509bceSStefano Zampini .ve
22740f202f7eSStefano Zampini    e.g -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KPSPREONLY and PCLU.
227528509bceSStefano Zampini 
22760f202f7eSStefano Zampini    When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as
227728509bceSStefano Zampini .vb
2278312be037SStefano Zampini       -pc_bddc_dirichlet_lN_
2279312be037SStefano Zampini       -pc_bddc_neumann_lN_
2280312be037SStefano Zampini       -pc_bddc_coarse_lN_
228128509bceSStefano Zampini .ve
22820f202f7eSStefano Zampini    Note that level number ranges from the finest (0) to the coarsest (N).
22830f202f7eSStefano 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.
22840f202f7eSStefano Zampini .vb
22850f202f7eSStefano Zampini      -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3
22860f202f7eSStefano Zampini .ve
22870f202f7eSStefano 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
2288da1bb401SStefano Zampini 
2289da1bb401SStefano Zampini    Level: intermediate
2290da1bb401SStefano Zampini 
2291b6fdb6dfSStefano Zampini    Developer notes:
2292da1bb401SStefano Zampini 
2293da1bb401SStefano Zampini    Contributed by Stefano Zampini
2294da1bb401SStefano Zampini 
2295da1bb401SStefano Zampini .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
2296da1bb401SStefano Zampini M*/
2297b2573a8aSBarry Smith 
2298da1bb401SStefano Zampini #undef __FUNCT__
2299da1bb401SStefano Zampini #define __FUNCT__ "PCCreate_BDDC"
23008cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
2301da1bb401SStefano Zampini {
2302da1bb401SStefano Zampini   PetscErrorCode      ierr;
2303da1bb401SStefano Zampini   PC_BDDC             *pcbddc;
2304da1bb401SStefano Zampini 
2305da1bb401SStefano Zampini   PetscFunctionBegin;
2306da1bb401SStefano Zampini   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
2307b00a9115SJed Brown   ierr      = PetscNewLog(pc,&pcbddc);CHKERRQ(ierr);
2308da1bb401SStefano Zampini   pc->data  = (void*)pcbddc;
2309da1bb401SStefano Zampini 
2310da1bb401SStefano Zampini   /* create PCIS data structure */
2311da1bb401SStefano Zampini   ierr = PCISCreate(pc);CHKERRQ(ierr);
2312da1bb401SStefano Zampini 
231347d04d0dSStefano Zampini   /* BDDC customization */
231408a5cf49SStefano Zampini   pcbddc->use_local_adj       = PETSC_TRUE;
231547d04d0dSStefano Zampini   pcbddc->use_vertices        = PETSC_TRUE;
231647d04d0dSStefano Zampini   pcbddc->use_edges           = PETSC_TRUE;
231747d04d0dSStefano Zampini   pcbddc->use_faces           = PETSC_FALSE;
231847d04d0dSStefano Zampini   pcbddc->use_change_of_basis = PETSC_FALSE;
231947d04d0dSStefano Zampini   pcbddc->use_change_on_faces = PETSC_FALSE;
232047d04d0dSStefano Zampini   pcbddc->switch_static       = PETSC_FALSE;
2321fa434743SStefano Zampini   pcbddc->use_nnsp_true       = PETSC_FALSE;
2322fa434743SStefano Zampini   pcbddc->use_qr_single       = PETSC_FALSE;
23233301b35fSStefano Zampini   pcbddc->symmetric_primal    = PETSC_TRUE;
232406a4e24aSStefano Zampini   pcbddc->benign_saddle_point = PETSC_FALSE;
2325*14f95afaSStefano Zampini   pcbddc->vertex_size         = 1;
232647d04d0dSStefano Zampini   pcbddc->dbg_flag            = 0;
2327b9d89cd5SStefano Zampini   /* private */
2328727cdba6SStefano Zampini   pcbddc->local_primal_size          = 0;
23290e6343abSStefano Zampini   pcbddc->local_primal_size_cc       = 0;
23300e6343abSStefano Zampini   pcbddc->local_primal_ref_node      = 0;
23310e6343abSStefano Zampini   pcbddc->local_primal_ref_mult      = 0;
2332e9189074SStefano Zampini   pcbddc->n_vertices                 = 0;
2333727cdba6SStefano Zampini   pcbddc->primal_indices_local_idxs  = 0;
2334fb180af4SStefano Zampini   pcbddc->recompute_topography       = PETSC_FALSE;
233568457ee5SStefano Zampini   pcbddc->coarse_size                = -1;
2336f4ddd8eeSStefano Zampini   pcbddc->new_primal_space           = PETSC_FALSE;
2337727cdba6SStefano Zampini   pcbddc->new_primal_space_local     = PETSC_FALSE;
2338f4ddd8eeSStefano Zampini   pcbddc->global_primal_indices      = 0;
2339f4ddd8eeSStefano Zampini   pcbddc->onearnullspace             = 0;
2340f4ddd8eeSStefano Zampini   pcbddc->onearnullvecs_state        = 0;
2341674ae819SStefano Zampini   pcbddc->user_primal_vertices       = 0;
234230368db7SStefano Zampini   pcbddc->user_primal_vertices_local = 0;
23430bdf917eSStefano Zampini   pcbddc->NullSpace                  = 0;
23443972b0daSStefano Zampini   pcbddc->temp_solution              = 0;
2345534831adSStefano Zampini   pcbddc->original_rhs               = 0;
2346534831adSStefano Zampini   pcbddc->local_mat                  = 0;
2347534831adSStefano Zampini   pcbddc->ChangeOfBasisMatrix        = 0;
2348b9b85e73SStefano Zampini   pcbddc->user_ChangeOfBasisMatrix   = 0;
2349906d46d4SStefano Zampini   pcbddc->new_global_mat             = 0;
2350da1bb401SStefano Zampini   pcbddc->coarse_vec                 = 0;
2351da1bb401SStefano Zampini   pcbddc->coarse_ksp                 = 0;
2352da1bb401SStefano Zampini   pcbddc->coarse_phi_B               = 0;
2353da1bb401SStefano Zampini   pcbddc->coarse_phi_D               = 0;
235415aaf578SStefano Zampini   pcbddc->coarse_psi_B               = 0;
235515aaf578SStefano Zampini   pcbddc->coarse_psi_D               = 0;
2356da1bb401SStefano Zampini   pcbddc->vec1_P                     = 0;
2357da1bb401SStefano Zampini   pcbddc->vec1_R                     = 0;
2358da1bb401SStefano Zampini   pcbddc->vec2_R                     = 0;
2359da1bb401SStefano Zampini   pcbddc->local_auxmat1              = 0;
2360da1bb401SStefano Zampini   pcbddc->local_auxmat2              = 0;
2361da1bb401SStefano Zampini   pcbddc->R_to_B                     = 0;
2362da1bb401SStefano Zampini   pcbddc->R_to_D                     = 0;
2363da1bb401SStefano Zampini   pcbddc->ksp_D                      = 0;
2364da1bb401SStefano Zampini   pcbddc->ksp_R                      = 0;
2365da1bb401SStefano Zampini   pcbddc->NeumannBoundaries          = 0;
2366785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal     = 0;
2367785d1243SStefano Zampini   pcbddc->DirichletBoundaries        = 0;
2368785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal   = 0;
236960d44989SStefano Zampini   pcbddc->user_provided_isfordofs    = PETSC_FALSE;
237060d44989SStefano Zampini   pcbddc->n_ISForDofs                = 0;
237163602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal           = 0;
2372da1bb401SStefano Zampini   pcbddc->ISForDofs                  = 0;
237363602bcaSStefano Zampini   pcbddc->ISForDofsLocal             = 0;
2374da1bb401SStefano Zampini   pcbddc->ConstraintMatrix           = 0;
237585c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick  = PETSC_TRUE;
237647d04d0dSStefano Zampini   pcbddc->coarse_loc_to_glob         = 0;
237747d04d0dSStefano Zampini   pcbddc->coarsening_ratio           = 8;
2378b0c7d250SStefano Zampini   pcbddc->coarse_adj_red             = 0;
23794fad6a16SStefano Zampini   pcbddc->current_level              = 0;
23802b510759SStefano Zampini   pcbddc->max_levels                 = 0;
2381323d395dSStefano Zampini   pcbddc->use_coarse_estimates       = PETSC_FALSE;
238274e2c79eSStefano Zampini   pcbddc->redistribute_coarse        = 0;
2383f3bde8b3SStefano Zampini   pcbddc->coarse_subassembling       = 0;
2384323d395dSStefano Zampini   pcbddc->coarse_subassembling_init  = 0;
23854f1b2e48SStefano Zampini   pcbddc->detect_disconnected        = PETSC_FALSE;
23864f1b2e48SStefano Zampini   pcbddc->n_local_subs               = 0;
23874f1b2e48SStefano Zampini   pcbddc->local_subs                 = NULL;
238881d14e9dSStefano Zampini 
238981d14e9dSStefano Zampini   /* benign subspace trick */
239081d14e9dSStefano Zampini   pcbddc->benign_change              = 0;
23910369aaf7SStefano Zampini   pcbddc->benign_vec                 = 0;
23920369aaf7SStefano Zampini   pcbddc->benign_original_mat        = 0;
23930369aaf7SStefano Zampini   pcbddc->benign_sf                  = 0;
23944f1b2e48SStefano Zampini   pcbddc->benign_B0                  = 0;
23954f1b2e48SStefano Zampini   pcbddc->benign_n                   = 0;
23964f1b2e48SStefano Zampini   pcbddc->benign_p0                  = NULL;
23974f1b2e48SStefano Zampini   pcbddc->benign_p0_lidx             = NULL;
23984f1b2e48SStefano Zampini   pcbddc->benign_p0_gidx             = NULL;
2399b0f5fe93SStefano Zampini   pcbddc->benign_null                = PETSC_FALSE;
240081d14e9dSStefano Zampini 
2401674ae819SStefano Zampini   /* create local graph structure */
2402674ae819SStefano Zampini   ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr);
2403674ae819SStefano Zampini 
2404674ae819SStefano Zampini   /* scaling */
2405674ae819SStefano Zampini   pcbddc->work_scaling          = 0;
240634a97f8cSStefano Zampini   pcbddc->use_deluxe_scaling    = PETSC_FALSE;
2407ac632422SStefano Zampini   pcbddc->faster_deluxe         = PETSC_FALSE;
2408b96c3477SStefano Zampini 
2409b96c3477SStefano Zampini   /* create sub schurs structure */
2410b96c3477SStefano Zampini   ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
2411b96c3477SStefano Zampini   pcbddc->sub_schurs_rebuild     = PETSC_FALSE;
2412b96c3477SStefano Zampini   pcbddc->sub_schurs_layers      = -1;
2413b96c3477SStefano Zampini   pcbddc->sub_schurs_use_useradj = PETSC_FALSE;
2414b96c3477SStefano Zampini 
2415b96c3477SStefano Zampini   pcbddc->computed_rowadj = PETSC_FALSE;
2416da1bb401SStefano Zampini 
2417b7eb3628SStefano Zampini   /* adaptivity */
2418f6f667cfSStefano Zampini   pcbddc->adaptive_threshold      = 0.0;
241908122e43SStefano Zampini   pcbddc->adaptive_nmax           = 0;
2420f6f667cfSStefano Zampini   pcbddc->adaptive_nmin           = 0;
2421b7eb3628SStefano Zampini 
2422da1bb401SStefano Zampini   /* function pointers */
2423da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
242493bd9ae7SStefano Zampini   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
2425da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
2426da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
2427da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
2428da1bb401SStefano Zampini   pc->ops->view                = 0;
2429da1bb401SStefano Zampini   pc->ops->applyrichardson     = 0;
2430da1bb401SStefano Zampini   pc->ops->applysymmetricleft  = 0;
2431da1bb401SStefano Zampini   pc->ops->applysymmetricright = 0;
2432534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
2433534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
2434da1bb401SStefano Zampini 
2435da1bb401SStefano Zampini   /* composing function */
2436906d46d4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC);CHKERRQ(ierr);
2437674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
243830368db7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",PCBDDCSetPrimalVerticesIS_BDDC);CHKERRQ(ierr);
2439bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
24402b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC);CHKERRQ(ierr);
2441b8ffe317SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC);CHKERRQ(ierr);
24422b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC);CHKERRQ(ierr);
2443bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",PCBDDCSetNullSpace_BDDC);CHKERRQ(ierr);
2444bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
244582ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
2446bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
244782ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
2448bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
244982ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
2450bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
245182ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
2452bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
245363602bcaSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC);CHKERRQ(ierr);
2454bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
2455bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
2456bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
2457bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
2458da1bb401SStefano Zampini   PetscFunctionReturn(0);
2459da1bb401SStefano Zampini }
24603425bc38SStefano Zampini 
2461