xref: /petsc/src/ksp/pc/impls/bddc/bddc.c (revision f94e96cb53efac33ad09eaf54a7c841720c10bc8)
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"
354416b707SBarry Smith PetscErrorCode PCSetFromOptions_BDDC(PetscOptionItems *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);
446b78500eSPatrick Sanan   /* Primal space customization */
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);
4914f95afaSStefano 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);
5114f95afaSStefano 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);
6057de7509SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_coarse_eqs_per_proc","Number of equations per process for coarse problem redistribution (significant only at the coarsest level)","none",pcbddc->coarse_eqs_per_proc,&pcbddc->coarse_eqs_per_proc,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);
70bf3a8328SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_adaptive_userdefined","Use user-defined constraints (should be attached via MatSetNearNullSpace to pmat) in addition to those adaptively generated","none",pcbddc->adaptive_userdefined,&pcbddc->adaptive_userdefined,NULL);CHKERRQ(ierr);
714c6709b3SStefano Zampini   ierr = PetscOptionsReal("-pc_bddc_adaptive_threshold","Threshold to be used for adaptive selection of constraints","none",pcbddc->adaptive_threshold,&pcbddc->adaptive_threshold,NULL);CHKERRQ(ierr);
7208122e43SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_adaptive_nmin","Minimum number of constraints per connected components","none",pcbddc->adaptive_nmin,&pcbddc->adaptive_nmin,NULL);CHKERRQ(ierr);
7308122e43SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_adaptive_nmax","Maximum number of constraints per connected components","none",pcbddc->adaptive_nmax,&pcbddc->adaptive_nmax,NULL);CHKERRQ(ierr);
743301b35fSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_symmetric","Symmetric computation of primal basis functions","none",pcbddc->symmetric_primal,&pcbddc->symmetric_primal,NULL);CHKERRQ(ierr);
75b0c7d250SStefano Zampini   ierr = PetscOptionsInt("-pc_bddc_coarse_adj","Number of processors where to map the coarse adjacency list","none",pcbddc->coarse_adj_red,&pcbddc->coarse_adj_red,NULL);CHKERRQ(ierr);
76b3afcdbeSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_benign_trick","Apply the benign subspace trick to saddle point problems with discontinuous pressures","none",pcbddc->benign_saddle_point,&pcbddc->benign_saddle_point,NULL);CHKERRQ(ierr);
77b3afcdbeSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_benign_nonetflux","Automatic computation of no-net-flux quadrature weights","none",pcbddc->benign_compute_nonetflux,&pcbddc->benign_compute_nonetflux,NULL);CHKERRQ(ierr);
78e9627c49SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_benign_change","Compute the pressure change of basis explicitly","none",pcbddc->benign_change_explicit,&pcbddc->benign_change_explicit,NULL);CHKERRQ(ierr);
7927b6a85dSStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_benign_compute_correction","Compute the benign correction during PreSolve","none",pcbddc->benign_compute_correction,&pcbddc->benign_compute_correction,NULL);CHKERRQ(ierr);
804f1b2e48SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_detect_disconnected","Detects disconnected subdomains","none",pcbddc->detect_disconnected,&pcbddc->detect_disconnected,NULL);CHKERRQ(ierr);
8170c64980SStefano Zampini   ierr = PetscOptionsBool("-pc_bddc_eliminate_dirichlet","Whether or not we want to eliminate dirichlet dofs during presolve","none",pcbddc->eliminate_dirdofs,&pcbddc->eliminate_dirdofs,NULL);CHKERRQ(ierr);
820c7d97c5SJed Brown   ierr = PetscOptionsTail();CHKERRQ(ierr);
830c7d97c5SJed Brown   PetscFunctionReturn(0);
840c7d97c5SJed Brown }
856b78500eSPatrick Sanan 
866b78500eSPatrick Sanan /* -------------------------------------------------------------------------- */
876b78500eSPatrick Sanan #undef __FUNCT__
886b78500eSPatrick Sanan #define __FUNCT__ "PCView_BDDC"
896b78500eSPatrick Sanan static PetscErrorCode PCView_BDDC(PC pc,PetscViewer viewer)
906b78500eSPatrick Sanan {
916b78500eSPatrick Sanan   PC_BDDC              *pcbddc = (PC_BDDC*)pc->data;
92e9627c49SStefano Zampini   PC_IS                *pcis = (PC_IS*)pc->data;
936b78500eSPatrick Sanan   PetscErrorCode       ierr;
946b78500eSPatrick Sanan   PetscBool            isascii,isstring;
95e9627c49SStefano Zampini   PetscSubcomm         subcomm;
96e9627c49SStefano Zampini   PetscViewer          subviewer;
976b78500eSPatrick Sanan 
986b78500eSPatrick Sanan   PetscFunctionBegin;
996b78500eSPatrick Sanan   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
1006b78500eSPatrick Sanan   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr);
1016b78500eSPatrick Sanan   /* Nothing printed for the String viewer */
1026b78500eSPatrick Sanan   /* ASCII viewer */
1036b78500eSPatrick Sanan   if (isascii) {
104e9627c49SStefano Zampini     PetscMPIInt   color,rank;
105e9627c49SStefano Zampini     Petsc64bitInt loc[4],gsum[4],gmax[4],gmin[4];
106e9627c49SStefano Zampini     PetscScalar   interface_size;
107e9627c49SStefano Zampini     PetscReal     ratio1=0.,ratio2=0.;
108e9627c49SStefano Zampini     Vec           counter;
1096b78500eSPatrick Sanan 
110e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use verbose output: %d\n",pcbddc->dbg_flag);CHKERRQ(ierr);
111e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use user-defined CSR: %d\n",!!pcbddc->mat_graph->nvtxs_csr);CHKERRQ(ierr);
1126b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use local mat graph: %d\n",pcbddc->use_local_adj);CHKERRQ(ierr);
113e9627c49SStefano Zampini     if (pcbddc->mat_graph->twodim) {
114e9627c49SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Connectivity graph topological dimension: 2\n");CHKERRQ(ierr);
115e9627c49SStefano Zampini     } else {
116e9627c49SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Connectivity graph topological dimension: 3\n");CHKERRQ(ierr);
117e9627c49SStefano Zampini     }
118e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use vertices: %d (vertext size %d)\n",pcbddc->use_vertices,pcbddc->vertex_size);CHKERRQ(ierr);
1196b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use edges: %d\n",pcbddc->use_edges);CHKERRQ(ierr);
1206b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use faces: %d\n",pcbddc->use_faces);CHKERRQ(ierr);
1216b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use true near null space: %d\n",pcbddc->use_nnsp_true);CHKERRQ(ierr);
1226b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use QR for single constraints on cc: %d\n",pcbddc->use_qr_single);CHKERRQ(ierr);
1236b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use change of basis on local edge nodes: %d\n",pcbddc->use_change_of_basis);CHKERRQ(ierr);
1246b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use change of basis on local face nodes: %d\n",pcbddc->use_change_on_faces);CHKERRQ(ierr);
12527b6a85dSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: User defined change of basis matrix: %d\n",!!pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
12627b6a85dSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Has change of basis matrix: %d\n",!!pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
12727b6a85dSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Eliminate dirichlet boundary dofs: %d\n",pcbddc->eliminate_dirdofs);CHKERRQ(ierr);
1286b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Switch on static condensation ops around the interface preconditioner: %d\n",pcbddc->switch_static);CHKERRQ(ierr);
12927b6a85dSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use exact dirichlet trick: %d\n",pcbddc->use_exact_dirichlet_trick);CHKERRQ(ierr);
1306b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Multilevel max levels: %d\n",pcbddc->max_levels);CHKERRQ(ierr);
131e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Multilevel coarsening ratio: %d\n",pcbddc->coarsening_ratio);CHKERRQ(ierr);
1326b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use estimated eigs for coarse problem: %d\n",pcbddc->use_coarse_estimates);CHKERRQ(ierr);
1336b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use deluxe scaling: %d\n",pcbddc->use_deluxe_scaling);CHKERRQ(ierr);
134e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use deluxe zerorows: %d\n",pcbddc->deluxe_zerorows);CHKERRQ(ierr);
1356b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Rebuild interface graph for Schur principal minors: %d\n",pcbddc->sub_schurs_rebuild);CHKERRQ(ierr);
1366b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Number of dofs' layers for the computation of principal minors: %d\n",pcbddc->sub_schurs_layers);CHKERRQ(ierr);
1376b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Use user CSR graph to compute successive layers: %d\n",pcbddc->sub_schurs_use_useradj);CHKERRQ(ierr);
138e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Adaptive constraint selection threshold (active %d, userdefined %d): %g\n",pcbddc->adaptive_threshold,pcbddc->adaptive_selection,pcbddc->adaptive_userdefined);CHKERRQ(ierr);
1396b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Min constraints / connected component: %d\n",pcbddc->adaptive_nmin);CHKERRQ(ierr);
1406b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Max constraints / connected component: %d\n",pcbddc->adaptive_nmax);CHKERRQ(ierr);
141e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Invert exact Schur complement for adaptive selection: %d\n",pcbddc->sub_schurs_exact_schur);CHKERRQ(ierr);
1426b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Symmetric computation of primal basis functions: %d\n",pcbddc->symmetric_primal);CHKERRQ(ierr);
1436b78500eSPatrick Sanan     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Num. Procs. to map coarse adjacency list: %d\n",pcbddc->coarse_adj_red);CHKERRQ(ierr);
144e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Coarse eqs per proc (significant at the coarsest level): %d\n",pcbddc->coarse_eqs_per_proc);CHKERRQ(ierr);
145e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Detect disconnected: %d\n",pcbddc->detect_disconnected);CHKERRQ(ierr);
14627b6a85dSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Benign subspace trick: %d\n",pcbddc->benign_saddle_point);CHKERRQ(ierr);
14727b6a85dSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Benign subspace trick is active: %d (algebraic computation of no-net-flux %d)\n",pcbddc->benign_have_null,pcbddc->benign_compute_nonetflux);CHKERRQ(ierr);
1486b78500eSPatrick Sanan 
149e9627c49SStefano Zampini     /* compute some number on the domain decomposition */
150e9627c49SStefano Zampini     ierr = VecSet(pcis->vec1_B,1.0);CHKERRQ(ierr);
151e9627c49SStefano Zampini     ierr = MatCreateVecs(pc->pmat,&counter,0);CHKERRQ(ierr);
152e9627c49SStefano Zampini     ierr = VecSet(counter,0.0);CHKERRQ(ierr);
153e9627c49SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
154e9627c49SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,counter,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
155e9627c49SStefano Zampini     ierr = VecSum(counter,&interface_size);CHKERRQ(ierr);
156e9627c49SStefano Zampini     ierr = VecDestroy(&counter);CHKERRQ(ierr);
157e9627c49SStefano Zampini     gsum[0] = 1;
158e9627c49SStefano Zampini     gsum[1] = gsum[2] = gsum[3] = 0;
159e9627c49SStefano Zampini     loc[0] = !!pcis->n;
160e9627c49SStefano Zampini     loc[1] = pcis->n - pcis->n_B;
161e9627c49SStefano Zampini     loc[2] = pcis->n_B;
162e9627c49SStefano Zampini     loc[3] = pcbddc->local_primal_size;
163e9627c49SStefano Zampini     ierr = MPI_Reduce(loc,gsum,4,MPIU_INT64,MPI_SUM,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
164e9627c49SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = -1;
165e9627c49SStefano Zampini     ierr = MPI_Reduce(loc,gmax,4,MPIU_INT64,MPI_MAX,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
166e9627c49SStefano Zampini     if (!loc[0]) loc[1] = loc[2] = loc[3] = PETSC_MAX_INT;
167e9627c49SStefano Zampini     ierr = MPI_Reduce(loc,gmin,4,MPIU_INT64,MPI_MIN,0,PetscObjectComm((PetscObject)pc));CHKERRQ(ierr);
168e9627c49SStefano Zampini     if (pcbddc->coarse_size) {
169e9627c49SStefano Zampini       ratio1 = pc->pmat->rmap->N/(1.*pcbddc->coarse_size);
170e9627c49SStefano Zampini       ratio2 = PetscRealPart(interface_size)/pcbddc->coarse_size;
171e9627c49SStefano Zampini     }
172e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: ********************************** STATISTICS AT LEVEL %d **********************************\n",pcbddc->current_level);CHKERRQ(ierr);
173e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Global dofs sizes: all %d interface %d coarse %d\n",pc->pmat->rmap->N,(PetscInt)PetscRealPart(interface_size),pcbddc->coarse_size);CHKERRQ(ierr);
174e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Coarsening ratios: all/coarse %d interface/coarse %d\n",(PetscInt)ratio1,(PetscInt)ratio2);CHKERRQ(ierr);
175e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Active processes : %d\n",(PetscInt)gsum[0]);CHKERRQ(ierr);
176e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Dofs type        :\tMIN\tMAX\tMEAN\n",(PetscInt)gmin[1],(PetscInt)gmax[1],(PetscInt)(gsum[1]/gsum[0]));CHKERRQ(ierr);
177e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Interior  dofs   :\t%d\t%d\t%d\n",(PetscInt)gmin[1],(PetscInt)gmax[1],(PetscInt)(gsum[1]/gsum[0]));CHKERRQ(ierr);
178e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Interface dofs   :\t%d\t%d\t%d\n",(PetscInt)gmin[2],(PetscInt)gmax[2],(PetscInt)(gsum[2]/gsum[0]));CHKERRQ(ierr);
179e9627c49SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: Primal    dofs   :\t%d\t%d\t%d\n",(PetscInt)gmin[3],(PetscInt)gmax[3],(PetscInt)(gsum[3]/gsum[0]));CHKERRQ(ierr);
18027b6a85dSStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"  BDDC: ********************************** COARSE PROBLEM DETAILS *********************************\n",pcbddc->current_level);CHKERRQ(ierr);
18127b6a85dSStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
182e9627c49SStefano Zampini 
183e9627c49SStefano Zampini     /* the coarse problem can be handled with a different communicator */
184e9627c49SStefano Zampini     if (pcbddc->coarse_ksp) color = 1;
185e9627c49SStefano Zampini     else color = 0;
186e9627c49SStefano Zampini     ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)pc),&rank);CHKERRQ(ierr);
187e9627c49SStefano Zampini     ierr = PetscSubcommCreate(PetscObjectComm((PetscObject)pc),&subcomm);CHKERRQ(ierr);
188e9627c49SStefano Zampini     ierr = PetscSubcommSetNumber(subcomm,2);CHKERRQ(ierr);
189e9627c49SStefano Zampini     ierr = PetscSubcommSetTypeGeneral(subcomm,color,rank);CHKERRQ(ierr);
190e9627c49SStefano Zampini     ierr = PetscViewerGetSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer);CHKERRQ(ierr);
191e9627c49SStefano Zampini     if (color == 1) {
192e9627c49SStefano Zampini       ierr = KSPView(pcbddc->coarse_ksp,subviewer);CHKERRQ(ierr);
193e9627c49SStefano Zampini       ierr = PetscViewerFlush(subviewer);CHKERRQ(ierr);
194e9627c49SStefano Zampini     }
195e9627c49SStefano Zampini     ierr = PetscViewerRestoreSubViewer(viewer,PetscSubcommChild(subcomm),&subviewer);CHKERRQ(ierr);
196e9627c49SStefano Zampini     ierr = PetscSubcommDestroy(&subcomm);CHKERRQ(ierr);
197e9627c49SStefano Zampini     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
198e9627c49SStefano Zampini   }
1996b78500eSPatrick Sanan   PetscFunctionReturn(0);
2006b78500eSPatrick Sanan }
2016b78500eSPatrick Sanan 
2020c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
203674ae819SStefano Zampini #undef __FUNCT__
204906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCSetChangeOfBasisMat_BDDC"
2051dd7afcfSStefano Zampini static PetscErrorCode PCBDDCSetChangeOfBasisMat_BDDC(PC pc, Mat change, PetscBool interior)
206b9b85e73SStefano Zampini {
207b9b85e73SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
208b9b85e73SStefano Zampini   PetscErrorCode ierr;
209b9b85e73SStefano Zampini 
210b9b85e73SStefano Zampini   PetscFunctionBegin;
211b9b85e73SStefano Zampini   ierr = PetscObjectReference((PetscObject)change);CHKERRQ(ierr);
21256282151SStefano Zampini   ierr = MatDestroy(&pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
213b9b85e73SStefano Zampini   pcbddc->user_ChangeOfBasisMatrix = change;
2141dd7afcfSStefano Zampini   pcbddc->change_interior = interior;
215b9b85e73SStefano Zampini   PetscFunctionReturn(0);
216b9b85e73SStefano Zampini }
217b9b85e73SStefano Zampini #undef __FUNCT__
218906d46d4SStefano Zampini #define __FUNCT__ "PCBDDCSetChangeOfBasisMat"
219b9b85e73SStefano Zampini /*@
220906d46d4SStefano Zampini  PCBDDCSetChangeOfBasisMat - Set user defined change of basis for dofs
221b9b85e73SStefano Zampini 
222b9b85e73SStefano Zampini    Collective on PC
223b9b85e73SStefano Zampini 
224b9b85e73SStefano Zampini    Input Parameters:
225b9b85e73SStefano Zampini +  pc - the preconditioning context
2261dd7afcfSStefano Zampini .  change - the change of basis matrix
2271dd7afcfSStefano Zampini -  interior - whether or not the change of basis modifies interior dofs
228b9b85e73SStefano Zampini 
229b9b85e73SStefano Zampini    Level: intermediate
230b9b85e73SStefano Zampini 
231b9b85e73SStefano Zampini    Notes:
232b9b85e73SStefano Zampini 
233b9b85e73SStefano Zampini .seealso: PCBDDC
234b9b85e73SStefano Zampini @*/
2351dd7afcfSStefano Zampini PetscErrorCode PCBDDCSetChangeOfBasisMat(PC pc, Mat change, PetscBool interior)
236b9b85e73SStefano Zampini {
237b9b85e73SStefano Zampini   PetscErrorCode ierr;
238b9b85e73SStefano Zampini 
239b9b85e73SStefano Zampini   PetscFunctionBegin;
240b9b85e73SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
241b9b85e73SStefano Zampini   PetscValidHeaderSpecific(change,MAT_CLASSID,2);
242906d46d4SStefano Zampini   PetscCheckSameComm(pc,1,change,2);
243906d46d4SStefano Zampini   if (pc->mat) {
244906d46d4SStefano Zampini     PetscInt rows_c,cols_c,rows,cols;
245906d46d4SStefano Zampini     ierr = MatGetSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
246906d46d4SStefano Zampini     ierr = MatGetSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
2476c4ed002SBarry Smith     if (rows_c != rows) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of rows for change of basis matrix! %d != %d",rows_c,rows);
2486c4ed002SBarry Smith     if (cols_c != cols) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of columns for change of basis matrix! %d != %d",cols_c,cols);
249906d46d4SStefano Zampini     ierr = MatGetLocalSize(pc->mat,&rows,&cols);CHKERRQ(ierr);
250906d46d4SStefano Zampini     ierr = MatGetLocalSize(change,&rows_c,&cols_c);CHKERRQ(ierr);
2516c4ed002SBarry Smith     if (rows_c != rows) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local rows for change of basis matrix! %d != %d",rows_c,rows);
2526c4ed002SBarry Smith     if (cols_c != cols) SETERRQ2(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Invalid number of local columns for change of basis matrix! %d != %d",cols_c,cols);
253906d46d4SStefano Zampini   }
2541dd7afcfSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetChangeOfBasisMat_C",(PC,Mat,PetscBool),(pc,change,interior));CHKERRQ(ierr);
255b9b85e73SStefano Zampini   PetscFunctionReturn(0);
256b9b85e73SStefano Zampini }
257b9b85e73SStefano Zampini /* -------------------------------------------------------------------------- */
258b9b85e73SStefano Zampini #undef __FUNCT__
25930368db7SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesIS_BDDC"
26030368db7SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesIS_BDDC(PC pc, IS PrimalVertices)
26130368db7SStefano Zampini {
26230368db7SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
26356282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
26430368db7SStefano Zampini   PetscErrorCode ierr;
26530368db7SStefano Zampini 
26630368db7SStefano Zampini   PetscFunctionBegin;
26756282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
26856282151SStefano Zampini   if (pcbddc->user_primal_vertices) {
26956282151SStefano Zampini     ierr = ISEqual(PrimalVertices,pcbddc->user_primal_vertices,&isequal);CHKERRQ(ierr);
27056282151SStefano Zampini   }
27130368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
27230368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
27330368db7SStefano Zampini   pcbddc->user_primal_vertices = PrimalVertices;
27456282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
27530368db7SStefano Zampini   PetscFunctionReturn(0);
27630368db7SStefano Zampini }
27730368db7SStefano Zampini #undef __FUNCT__
27830368db7SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesIS"
27930368db7SStefano Zampini /*@
28030368db7SStefano Zampini  PCBDDCSetPrimalVerticesIS - Set additional user defined primal vertices in PCBDDC
28130368db7SStefano Zampini 
28230368db7SStefano Zampini    Collective
28330368db7SStefano Zampini 
28430368db7SStefano Zampini    Input Parameters:
28530368db7SStefano Zampini +  pc - the preconditioning context
28630368db7SStefano Zampini -  PrimalVertices - index set of primal vertices in global numbering (can be empty)
28730368db7SStefano Zampini 
28830368db7SStefano Zampini    Level: intermediate
28930368db7SStefano Zampini 
29030368db7SStefano Zampini    Notes:
29130368db7SStefano Zampini      Any process can list any global node
29230368db7SStefano Zampini 
29330368db7SStefano Zampini .seealso: PCBDDC
29430368db7SStefano Zampini @*/
29530368db7SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesIS(PC pc, IS PrimalVertices)
29630368db7SStefano Zampini {
29730368db7SStefano Zampini   PetscErrorCode ierr;
29830368db7SStefano Zampini 
29930368db7SStefano Zampini   PetscFunctionBegin;
30030368db7SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
30130368db7SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
30230368db7SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
30330368db7SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
30430368db7SStefano Zampini   PetscFunctionReturn(0);
30530368db7SStefano Zampini }
30630368db7SStefano Zampini /* -------------------------------------------------------------------------- */
30730368db7SStefano Zampini #undef __FUNCT__
308674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS_BDDC"
309674ae819SStefano Zampini static PetscErrorCode PCBDDCSetPrimalVerticesLocalIS_BDDC(PC pc, IS PrimalVertices)
310674ae819SStefano Zampini {
311674ae819SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
31256282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
313674ae819SStefano Zampini   PetscErrorCode ierr;
3141e6b0712SBarry Smith 
315674ae819SStefano Zampini   PetscFunctionBegin;
31656282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)PrimalVertices);CHKERRQ(ierr);
31756282151SStefano Zampini   if (pcbddc->user_primal_vertices_local) {
31856282151SStefano Zampini     ierr = ISEqual(PrimalVertices,pcbddc->user_primal_vertices_local,&isequal);CHKERRQ(ierr);
31956282151SStefano Zampini   }
320674ae819SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices);CHKERRQ(ierr);
32130368db7SStefano Zampini   ierr = ISDestroy(&pcbddc->user_primal_vertices_local);CHKERRQ(ierr);
32230368db7SStefano Zampini   pcbddc->user_primal_vertices_local = PrimalVertices;
32356282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
324674ae819SStefano Zampini   PetscFunctionReturn(0);
325674ae819SStefano Zampini }
326674ae819SStefano Zampini #undef __FUNCT__
327674ae819SStefano Zampini #define __FUNCT__ "PCBDDCSetPrimalVerticesLocalIS"
328674ae819SStefano Zampini /*@
32928509bceSStefano Zampini  PCBDDCSetPrimalVerticesLocalIS - Set additional user defined primal vertices in PCBDDC
330674ae819SStefano Zampini 
33117eb1463SStefano Zampini    Collective
332674ae819SStefano Zampini 
333674ae819SStefano Zampini    Input Parameters:
334674ae819SStefano Zampini +  pc - the preconditioning context
33517eb1463SStefano Zampini -  PrimalVertices - index set of primal vertices in local numbering (can be empty)
336674ae819SStefano Zampini 
337674ae819SStefano Zampini    Level: intermediate
338674ae819SStefano Zampini 
339674ae819SStefano Zampini    Notes:
340674ae819SStefano Zampini 
341674ae819SStefano Zampini .seealso: PCBDDC
342674ae819SStefano Zampini @*/
343674ae819SStefano Zampini PetscErrorCode PCBDDCSetPrimalVerticesLocalIS(PC pc, IS PrimalVertices)
344674ae819SStefano Zampini {
345674ae819SStefano Zampini   PetscErrorCode ierr;
346674ae819SStefano Zampini 
347674ae819SStefano Zampini   PetscFunctionBegin;
348674ae819SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
349674ae819SStefano Zampini   PetscValidHeaderSpecific(PrimalVertices,IS_CLASSID,2);
35017eb1463SStefano Zampini   PetscCheckSameComm(pc,1,PrimalVertices,2);
351674ae819SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetPrimalVerticesLocalIS_C",(PC,IS),(pc,PrimalVertices));CHKERRQ(ierr);
352674ae819SStefano Zampini   PetscFunctionReturn(0);
353674ae819SStefano Zampini }
354674ae819SStefano Zampini /* -------------------------------------------------------------------------- */
3550c7d97c5SJed Brown #undef __FUNCT__
3564fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetCoarseningRatio_BDDC"
3574fad6a16SStefano Zampini static PetscErrorCode PCBDDCSetCoarseningRatio_BDDC(PC pc,PetscInt k)
3584fad6a16SStefano Zampini {
3594fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
3604fad6a16SStefano Zampini 
3614fad6a16SStefano Zampini   PetscFunctionBegin;
3624fad6a16SStefano Zampini   pcbddc->coarsening_ratio = k;
3634fad6a16SStefano Zampini   PetscFunctionReturn(0);
3644fad6a16SStefano Zampini }
3651e6b0712SBarry Smith 
3664fad6a16SStefano Zampini #undef __FUNCT__
3674fad6a16SStefano Zampini #define __FUNCT__ "PCBDDCSetCoarseningRatio"
3684fad6a16SStefano Zampini /*@
36928509bceSStefano Zampini  PCBDDCSetCoarseningRatio - Set coarsening ratio used in multilevel
3704fad6a16SStefano Zampini 
3714fad6a16SStefano Zampini    Logically collective on PC
3724fad6a16SStefano Zampini 
3734fad6a16SStefano Zampini    Input Parameters:
3744fad6a16SStefano Zampini +  pc - the preconditioning context
37528509bceSStefano Zampini -  k - coarsening ratio (H/h at the coarser level)
3764fad6a16SStefano Zampini 
3770f202f7eSStefano Zampini    Options Database Keys:
3780f202f7eSStefano Zampini .    -pc_bddc_coarsening_ratio
3794fad6a16SStefano Zampini 
3804fad6a16SStefano Zampini    Level: intermediate
3814fad6a16SStefano Zampini 
3824fad6a16SStefano Zampini    Notes:
3830f202f7eSStefano Zampini      Approximatively k subdomains at the finer level will be aggregated into a single subdomain at the coarser level
3844fad6a16SStefano Zampini 
3850f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetLevels()
3864fad6a16SStefano Zampini @*/
3874fad6a16SStefano Zampini PetscErrorCode PCBDDCSetCoarseningRatio(PC pc,PetscInt k)
3884fad6a16SStefano Zampini {
3894fad6a16SStefano Zampini   PetscErrorCode ierr;
3904fad6a16SStefano Zampini 
3914fad6a16SStefano Zampini   PetscFunctionBegin;
3924fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
3932b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,k,2);
3944fad6a16SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetCoarseningRatio_C",(PC,PetscInt),(pc,k));CHKERRQ(ierr);
3954fad6a16SStefano Zampini   PetscFunctionReturn(0);
3964fad6a16SStefano Zampini }
3972b510759SStefano Zampini 
398b8ffe317SStefano Zampini /* The following functions (PCBDDCSetUseExactDirichlet PCBDDCSetLevel) are not public */
3992b510759SStefano Zampini #undef __FUNCT__
400b8ffe317SStefano Zampini #define __FUNCT__ "PCBDDCSetUseExactDirichlet_BDDC"
401b8ffe317SStefano Zampini static PetscErrorCode PCBDDCSetUseExactDirichlet_BDDC(PC pc,PetscBool flg)
402b8ffe317SStefano Zampini {
403b8ffe317SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
404b8ffe317SStefano Zampini 
405b8ffe317SStefano Zampini   PetscFunctionBegin;
40685c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick = flg;
407b8ffe317SStefano Zampini   PetscFunctionReturn(0);
408b8ffe317SStefano Zampini }
409b8ffe317SStefano Zampini 
410b8ffe317SStefano Zampini #undef __FUNCT__
411b8ffe317SStefano Zampini #define __FUNCT__ "PCBDDCSetUseExactDirichlet"
412b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetUseExactDirichlet(PC pc,PetscBool flg)
4132b510759SStefano Zampini {
4142b510759SStefano Zampini   PetscErrorCode ierr;
4152b510759SStefano Zampini 
4162b510759SStefano Zampini   PetscFunctionBegin;
4172b510759SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
418b8ffe317SStefano Zampini   PetscValidLogicalCollectiveBool(pc,flg,2);
419b8ffe317SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetUseExactDirichlet_C",(PC,PetscBool),(pc,flg));CHKERRQ(ierr);
4202b510759SStefano Zampini   PetscFunctionReturn(0);
4212b510759SStefano Zampini }
4221e6b0712SBarry Smith 
4234fad6a16SStefano Zampini #undef __FUNCT__
4242b510759SStefano Zampini #define __FUNCT__ "PCBDDCSetLevel_BDDC"
4252b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevel_BDDC(PC pc,PetscInt level)
4264fad6a16SStefano Zampini {
4274fad6a16SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
4284fad6a16SStefano Zampini 
4294fad6a16SStefano Zampini   PetscFunctionBegin;
4302b510759SStefano Zampini   pcbddc->current_level = level;
4314fad6a16SStefano Zampini   PetscFunctionReturn(0);
4324fad6a16SStefano Zampini }
4331e6b0712SBarry Smith 
4344fad6a16SStefano Zampini #undef __FUNCT__
435b8ffe317SStefano Zampini #define __FUNCT__ "PCBDDCSetLevel"
436b8ffe317SStefano Zampini PetscErrorCode PCBDDCSetLevel(PC pc,PetscInt level)
437b8ffe317SStefano Zampini {
438b8ffe317SStefano Zampini   PetscErrorCode ierr;
439b8ffe317SStefano Zampini 
440b8ffe317SStefano Zampini   PetscFunctionBegin;
441b8ffe317SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
442b8ffe317SStefano Zampini   PetscValidLogicalCollectiveInt(pc,level,2);
443b8ffe317SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLevel_C",(PC,PetscInt),(pc,level));CHKERRQ(ierr);
444b8ffe317SStefano Zampini   PetscFunctionReturn(0);
445b8ffe317SStefano Zampini }
446b8ffe317SStefano Zampini 
447b8ffe317SStefano Zampini #undef __FUNCT__
4482b510759SStefano Zampini #define __FUNCT__ "PCBDDCSetLevels_BDDC"
4492b510759SStefano Zampini static PetscErrorCode PCBDDCSetLevels_BDDC(PC pc,PetscInt levels)
4502b510759SStefano Zampini {
4512b510759SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
4522b510759SStefano Zampini 
4532b510759SStefano Zampini   PetscFunctionBegin;
4542b510759SStefano Zampini   pcbddc->max_levels = levels;
4552b510759SStefano Zampini   PetscFunctionReturn(0);
4562b510759SStefano Zampini }
4572b510759SStefano Zampini 
4582b510759SStefano Zampini #undef __FUNCT__
4592b510759SStefano Zampini #define __FUNCT__ "PCBDDCSetLevels"
4604fad6a16SStefano Zampini /*@
46128509bceSStefano Zampini  PCBDDCSetLevels - Sets the maximum number of levels for multilevel
4624fad6a16SStefano Zampini 
4634fad6a16SStefano Zampini    Logically collective on PC
4644fad6a16SStefano Zampini 
4654fad6a16SStefano Zampini    Input Parameters:
4664fad6a16SStefano Zampini +  pc - the preconditioning context
46728509bceSStefano Zampini -  levels - the maximum number of levels (max 9)
4684fad6a16SStefano Zampini 
4690f202f7eSStefano Zampini    Options Database Keys:
4700f202f7eSStefano Zampini .    -pc_bddc_levels
4714fad6a16SStefano Zampini 
4724fad6a16SStefano Zampini    Level: intermediate
4734fad6a16SStefano Zampini 
4744fad6a16SStefano Zampini    Notes:
4750f202f7eSStefano Zampini      Default value is 0, i.e. traditional one-level BDDC
4764fad6a16SStefano Zampini 
4770f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetCoarseningRatio()
4784fad6a16SStefano Zampini @*/
4792b510759SStefano Zampini PetscErrorCode PCBDDCSetLevels(PC pc,PetscInt levels)
4804fad6a16SStefano Zampini {
4814fad6a16SStefano Zampini   PetscErrorCode ierr;
4824fad6a16SStefano Zampini 
4834fad6a16SStefano Zampini   PetscFunctionBegin;
4844fad6a16SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
4852b510759SStefano Zampini   PetscValidLogicalCollectiveInt(pc,levels,2);
486312be037SStefano Zampini   if (levels > 99) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"Maximum number of levels for bddc is 99\n");
4872b510759SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetLevels_C",(PC,PetscInt),(pc,levels));CHKERRQ(ierr);
4884fad6a16SStefano Zampini   PetscFunctionReturn(0);
4894fad6a16SStefano Zampini }
4904fad6a16SStefano Zampini /* -------------------------------------------------------------------------- */
4911e6b0712SBarry Smith 
4924fad6a16SStefano Zampini #undef __FUNCT__
4930bdf917eSStefano Zampini #define __FUNCT__ "PCBDDCSetNullSpace_BDDC"
4940bdf917eSStefano Zampini static PetscErrorCode PCBDDCSetNullSpace_BDDC(PC pc,MatNullSpace NullSpace)
4950bdf917eSStefano Zampini {
4960bdf917eSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
4970bdf917eSStefano Zampini   PetscErrorCode ierr;
4980bdf917eSStefano Zampini 
4990bdf917eSStefano Zampini   PetscFunctionBegin;
5000bdf917eSStefano Zampini   ierr = PetscObjectReference((PetscObject)NullSpace);CHKERRQ(ierr);
5010bdf917eSStefano Zampini   ierr = MatNullSpaceDestroy(&pcbddc->NullSpace);CHKERRQ(ierr);
5020bdf917eSStefano Zampini   pcbddc->NullSpace = NullSpace;
5030bdf917eSStefano Zampini   PetscFunctionReturn(0);
5040bdf917eSStefano Zampini }
5051e6b0712SBarry Smith 
5060bdf917eSStefano Zampini #undef __FUNCT__
5070bdf917eSStefano Zampini #define __FUNCT__ "PCBDDCSetNullSpace"
5080bdf917eSStefano Zampini /*@
50928509bceSStefano Zampini  PCBDDCSetNullSpace - Set nullspace for BDDC operator
5100bdf917eSStefano Zampini 
5110bdf917eSStefano Zampini    Logically collective on PC and MatNullSpace
5120bdf917eSStefano Zampini 
5130bdf917eSStefano Zampini    Input Parameters:
5140bdf917eSStefano Zampini +  pc - the preconditioning context
51528509bceSStefano Zampini -  NullSpace - Null space of the linear operator to be preconditioned (Pmat)
5160bdf917eSStefano Zampini 
5170bdf917eSStefano Zampini    Level: intermediate
5180bdf917eSStefano Zampini 
5190bdf917eSStefano Zampini    Notes:
5200bdf917eSStefano Zampini 
5210bdf917eSStefano Zampini .seealso: PCBDDC
5220bdf917eSStefano Zampini @*/
5230bdf917eSStefano Zampini PetscErrorCode PCBDDCSetNullSpace(PC pc,MatNullSpace NullSpace)
5240bdf917eSStefano Zampini {
5250bdf917eSStefano Zampini   PetscErrorCode ierr;
5260bdf917eSStefano Zampini 
5270bdf917eSStefano Zampini   PetscFunctionBegin;
5280bdf917eSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
529674ae819SStefano Zampini   PetscValidHeaderSpecific(NullSpace,MAT_NULLSPACE_CLASSID,2);
5302b510759SStefano Zampini   PetscCheckSameComm(pc,1,NullSpace,2);
5310bdf917eSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNullSpace_C",(PC,MatNullSpace),(pc,NullSpace));CHKERRQ(ierr);
5320bdf917eSStefano Zampini   PetscFunctionReturn(0);
5330bdf917eSStefano Zampini }
5340bdf917eSStefano Zampini /* -------------------------------------------------------------------------- */
5351e6b0712SBarry Smith 
5360bdf917eSStefano Zampini #undef __FUNCT__
5373b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries_BDDC"
5383b03a366Sstefano_zampini static PetscErrorCode PCBDDCSetDirichletBoundaries_BDDC(PC pc,IS DirichletBoundaries)
5393b03a366Sstefano_zampini {
5403b03a366Sstefano_zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
54156282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
5423b03a366Sstefano_zampini   PetscErrorCode ierr;
5433b03a366Sstefano_zampini 
5443b03a366Sstefano_zampini   PetscFunctionBegin;
54556282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
54656282151SStefano Zampini   if (pcbddc->DirichletBoundaries) {
54756282151SStefano Zampini     ierr = ISEqual(DirichletBoundaries,pcbddc->DirichletBoundaries,&isequal);CHKERRQ(ierr);
54856282151SStefano Zampini   }
549785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
550785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
5513b03a366Sstefano_zampini   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
55236e030ebSStefano Zampini   pcbddc->DirichletBoundaries = DirichletBoundaries;
55356282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
5543b03a366Sstefano_zampini   PetscFunctionReturn(0);
5553b03a366Sstefano_zampini }
5561e6b0712SBarry Smith 
5573b03a366Sstefano_zampini #undef __FUNCT__
5583b03a366Sstefano_zampini #define __FUNCT__ "PCBDDCSetDirichletBoundaries"
5593b03a366Sstefano_zampini /*@
56028509bceSStefano Zampini  PCBDDCSetDirichletBoundaries - Set IS defining Dirichlet boundaries for the global problem.
5613b03a366Sstefano_zampini 
562785d1243SStefano Zampini    Collective
5633b03a366Sstefano_zampini 
5643b03a366Sstefano_zampini    Input Parameters:
5653b03a366Sstefano_zampini +  pc - the preconditioning context
566785d1243SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries
5673b03a366Sstefano_zampini 
5683b03a366Sstefano_zampini    Level: intermediate
5693b03a366Sstefano_zampini 
5700f202f7eSStefano Zampini    Notes:
5710f202f7eSStefano Zampini      Provide the information if you used MatZeroRows/Columns routines. Any process can list any global node
5723b03a366Sstefano_zampini 
5730f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundariesLocal(), MatZeroRows(), MatZeroRowsColumns()
5743b03a366Sstefano_zampini @*/
5753b03a366Sstefano_zampini PetscErrorCode PCBDDCSetDirichletBoundaries(PC pc,IS DirichletBoundaries)
5763b03a366Sstefano_zampini {
5773b03a366Sstefano_zampini   PetscErrorCode ierr;
5783b03a366Sstefano_zampini 
5793b03a366Sstefano_zampini   PetscFunctionBegin;
5803b03a366Sstefano_zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
581674ae819SStefano Zampini   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
582785d1243SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
5833b03a366Sstefano_zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundaries_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
5843b03a366Sstefano_zampini   PetscFunctionReturn(0);
5853b03a366Sstefano_zampini }
5863b03a366Sstefano_zampini /* -------------------------------------------------------------------------- */
5871e6b0712SBarry Smith 
5883b03a366Sstefano_zampini #undef __FUNCT__
58982ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCSetDirichletBoundariesLocal_BDDC"
59082ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetDirichletBoundariesLocal_BDDC(PC pc,IS DirichletBoundaries)
5910c7d97c5SJed Brown {
5920c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
59356282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
5940c7d97c5SJed Brown   PetscErrorCode ierr;
5950c7d97c5SJed Brown 
5960c7d97c5SJed Brown   PetscFunctionBegin;
59756282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)DirichletBoundaries);CHKERRQ(ierr);
59856282151SStefano Zampini   if (pcbddc->DirichletBoundariesLocal) {
59956282151SStefano Zampini     ierr = ISEqual(DirichletBoundaries,pcbddc->DirichletBoundariesLocal,&isequal);CHKERRQ(ierr);
60056282151SStefano Zampini   }
601785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
602785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->DirichletBoundariesLocal);CHKERRQ(ierr);
6030c7d97c5SJed Brown   ierr = ISDestroy(&pcbddc->DirichletBoundaries);CHKERRQ(ierr);
604785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal = DirichletBoundaries;
60556282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
6060c7d97c5SJed Brown   PetscFunctionReturn(0);
6070c7d97c5SJed Brown }
6080c7d97c5SJed Brown 
6090c7d97c5SJed Brown #undef __FUNCT__
61082ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCSetDirichletBoundariesLocal"
6119c0446d6SStefano Zampini /*@
61282ba6b80SStefano Zampini  PCBDDCSetDirichletBoundariesLocal - Set IS defining Dirichlet boundaries for the global problem in local ordering.
6139c0446d6SStefano Zampini 
614785d1243SStefano Zampini    Collective
61553cdbc3dSStefano Zampini 
61653cdbc3dSStefano Zampini    Input Parameters:
61753cdbc3dSStefano Zampini +  pc - the preconditioning context
61882ba6b80SStefano Zampini -  DirichletBoundaries - parallel IS defining the Dirichlet boundaries (in local ordering)
61953cdbc3dSStefano Zampini 
62053cdbc3dSStefano Zampini    Level: intermediate
62153cdbc3dSStefano Zampini 
6229c0446d6SStefano Zampini    Notes:
62353cdbc3dSStefano Zampini 
6240f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetDirichletBoundaries(), MatZeroRows(), MatZeroRowsColumns()
62553cdbc3dSStefano Zampini @*/
62682ba6b80SStefano Zampini PetscErrorCode PCBDDCSetDirichletBoundariesLocal(PC pc,IS DirichletBoundaries)
6270c7d97c5SJed Brown {
6280c7d97c5SJed Brown   PetscErrorCode ierr;
6290c7d97c5SJed Brown 
6300c7d97c5SJed Brown   PetscFunctionBegin;
6310c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
6320c7d97c5SJed Brown   PetscValidHeaderSpecific(DirichletBoundaries,IS_CLASSID,2);
63382ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,DirichletBoundaries,2);
63482ba6b80SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDirichletBoundariesLocal_C",(PC,IS),(pc,DirichletBoundaries));CHKERRQ(ierr);
6350c7d97c5SJed Brown   PetscFunctionReturn(0);
6360c7d97c5SJed Brown }
6370c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
6380c7d97c5SJed Brown 
6390c7d97c5SJed Brown #undef __FUNCT__
6400c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries_BDDC"
64153cdbc3dSStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundaries_BDDC(PC pc,IS NeumannBoundaries)
6420c7d97c5SJed Brown {
6430c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
64456282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
64553cdbc3dSStefano Zampini   PetscErrorCode ierr;
6460c7d97c5SJed Brown 
6470c7d97c5SJed Brown   PetscFunctionBegin;
64856282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
64956282151SStefano Zampini   if (pcbddc->NeumannBoundaries) {
65056282151SStefano Zampini     ierr = ISEqual(NeumannBoundaries,pcbddc->NeumannBoundaries,&isequal);CHKERRQ(ierr);
65156282151SStefano Zampini   }
652785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
653785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
65453cdbc3dSStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
65536e030ebSStefano Zampini   pcbddc->NeumannBoundaries = NeumannBoundaries;
65656282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
6570c7d97c5SJed Brown   PetscFunctionReturn(0);
6580c7d97c5SJed Brown }
6591e6b0712SBarry Smith 
6600c7d97c5SJed Brown #undef __FUNCT__
6610c7d97c5SJed Brown #define __FUNCT__ "PCBDDCSetNeumannBoundaries"
66257527edcSJed Brown /*@
66328509bceSStefano Zampini  PCBDDCSetNeumannBoundaries - Set IS defining Neumann boundaries for the global problem.
66457527edcSJed Brown 
665785d1243SStefano Zampini    Collective
66657527edcSJed Brown 
66757527edcSJed Brown    Input Parameters:
66857527edcSJed Brown +  pc - the preconditioning context
669785d1243SStefano Zampini -  NeumannBoundaries - parallel IS defining the Neumann boundaries
67057527edcSJed Brown 
67157527edcSJed Brown    Level: intermediate
67257527edcSJed Brown 
6730f202f7eSStefano Zampini    Notes:
6740f202f7eSStefano Zampini      Any process can list any global node
67557527edcSJed Brown 
6760f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundariesLocal()
67757527edcSJed Brown @*/
67853cdbc3dSStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundaries(PC pc,IS NeumannBoundaries)
6790c7d97c5SJed Brown {
6800c7d97c5SJed Brown   PetscErrorCode ierr;
6810c7d97c5SJed Brown 
6820c7d97c5SJed Brown   PetscFunctionBegin;
6830c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
684674ae819SStefano Zampini   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
685785d1243SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
68653cdbc3dSStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundaries_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
68753cdbc3dSStefano Zampini   PetscFunctionReturn(0);
68853cdbc3dSStefano Zampini }
68953cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
6901e6b0712SBarry Smith 
69153cdbc3dSStefano Zampini #undef __FUNCT__
69282ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCSetNeumannBoundariesLocal_BDDC"
69382ba6b80SStefano Zampini static PetscErrorCode PCBDDCSetNeumannBoundariesLocal_BDDC(PC pc,IS NeumannBoundaries)
6940c7d97c5SJed Brown {
6950c7d97c5SJed Brown   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
69656282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
6970c7d97c5SJed Brown   PetscErrorCode ierr;
6980c7d97c5SJed Brown 
6990c7d97c5SJed Brown   PetscFunctionBegin;
70056282151SStefano Zampini   ierr = PetscObjectReference((PetscObject)NeumannBoundaries);CHKERRQ(ierr);
70156282151SStefano Zampini   if (pcbddc->NeumannBoundariesLocal) {
70256282151SStefano Zampini     ierr = ISEqual(NeumannBoundaries,pcbddc->NeumannBoundariesLocal,&isequal);CHKERRQ(ierr);
70356282151SStefano Zampini   }
704785d1243SStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
705785d1243SStefano Zampini   ierr = ISDestroy(&pcbddc->NeumannBoundariesLocal);CHKERRQ(ierr);
7060c7d97c5SJed Brown   ierr = ISDestroy(&pcbddc->NeumannBoundaries);CHKERRQ(ierr);
707785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal = NeumannBoundaries;
70856282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
7090c7d97c5SJed Brown   PetscFunctionReturn(0);
7100c7d97c5SJed Brown }
7110c7d97c5SJed Brown 
7120c7d97c5SJed Brown #undef __FUNCT__
71382ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCSetNeumannBoundariesLocal"
7140c7d97c5SJed Brown /*@
71582ba6b80SStefano Zampini  PCBDDCSetNeumannBoundariesLocal - Set IS defining Neumann boundaries for the global problem in local ordering.
7160c7d97c5SJed Brown 
717785d1243SStefano Zampini    Collective
7180c7d97c5SJed Brown 
7190c7d97c5SJed Brown    Input Parameters:
7200c7d97c5SJed Brown +  pc - the preconditioning context
72182ba6b80SStefano Zampini -  NeumannBoundaries - parallel IS defining the subdomain part of Neumann boundaries (in local ordering)
7220c7d97c5SJed Brown 
7230c7d97c5SJed Brown    Level: intermediate
7240c7d97c5SJed Brown 
7250c7d97c5SJed Brown    Notes:
7260c7d97c5SJed Brown 
7270f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCSetNeumannBoundaries()
7280c7d97c5SJed Brown @*/
72982ba6b80SStefano Zampini PetscErrorCode PCBDDCSetNeumannBoundariesLocal(PC pc,IS NeumannBoundaries)
7300c7d97c5SJed Brown {
7310c7d97c5SJed Brown   PetscErrorCode ierr;
7320c7d97c5SJed Brown 
7330c7d97c5SJed Brown   PetscFunctionBegin;
7340c7d97c5SJed Brown   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
7350c7d97c5SJed Brown   PetscValidHeaderSpecific(NeumannBoundaries,IS_CLASSID,2);
73682ba6b80SStefano Zampini   PetscCheckSameComm(pc,1,NeumannBoundaries,2);
73782ba6b80SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetNeumannBoundariesLocal_C",(PC,IS),(pc,NeumannBoundaries));CHKERRQ(ierr);
73853cdbc3dSStefano Zampini   PetscFunctionReturn(0);
73953cdbc3dSStefano Zampini }
74053cdbc3dSStefano Zampini /* -------------------------------------------------------------------------- */
74153cdbc3dSStefano Zampini 
74253cdbc3dSStefano Zampini #undef __FUNCT__
743da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries_BDDC"
744da1bb401SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundaries_BDDC(PC pc,IS *DirichletBoundaries)
745da1bb401SStefano Zampini {
746da1bb401SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
747da1bb401SStefano Zampini 
748da1bb401SStefano Zampini   PetscFunctionBegin;
749da1bb401SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundaries;
750da1bb401SStefano Zampini   PetscFunctionReturn(0);
751da1bb401SStefano Zampini }
7521e6b0712SBarry Smith 
753da1bb401SStefano Zampini #undef __FUNCT__
754da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundaries"
755da1bb401SStefano Zampini /*@
756785d1243SStefano Zampini  PCBDDCGetDirichletBoundaries - Get parallel IS for Dirichlet boundaries
757da1bb401SStefano Zampini 
758785d1243SStefano Zampini    Collective
759785d1243SStefano Zampini 
760785d1243SStefano Zampini    Input Parameters:
761785d1243SStefano Zampini .  pc - the preconditioning context
762785d1243SStefano Zampini 
763785d1243SStefano Zampini    Output Parameters:
764785d1243SStefano Zampini .  DirichletBoundaries - index set defining the Dirichlet boundaries
765785d1243SStefano Zampini 
766785d1243SStefano Zampini    Level: intermediate
767785d1243SStefano Zampini 
7680f202f7eSStefano Zampini    Notes:
7690f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetDirichletBoundaries
770785d1243SStefano Zampini 
771785d1243SStefano Zampini .seealso: PCBDDC
772785d1243SStefano Zampini @*/
773785d1243SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundaries(PC pc,IS *DirichletBoundaries)
774785d1243SStefano Zampini {
775785d1243SStefano Zampini   PetscErrorCode ierr;
776785d1243SStefano Zampini 
777785d1243SStefano Zampini   PetscFunctionBegin;
778785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
779785d1243SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundaries_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
780785d1243SStefano Zampini   PetscFunctionReturn(0);
781785d1243SStefano Zampini }
782785d1243SStefano Zampini /* -------------------------------------------------------------------------- */
783785d1243SStefano Zampini 
784785d1243SStefano Zampini #undef __FUNCT__
785785d1243SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundariesLocal_BDDC"
786785d1243SStefano Zampini static PetscErrorCode PCBDDCGetDirichletBoundariesLocal_BDDC(PC pc,IS *DirichletBoundaries)
787785d1243SStefano Zampini {
788785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
789785d1243SStefano Zampini 
790785d1243SStefano Zampini   PetscFunctionBegin;
791785d1243SStefano Zampini   *DirichletBoundaries = pcbddc->DirichletBoundariesLocal;
792785d1243SStefano Zampini   PetscFunctionReturn(0);
793785d1243SStefano Zampini }
794785d1243SStefano Zampini 
795785d1243SStefano Zampini #undef __FUNCT__
79682ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCGetDirichletBoundariesLocal"
797da1bb401SStefano Zampini /*@
79882ba6b80SStefano Zampini  PCBDDCGetDirichletBoundariesLocal - Get parallel IS for Dirichlet boundaries (in local ordering)
799da1bb401SStefano Zampini 
800785d1243SStefano Zampini    Collective
801da1bb401SStefano Zampini 
802da1bb401SStefano Zampini    Input Parameters:
80328509bceSStefano Zampini .  pc - the preconditioning context
804da1bb401SStefano Zampini 
805da1bb401SStefano Zampini    Output Parameters:
80628509bceSStefano Zampini .  DirichletBoundaries - index set defining the subdomain part of Dirichlet boundaries
807da1bb401SStefano Zampini 
808da1bb401SStefano Zampini    Level: intermediate
809da1bb401SStefano Zampini 
810da1bb401SStefano Zampini    Notes:
8110f202f7eSStefano 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).
8120f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
813da1bb401SStefano Zampini 
814da1bb401SStefano Zampini .seealso: PCBDDC
815da1bb401SStefano Zampini @*/
81682ba6b80SStefano Zampini PetscErrorCode PCBDDCGetDirichletBoundariesLocal(PC pc,IS *DirichletBoundaries)
817da1bb401SStefano Zampini {
818da1bb401SStefano Zampini   PetscErrorCode ierr;
819da1bb401SStefano Zampini 
820da1bb401SStefano Zampini   PetscFunctionBegin;
821da1bb401SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
82282ba6b80SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetDirichletBoundariesLocal_C",(PC,IS*),(pc,DirichletBoundaries));CHKERRQ(ierr);
823da1bb401SStefano Zampini   PetscFunctionReturn(0);
824da1bb401SStefano Zampini }
825da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
8261e6b0712SBarry Smith 
827da1bb401SStefano Zampini #undef __FUNCT__
82853cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries_BDDC"
82953cdbc3dSStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundaries_BDDC(PC pc,IS *NeumannBoundaries)
83053cdbc3dSStefano Zampini {
83153cdbc3dSStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
83253cdbc3dSStefano Zampini 
83353cdbc3dSStefano Zampini   PetscFunctionBegin;
83453cdbc3dSStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundaries;
83553cdbc3dSStefano Zampini   PetscFunctionReturn(0);
83653cdbc3dSStefano Zampini }
8371e6b0712SBarry Smith 
83853cdbc3dSStefano Zampini #undef __FUNCT__
83953cdbc3dSStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundaries"
84053cdbc3dSStefano Zampini /*@
841785d1243SStefano Zampini  PCBDDCGetNeumannBoundaries - Get parallel IS for Neumann boundaries
84253cdbc3dSStefano Zampini 
843785d1243SStefano Zampini    Collective
844785d1243SStefano Zampini 
845785d1243SStefano Zampini    Input Parameters:
846785d1243SStefano Zampini .  pc - the preconditioning context
847785d1243SStefano Zampini 
848785d1243SStefano Zampini    Output Parameters:
849785d1243SStefano Zampini .  NeumannBoundaries - index set defining the Neumann boundaries
850785d1243SStefano Zampini 
851785d1243SStefano Zampini    Level: intermediate
852785d1243SStefano Zampini 
8530f202f7eSStefano Zampini    Notes:
8540f202f7eSStefano Zampini      The IS returned (if any) is the same passed in earlier by the user with PCBDDCSetNeumannBoundaries
855785d1243SStefano Zampini 
856785d1243SStefano Zampini .seealso: PCBDDC
857785d1243SStefano Zampini @*/
858785d1243SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundaries(PC pc,IS *NeumannBoundaries)
859785d1243SStefano Zampini {
860785d1243SStefano Zampini   PetscErrorCode ierr;
861785d1243SStefano Zampini 
862785d1243SStefano Zampini   PetscFunctionBegin;
863785d1243SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
864785d1243SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundaries_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
865785d1243SStefano Zampini   PetscFunctionReturn(0);
866785d1243SStefano Zampini }
867785d1243SStefano Zampini /* -------------------------------------------------------------------------- */
868785d1243SStefano Zampini 
869785d1243SStefano Zampini #undef __FUNCT__
870785d1243SStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundariesLocal_BDDC"
871785d1243SStefano Zampini static PetscErrorCode PCBDDCGetNeumannBoundariesLocal_BDDC(PC pc,IS *NeumannBoundaries)
872785d1243SStefano Zampini {
873785d1243SStefano Zampini   PC_BDDC  *pcbddc = (PC_BDDC*)pc->data;
874785d1243SStefano Zampini 
875785d1243SStefano Zampini   PetscFunctionBegin;
876785d1243SStefano Zampini   *NeumannBoundaries = pcbddc->NeumannBoundariesLocal;
877785d1243SStefano Zampini   PetscFunctionReturn(0);
878785d1243SStefano Zampini }
879785d1243SStefano Zampini 
880785d1243SStefano Zampini #undef __FUNCT__
88182ba6b80SStefano Zampini #define __FUNCT__ "PCBDDCGetNeumannBoundariesLocal"
88253cdbc3dSStefano Zampini /*@
88382ba6b80SStefano Zampini  PCBDDCGetNeumannBoundariesLocal - Get parallel IS for Neumann boundaries (in local ordering)
88453cdbc3dSStefano Zampini 
885785d1243SStefano Zampini    Collective
88653cdbc3dSStefano Zampini 
88753cdbc3dSStefano Zampini    Input Parameters:
88828509bceSStefano Zampini .  pc - the preconditioning context
88953cdbc3dSStefano Zampini 
89053cdbc3dSStefano Zampini    Output Parameters:
89128509bceSStefano Zampini .  NeumannBoundaries - index set defining the subdomain part of Neumann boundaries
89253cdbc3dSStefano Zampini 
89353cdbc3dSStefano Zampini    Level: intermediate
89453cdbc3dSStefano Zampini 
89553cdbc3dSStefano Zampini    Notes:
8960f202f7eSStefano 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).
8970f202f7eSStefano Zampini           In the latter case, the IS will be available after PCSetUp.
89853cdbc3dSStefano Zampini 
89953cdbc3dSStefano Zampini .seealso: PCBDDC
90053cdbc3dSStefano Zampini @*/
90182ba6b80SStefano Zampini PetscErrorCode PCBDDCGetNeumannBoundariesLocal(PC pc,IS *NeumannBoundaries)
90253cdbc3dSStefano Zampini {
90353cdbc3dSStefano Zampini   PetscErrorCode ierr;
90453cdbc3dSStefano Zampini 
90553cdbc3dSStefano Zampini   PetscFunctionBegin;
90653cdbc3dSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
90782ba6b80SStefano Zampini   ierr = PetscUseMethod(pc,"PCBDDCGetNeumannBoundariesLocal_C",(PC,IS*),(pc,NeumannBoundaries));CHKERRQ(ierr);
9080c7d97c5SJed Brown   PetscFunctionReturn(0);
9090c7d97c5SJed Brown }
91036e030ebSStefano Zampini /* -------------------------------------------------------------------------- */
9111e6b0712SBarry Smith 
91236e030ebSStefano Zampini #undef __FUNCT__
913da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph_BDDC"
9141a83f524SJed Brown static PetscErrorCode PCBDDCSetLocalAdjacencyGraph_BDDC(PC pc, PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
91536e030ebSStefano Zampini {
91636e030ebSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
917da1bb401SStefano Zampini   PCBDDCGraph    mat_graph = pcbddc->mat_graph;
91856282151SStefano Zampini   PetscBool      same_data = PETSC_FALSE;
919da1bb401SStefano Zampini   PetscErrorCode ierr;
92036e030ebSStefano Zampini 
92136e030ebSStefano Zampini   PetscFunctionBegin;
9228687889aSStefano Zampini   if (!nvtxs) {
9238687889aSStefano Zampini     ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
9248687889aSStefano Zampini     PetscFunctionReturn(0);
9258687889aSStefano Zampini   }
92656282151SStefano Zampini   if (mat_graph->nvtxs_csr == nvtxs) {
92756282151SStefano Zampini     if (mat_graph->xadj == xadj && mat_graph->adjncy == adjncy) same_data = PETSC_TRUE;
92856282151SStefano Zampini     if (!same_data && mat_graph->xadj[nvtxs] == xadj[nvtxs]) {
92956282151SStefano Zampini       ierr = PetscMemcmp(adjncy,mat_graph->adjncy,nvtxs*sizeof(PetscInt),&same_data);CHKERRQ(ierr);
93056282151SStefano Zampini     }
93156282151SStefano Zampini   }
93256282151SStefano Zampini   if (!same_data) {
933674ae819SStefano Zampini     /* free old CSR */
934674ae819SStefano Zampini     ierr = PCBDDCGraphResetCSR(mat_graph);CHKERRQ(ierr);
935674ae819SStefano Zampini     /* get CSR into graph structure */
936da1bb401SStefano Zampini     if (copymode == PETSC_COPY_VALUES) {
937854ce69bSBarry Smith       ierr = PetscMalloc1(nvtxs+1,&mat_graph->xadj);CHKERRQ(ierr);
938785e854fSJed Brown       ierr = PetscMalloc1(xadj[nvtxs],&mat_graph->adjncy);CHKERRQ(ierr);
939674ae819SStefano Zampini       ierr = PetscMemcpy(mat_graph->xadj,xadj,(nvtxs+1)*sizeof(PetscInt));CHKERRQ(ierr);
940674ae819SStefano Zampini       ierr = PetscMemcpy(mat_graph->adjncy,adjncy,xadj[nvtxs]*sizeof(PetscInt));CHKERRQ(ierr);
941da1bb401SStefano Zampini     } else if (copymode == PETSC_OWN_POINTER) {
9421a83f524SJed Brown       mat_graph->xadj = (PetscInt*)xadj;
9431a83f524SJed Brown       mat_graph->adjncy = (PetscInt*)adjncy;
944674ae819SStefano Zampini     }
945575ad6abSStefano Zampini     mat_graph->nvtxs_csr = nvtxs;
94656282151SStefano Zampini     pcbddc->recompute_topography = PETSC_TRUE;
94756282151SStefano Zampini   }
94836e030ebSStefano Zampini   PetscFunctionReturn(0);
94936e030ebSStefano Zampini }
9501e6b0712SBarry Smith 
95136e030ebSStefano Zampini #undef __FUNCT__
952da1bb401SStefano Zampini #define __FUNCT__ "PCBDDCSetLocalAdjacencyGraph"
95336e030ebSStefano Zampini /*@
9540f202f7eSStefano Zampini  PCBDDCSetLocalAdjacencyGraph - Set adjacency structure (CSR graph) of the local matrix
95536e030ebSStefano Zampini 
95636e030ebSStefano Zampini    Not collective
95736e030ebSStefano Zampini 
95836e030ebSStefano Zampini    Input Parameters:
95936e030ebSStefano Zampini +  pc - the preconditioning context
9600f202f7eSStefano Zampini .  nvtxs - number of local vertices of the graph (i.e., the size of the local problem)
96128509bceSStefano Zampini .  xadj, adjncy - the CSR graph
96228509bceSStefano Zampini -  copymode - either PETSC_COPY_VALUES or PETSC_OWN_POINTER.
96336e030ebSStefano Zampini 
96436e030ebSStefano Zampini    Level: intermediate
96536e030ebSStefano Zampini 
96636e030ebSStefano Zampini    Notes:
96736e030ebSStefano Zampini 
96828509bceSStefano Zampini .seealso: PCBDDC,PetscCopyMode
96936e030ebSStefano Zampini @*/
9701a83f524SJed Brown PetscErrorCode PCBDDCSetLocalAdjacencyGraph(PC pc,PetscInt nvtxs,const PetscInt xadj[],const PetscInt adjncy[], PetscCopyMode copymode)
97136e030ebSStefano Zampini {
972575ad6abSStefano Zampini   void (*f)(void) = 0;
97336e030ebSStefano Zampini   PetscErrorCode ierr;
97436e030ebSStefano Zampini 
97536e030ebSStefano Zampini   PetscFunctionBegin;
97636e030ebSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
9778687889aSStefano Zampini   if (nvtxs) {
978674ae819SStefano Zampini     PetscValidIntPointer(xadj,3);
979d7de1dd9SStefano Zampini     PetscValidIntPointer(adjncy,4);
9808687889aSStefano Zampini   }
9816c4ed002SBarry Smith   if (copymode != PETSC_COPY_VALUES && copymode != PETSC_OWN_POINTER)  SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Unsupported copy mode %d",copymode);
9821a83f524SJed Brown   ierr = PetscTryMethod(pc,"PCBDDCSetLocalAdjacencyGraph_C",(PC,PetscInt,const PetscInt[],const PetscInt[],PetscCopyMode),(pc,nvtxs,xadj,adjncy,copymode));CHKERRQ(ierr);
983575ad6abSStefano Zampini   /* free arrays if PCBDDC is not the PC type */
984575ad6abSStefano Zampini   ierr = PetscObjectQueryFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",&f);CHKERRQ(ierr);
985575ad6abSStefano Zampini   if (!f && copymode == PETSC_OWN_POINTER) {
986575ad6abSStefano Zampini     ierr = PetscFree(xadj);CHKERRQ(ierr);
987575ad6abSStefano Zampini     ierr = PetscFree(adjncy);CHKERRQ(ierr);
988da1bb401SStefano Zampini   }
98936e030ebSStefano Zampini   PetscFunctionReturn(0);
99036e030ebSStefano Zampini }
9919c0446d6SStefano Zampini /* -------------------------------------------------------------------------- */
9921e6b0712SBarry Smith 
9939c0446d6SStefano Zampini #undef __FUNCT__
99463602bcaSStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplittingLocal_BDDC"
99563602bcaSStefano Zampini static PetscErrorCode PCBDDCSetDofsSplittingLocal_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
99663602bcaSStefano Zampini {
99763602bcaSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
99863602bcaSStefano Zampini   PetscInt       i;
99956282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
100063602bcaSStefano Zampini   PetscErrorCode ierr;
100163602bcaSStefano Zampini 
100263602bcaSStefano Zampini   PetscFunctionBegin;
100356282151SStefano Zampini   if (pcbddc->n_ISForDofsLocal == n_is) {
100456282151SStefano Zampini     for (i=0;i<n_is;i++) {
100556282151SStefano Zampini       PetscBool isequalt;
100656282151SStefano Zampini       ierr = ISEqual(ISForDofs[i],pcbddc->ISForDofsLocal[i],&isequalt);CHKERRQ(ierr);
100756282151SStefano Zampini       if (!isequalt) break;
100856282151SStefano Zampini     }
100956282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
101056282151SStefano Zampini   }
101156282151SStefano Zampini   for (i=0;i<n_is;i++) {
101256282151SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
101356282151SStefano Zampini   }
101463602bcaSStefano Zampini   /* Destroy ISes if they were already set */
101563602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
101663602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
101763602bcaSStefano Zampini   }
101863602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
101963602bcaSStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
102063602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
102163602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
102263602bcaSStefano Zampini   }
102363602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
102463602bcaSStefano Zampini   pcbddc->n_ISForDofs = 0;
102563602bcaSStefano Zampini   /* allocate space then set */
1026d02579f5SStefano Zampini   if (n_is) {
1027d02579f5SStefano Zampini     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofsLocal);CHKERRQ(ierr);
1028d02579f5SStefano Zampini   }
102963602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
103063602bcaSStefano Zampini     pcbddc->ISForDofsLocal[i] = ISForDofs[i];
103163602bcaSStefano Zampini   }
103263602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = n_is;
103363602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
103456282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
103563602bcaSStefano Zampini   PetscFunctionReturn(0);
103663602bcaSStefano Zampini }
103763602bcaSStefano Zampini 
103863602bcaSStefano Zampini #undef __FUNCT__
103963602bcaSStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplittingLocal"
104063602bcaSStefano Zampini /*@
104163602bcaSStefano Zampini  PCBDDCSetDofsSplittingLocal - Set index sets defining fields of the local subdomain matrix
104263602bcaSStefano Zampini 
104363602bcaSStefano Zampini    Collective
104463602bcaSStefano Zampini 
104563602bcaSStefano Zampini    Input Parameters:
104663602bcaSStefano Zampini +  pc - the preconditioning context
10470f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
10480f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in local ordering
104963602bcaSStefano Zampini 
105063602bcaSStefano Zampini    Level: intermediate
105163602bcaSStefano Zampini 
10520f202f7eSStefano Zampini    Notes:
10530f202f7eSStefano Zampini      n_is should be the same among processes. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
105463602bcaSStefano Zampini 
105563602bcaSStefano Zampini .seealso: PCBDDC
105663602bcaSStefano Zampini @*/
105763602bcaSStefano Zampini PetscErrorCode PCBDDCSetDofsSplittingLocal(PC pc,PetscInt n_is, IS ISForDofs[])
105863602bcaSStefano Zampini {
105963602bcaSStefano Zampini   PetscInt       i;
106063602bcaSStefano Zampini   PetscErrorCode ierr;
106163602bcaSStefano Zampini 
106263602bcaSStefano Zampini   PetscFunctionBegin;
106363602bcaSStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
106463602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
106563602bcaSStefano Zampini   for (i=0;i<n_is;i++) {
106663602bcaSStefano Zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
106763602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
106863602bcaSStefano Zampini   }
1069e71e7a71SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplittingLocal_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
107063602bcaSStefano Zampini   PetscFunctionReturn(0);
107163602bcaSStefano Zampini }
107263602bcaSStefano Zampini /* -------------------------------------------------------------------------- */
107363602bcaSStefano Zampini 
107463602bcaSStefano Zampini #undef __FUNCT__
10759c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting_BDDC"
10769c0446d6SStefano Zampini static PetscErrorCode PCBDDCSetDofsSplitting_BDDC(PC pc,PetscInt n_is, IS ISForDofs[])
10779c0446d6SStefano Zampini {
10789c0446d6SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
10799c0446d6SStefano Zampini   PetscInt       i;
108056282151SStefano Zampini   PetscBool      isequal = PETSC_FALSE;
10819c0446d6SStefano Zampini   PetscErrorCode ierr;
10829c0446d6SStefano Zampini 
10839c0446d6SStefano Zampini   PetscFunctionBegin;
108456282151SStefano Zampini   if (pcbddc->n_ISForDofs == n_is) {
108556282151SStefano Zampini     for (i=0;i<n_is;i++) {
108656282151SStefano Zampini       PetscBool isequalt;
108756282151SStefano Zampini       ierr = ISEqual(ISForDofs[i],pcbddc->ISForDofs[i],&isequalt);CHKERRQ(ierr);
108856282151SStefano Zampini       if (!isequalt) break;
108956282151SStefano Zampini     }
109056282151SStefano Zampini     if (i == n_is) isequal = PETSC_TRUE;
109156282151SStefano Zampini   }
109256282151SStefano Zampini   for (i=0;i<n_is;i++) {
109356282151SStefano Zampini     ierr = PetscObjectReference((PetscObject)ISForDofs[i]);CHKERRQ(ierr);
109456282151SStefano Zampini   }
1095da1bb401SStefano Zampini   /* Destroy ISes if they were already set */
10969c0446d6SStefano Zampini   for (i=0;i<pcbddc->n_ISForDofs;i++) {
10979c0446d6SStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofs[i]);CHKERRQ(ierr);
10989c0446d6SStefano Zampini   }
1099d11ae9bbSstefano_zampini   ierr = PetscFree(pcbddc->ISForDofs);CHKERRQ(ierr);
110063602bcaSStefano Zampini   /* last user setting takes precendence -> destroy any other customization */
110163602bcaSStefano Zampini   for (i=0;i<pcbddc->n_ISForDofsLocal;i++) {
110263602bcaSStefano Zampini     ierr = ISDestroy(&pcbddc->ISForDofsLocal[i]);CHKERRQ(ierr);
110363602bcaSStefano Zampini   }
110463602bcaSStefano Zampini   ierr = PetscFree(pcbddc->ISForDofsLocal);CHKERRQ(ierr);
110563602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal = 0;
1106da1bb401SStefano Zampini   /* allocate space then set */
1107d02579f5SStefano Zampini   if (n_is) {
1108785e854fSJed Brown     ierr = PetscMalloc1(n_is,&pcbddc->ISForDofs);CHKERRQ(ierr);
1109d02579f5SStefano Zampini   }
11109c0446d6SStefano Zampini   for (i=0;i<n_is;i++) {
1111da1bb401SStefano Zampini     pcbddc->ISForDofs[i] = ISForDofs[i];
11129c0446d6SStefano Zampini   }
11139c0446d6SStefano Zampini   pcbddc->n_ISForDofs = n_is;
111463602bcaSStefano Zampini   if (n_is) pcbddc->user_provided_isfordofs = PETSC_TRUE;
111556282151SStefano Zampini   if (!isequal) pcbddc->recompute_topography = PETSC_TRUE;
11169c0446d6SStefano Zampini   PetscFunctionReturn(0);
11179c0446d6SStefano Zampini }
11181e6b0712SBarry Smith 
11199c0446d6SStefano Zampini #undef __FUNCT__
11209c0446d6SStefano Zampini #define __FUNCT__ "PCBDDCSetDofsSplitting"
11219c0446d6SStefano Zampini /*@
112263602bcaSStefano Zampini  PCBDDCSetDofsSplitting - Set index sets defining fields of the global matrix
11239c0446d6SStefano Zampini 
112463602bcaSStefano Zampini    Collective
11259c0446d6SStefano Zampini 
11269c0446d6SStefano Zampini    Input Parameters:
11279c0446d6SStefano Zampini +  pc - the preconditioning context
11280f202f7eSStefano Zampini .  n_is - number of index sets defining the fields
11290f202f7eSStefano Zampini -  ISForDofs - array of IS describing the fields in global ordering
11309c0446d6SStefano Zampini 
11319c0446d6SStefano Zampini    Level: intermediate
11329c0446d6SStefano Zampini 
11330f202f7eSStefano Zampini    Notes:
11340f202f7eSStefano Zampini      Any process can list any global node. Not all nodes need to be listed: unlisted nodes will belong to the complement field.
11359c0446d6SStefano Zampini 
11369c0446d6SStefano Zampini .seealso: PCBDDC
11379c0446d6SStefano Zampini @*/
11389c0446d6SStefano Zampini PetscErrorCode PCBDDCSetDofsSplitting(PC pc,PetscInt n_is, IS ISForDofs[])
11399c0446d6SStefano Zampini {
11402b510759SStefano Zampini   PetscInt       i;
11419c0446d6SStefano Zampini   PetscErrorCode ierr;
11429c0446d6SStefano Zampini 
11439c0446d6SStefano Zampini   PetscFunctionBegin;
11449c0446d6SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
114563602bcaSStefano Zampini   PetscValidLogicalCollectiveInt(pc,n_is,2);
11462b510759SStefano Zampini   for (i=0;i<n_is;i++) {
114763602bcaSStefano Zampini     PetscCheckSameComm(pc,1,ISForDofs[i],3);
114863602bcaSStefano Zampini     PetscValidHeaderSpecific(ISForDofs[i],IS_CLASSID,3);
11492b510759SStefano Zampini   }
11509c0446d6SStefano Zampini   ierr = PetscTryMethod(pc,"PCBDDCSetDofsSplitting_C",(PC,PetscInt,IS[]),(pc,n_is,ISForDofs));CHKERRQ(ierr);
11519c0446d6SStefano Zampini   PetscFunctionReturn(0);
11529c0446d6SStefano Zampini }
1153906d46d4SStefano Zampini 
1154da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
1155534831adSStefano Zampini #undef __FUNCT__
1156534831adSStefano Zampini #define __FUNCT__ "PCPreSolve_BDDC"
1157534831adSStefano Zampini /* -------------------------------------------------------------------------- */
1158534831adSStefano Zampini /*
1159534831adSStefano Zampini    PCPreSolve_BDDC - Changes the right hand side and (if necessary) the initial
1160534831adSStefano Zampini                      guess if a transformation of basis approach has been selected.
11619c0446d6SStefano Zampini 
1162534831adSStefano Zampini    Input Parameter:
1163534831adSStefano Zampini +  pc - the preconditioner contex
1164534831adSStefano Zampini 
1165534831adSStefano Zampini    Application Interface Routine: PCPreSolve()
1166534831adSStefano Zampini 
1167534831adSStefano Zampini    Notes:
1168534831adSStefano Zampini      The interface routine PCPreSolve() is not usually called directly by
1169534831adSStefano Zampini    the user, but instead is called by KSPSolve().
1170534831adSStefano Zampini */
1171534831adSStefano Zampini static PetscErrorCode PCPreSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1172534831adSStefano Zampini {
1173534831adSStefano Zampini   PetscErrorCode ierr;
1174534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1175534831adSStefano Zampini   PC_IS          *pcis = (PC_IS*)(pc->data);
11763972b0daSStefano Zampini   Vec            used_vec;
117727b6a85dSStefano Zampini   PetscBool      save_rhs = PETSC_TRUE, benign_correction_computed;
1178534831adSStefano Zampini 
1179534831adSStefano Zampini   PetscFunctionBegin;
118027b6a85dSStefano Zampini   /* if we are working with CG or CHEBYSHEV, one dirichlet solve can be avoided during Krylov iterations */
118185c4d303SStefano Zampini   if (ksp) {
1182*f94e96cbSStefano Zampini     PetscBool iscg, ischeby, isgroppcg, ispipecg, ispipecgrr;
118385c4d303SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPCG,&iscg);CHKERRQ(ierr);
118427b6a85dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPGROPPCG,&isgroppcg);CHKERRQ(ierr);
118527b6a85dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECG,&ispipecg);CHKERRQ(ierr);
1186*f94e96cbSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPPIPECGRR,&ispipecgrr);CHKERRQ(ierr);
118727b6a85dSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)ksp,KSPCHEBYSHEV,&ischeby);CHKERRQ(ierr);
1188*f94e96cbSStefano Zampini     if (pcbddc->switch_static || (!iscg && !ischeby && !isgroppcg && !ispipecg && !ispipecgrr)) {
118985c4d303SStefano Zampini       ierr = PCBDDCSetUseExactDirichlet(pc,PETSC_FALSE);CHKERRQ(ierr);
119085c4d303SStefano Zampini     }
119185c4d303SStefano Zampini   }
119285c4d303SStefano Zampini   /* Creates parallel work vectors used in presolve */
119362a6ff1dSStefano Zampini   if (!pcbddc->original_rhs) {
119462a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->original_rhs);CHKERRQ(ierr);
119562a6ff1dSStefano Zampini   }
119662a6ff1dSStefano Zampini   if (!pcbddc->temp_solution) {
119762a6ff1dSStefano Zampini     ierr = VecDuplicate(pcis->vec1_global,&pcbddc->temp_solution);CHKERRQ(ierr);
119862a6ff1dSStefano Zampini   }
11998d00608fSStefano Zampini 
120027b6a85dSStefano Zampini   pcbddc->temp_solution_used = PETSC_FALSE;
12013972b0daSStefano Zampini   if (x) {
12023972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);
12033972b0daSStefano Zampini     used_vec = x;
12048d00608fSStefano Zampini   } else { /* it can only happen when calling PCBDDCMatFETIDPGetRHS */
12053972b0daSStefano Zampini     ierr = PetscObjectReference((PetscObject)pcbddc->temp_solution);CHKERRQ(ierr);
12063972b0daSStefano Zampini     used_vec = pcbddc->temp_solution;
12073972b0daSStefano Zampini     ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
120827b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
12093972b0daSStefano Zampini   }
12108efcfb23SStefano Zampini 
12118efcfb23SStefano Zampini   /* hack into ksp data structure since PCPreSolve comes earlier than setting to zero the guess in src/ksp/ksp/interface/itfunc.c */
12123972b0daSStefano Zampini   if (ksp) {
1213a0cb1b98SStefano Zampini     /* store the flag for the initial guess since it will be restored back during PCPostSolve_BDDC */
12148efcfb23SStefano Zampini     ierr = KSPGetInitialGuessNonzero(ksp,&pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
12158efcfb23SStefano Zampini     if (!pcbddc->ksp_guess_nonzero) {
12163972b0daSStefano Zampini       ierr = VecSet(used_vec,0.0);CHKERRQ(ierr);
12173972b0daSStefano Zampini     }
12183972b0daSStefano Zampini   }
12193308cffdSStefano Zampini 
12208d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
12213972b0daSStefano Zampini   /* Take into account zeroed rows -> change rhs and store solution removed */
122270c64980SStefano Zampini   if (rhs && pcbddc->eliminate_dirdofs) {
12233975b054SStefano Zampini     IS dirIS = NULL;
12243975b054SStefano Zampini 
1225a07ea27aSStefano Zampini     /* DirichletBoundariesLocal may not be consistent among neighbours; gets a dirichlet dofs IS from graph (may be cached) */
12263975b054SStefano Zampini     ierr = PCBDDCGraphGetDirichletDofs(pcbddc->mat_graph,&dirIS);CHKERRQ(ierr);
12273975b054SStefano Zampini     if (dirIS) {
1228906d46d4SStefano Zampini       Mat_IS            *matis = (Mat_IS*)pc->pmat->data;
1229785d1243SStefano Zampini       PetscInt          dirsize,i,*is_indices;
12302b095fd8SStefano Zampini       PetscScalar       *array_x;
12312b095fd8SStefano Zampini       const PetscScalar *array_diagonal;
1232785d1243SStefano Zampini 
12333972b0daSStefano Zampini       ierr = MatGetDiagonal(pc->pmat,pcis->vec1_global);CHKERRQ(ierr);
12343972b0daSStefano Zampini       ierr = VecPointwiseDivide(pcis->vec1_global,rhs,pcis->vec1_global);CHKERRQ(ierr);
1235e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1236e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_global,pcis->vec2_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1237e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1238e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,used_vec,pcis->vec1_N,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
123982ba6b80SStefano Zampini       ierr = ISGetLocalSize(dirIS,&dirsize);CHKERRQ(ierr);
12403972b0daSStefano Zampini       ierr = VecGetArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
12412b095fd8SStefano Zampini       ierr = VecGetArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
12423972b0daSStefano Zampini       ierr = ISGetIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
12432fa5cd67SKarl Rupp       for (i=0; i<dirsize; i++) array_x[is_indices[i]] = array_diagonal[is_indices[i]];
12443972b0daSStefano Zampini       ierr = ISRestoreIndices(dirIS,(const PetscInt**)&is_indices);CHKERRQ(ierr);
12452b095fd8SStefano Zampini       ierr = VecRestoreArrayRead(pcis->vec2_N,&array_diagonal);CHKERRQ(ierr);
12463972b0daSStefano Zampini       ierr = VecRestoreArray(pcis->vec1_N,&array_x);CHKERRQ(ierr);
1247e176bc59SStefano Zampini       ierr = VecScatterBegin(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1248e176bc59SStefano Zampini       ierr = VecScatterEnd(matis->rctx,pcis->vec1_N,used_vec,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
12498d00608fSStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
12501b968477SStefano Zampini       ierr = ISDestroy(&dirIS);CHKERRQ(ierr);
12518efcfb23SStefano Zampini     }
1252a07ea27aSStefano Zampini   }
1253b76ba322SStefano Zampini 
12548efcfb23SStefano Zampini   /* remove the computed solution or the initial guess from the rhs */
12558d00608fSStefano Zampini   if (pcbddc->rhs_change || (ksp && pcbddc->ksp_guess_nonzero) ) {
125627b6a85dSStefano Zampini     /* save the original rhs */
125727b6a85dSStefano Zampini     if (save_rhs) {
125827b6a85dSStefano Zampini       ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
125927b6a85dSStefano Zampini       save_rhs = PETSC_FALSE;
12608d00608fSStefano Zampini     }
12618d00608fSStefano Zampini     pcbddc->rhs_change = PETSC_TRUE;
12623972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
126327b6a85dSStefano Zampini     ierr = MatMultAdd(pc->mat,used_vec,pcbddc->original_rhs,rhs);CHKERRQ(ierr);
12643972b0daSStefano Zampini     ierr = VecScale(used_vec,-1.0);CHKERRQ(ierr);
12658efcfb23SStefano Zampini     ierr = VecCopy(used_vec,pcbddc->temp_solution);CHKERRQ(ierr);
126627b6a85dSStefano Zampini     pcbddc->temp_solution_used = PETSC_TRUE;
12677acc28cbSStefano Zampini     if (ksp) {
12687acc28cbSStefano Zampini       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_FALSE);CHKERRQ(ierr);
12697acc28cbSStefano Zampini     }
12703308cffdSStefano Zampini   }
12718efcfb23SStefano Zampini   ierr = VecDestroy(&used_vec);CHKERRQ(ierr);
1272b76ba322SStefano Zampini 
127327b6a85dSStefano Zampini   /* compute initial vector in benign space if needed (TODO: FETI-DP is untested)
127427b6a85dSStefano Zampini      and remove non-benign solution from the rhs */
127527b6a85dSStefano Zampini   benign_correction_computed = PETSC_FALSE;
127627b6a85dSStefano Zampini   if (rhs && pcbddc->benign_compute_correction && pcbddc->benign_have_null) {
12770369aaf7SStefano Zampini     /* compute u^*_h as in Xuemin Tu's thesis (see Section 4.8.1) */
12780369aaf7SStefano Zampini     if (!pcbddc->benign_vec) {
12790369aaf7SStefano Zampini       ierr = VecDuplicate(rhs,&pcbddc->benign_vec);CHKERRQ(ierr);
12800369aaf7SStefano Zampini     }
12814fee134fSStefano Zampini     pcbddc->benign_apply_coarse_only = PETSC_TRUE;
128227b6a85dSStefano Zampini     if (!pcbddc->benign_skip_correction) {
12831dd7afcfSStefano Zampini       ierr = PCApply_BDDC(pc,rhs,pcbddc->benign_vec);CHKERRQ(ierr);
128427b6a85dSStefano Zampini       /* store the original rhs if not done earlier */
128527b6a85dSStefano Zampini       if (save_rhs) {
128627b6a85dSStefano Zampini         ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
128727b6a85dSStefano Zampini         save_rhs = PETSC_FALSE;
128892e3dcfbSStefano Zampini       }
128927b6a85dSStefano Zampini       benign_correction_computed = PETSC_TRUE;
129027b6a85dSStefano Zampini       if (pcbddc->temp_solution_used) {
129127b6a85dSStefano Zampini         ierr = VecAXPY(pcbddc->temp_solution,1.0,pcbddc->benign_vec);CHKERRQ(ierr);
12920369aaf7SStefano Zampini       }
12930369aaf7SStefano Zampini       ierr = VecScale(pcbddc->benign_vec,-1.0);CHKERRQ(ierr);
129427b6a85dSStefano Zampini       if (pcbddc->rhs_change) {
12950369aaf7SStefano Zampini         ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,rhs,rhs);CHKERRQ(ierr);
129627b6a85dSStefano Zampini       } else {
129727b6a85dSStefano Zampini         ierr = MatMultAdd(pc->mat,pcbddc->benign_vec,pcbddc->original_rhs,rhs);CHKERRQ(ierr);
129827b6a85dSStefano Zampini       }
12990369aaf7SStefano Zampini       pcbddc->rhs_change = PETSC_TRUE;
130027b6a85dSStefano Zampini     }
130127b6a85dSStefano Zampini     pcbddc->benign_apply_coarse_only = PETSC_FALSE;
13020369aaf7SStefano Zampini   }
13030369aaf7SStefano Zampini 
13040369aaf7SStefano Zampini   /* set initial guess if using PCG */
13050369aaf7SStefano Zampini   if (x && pcbddc->use_exact_dirichlet_trick) {
13060369aaf7SStefano Zampini     ierr = VecSet(x,0.0);CHKERRQ(ierr);
13071dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
130827b6a85dSStefano Zampini       if (benign_correction_computed) { /* we have already saved the changed rhs */
13091dd7afcfSStefano Zampini         ierr = VecLockPop(pcis->vec1_global);CHKERRQ(ierr);
13101dd7afcfSStefano Zampini       } else {
13111dd7afcfSStefano Zampini         ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,rhs,pcis->vec1_global);CHKERRQ(ierr);
13121dd7afcfSStefano Zampini       }
13131dd7afcfSStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13141dd7afcfSStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec1_global,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13151dd7afcfSStefano Zampini     } else {
13160369aaf7SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13170369aaf7SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,rhs,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13181dd7afcfSStefano Zampini     }
13190369aaf7SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
13201dd7afcfSStefano Zampini     if (pcbddc->ChangeOfBasisMatrix && pcbddc->change_interior) {
13211dd7afcfSStefano Zampini       ierr = VecSet(pcis->vec1_global,0.);CHKERRQ(ierr);
13221dd7afcfSStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13231dd7afcfSStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,pcis->vec1_global,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13241dd7afcfSStefano Zampini       ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcis->vec1_global,x);CHKERRQ(ierr);
13251dd7afcfSStefano Zampini     } else {
13260369aaf7SStefano Zampini       ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13270369aaf7SStefano Zampini       ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,x,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
13281dd7afcfSStefano Zampini     }
13290369aaf7SStefano Zampini     if (ksp) {
13300369aaf7SStefano Zampini       ierr = KSPSetInitialGuessNonzero(ksp,PETSC_TRUE);CHKERRQ(ierr);
13310369aaf7SStefano Zampini     }
13320369aaf7SStefano Zampini   }
1333534831adSStefano Zampini   PetscFunctionReturn(0);
1334534831adSStefano Zampini }
1335906d46d4SStefano Zampini 
1336534831adSStefano Zampini /* -------------------------------------------------------------------------- */
1337534831adSStefano Zampini #undef __FUNCT__
1338534831adSStefano Zampini #define __FUNCT__ "PCPostSolve_BDDC"
1339534831adSStefano Zampini /* -------------------------------------------------------------------------- */
1340534831adSStefano Zampini /*
1341534831adSStefano Zampini    PCPostSolve_BDDC - Changes the computed solution if a transformation of basis
1342534831adSStefano Zampini                      approach has been selected. Also, restores rhs to its original state.
1343534831adSStefano Zampini 
1344534831adSStefano Zampini    Input Parameter:
1345534831adSStefano Zampini +  pc - the preconditioner contex
1346534831adSStefano Zampini 
1347534831adSStefano Zampini    Application Interface Routine: PCPostSolve()
1348534831adSStefano Zampini 
1349534831adSStefano Zampini    Notes:
1350534831adSStefano Zampini      The interface routine PCPostSolve() is not usually called directly by
1351534831adSStefano Zampini      the user, but instead is called by KSPSolve().
1352534831adSStefano Zampini */
1353534831adSStefano Zampini static PetscErrorCode PCPostSolve_BDDC(PC pc, KSP ksp, Vec rhs, Vec x)
1354534831adSStefano Zampini {
1355534831adSStefano Zampini   PetscErrorCode ierr;
1356534831adSStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1357534831adSStefano Zampini 
1358534831adSStefano Zampini   PetscFunctionBegin;
13593972b0daSStefano Zampini   /* add solution removed in presolve */
13606bcfc461SStefano Zampini   if (x && pcbddc->rhs_change) {
136127b6a85dSStefano Zampini     if (pcbddc->temp_solution_used) {
13623425bc38SStefano Zampini       ierr = VecAXPY(x,1.0,pcbddc->temp_solution);CHKERRQ(ierr);
136327b6a85dSStefano Zampini     } else if (pcbddc->benign_compute_correction) {
136427b6a85dSStefano Zampini       ierr = VecAXPY(x,-1.0,pcbddc->benign_vec);CHKERRQ(ierr);
13653425bc38SStefano Zampini     }
136627b6a85dSStefano Zampini   }
136727b6a85dSStefano Zampini   pcbddc->temp_solution_used = PETSC_FALSE;
136827b6a85dSStefano Zampini 
1369fb223d50SStefano Zampini   /* restore rhs to its original state */
13708d00608fSStefano Zampini   if (rhs && pcbddc->rhs_change) {
137127b6a85dSStefano Zampini     ierr = VecSwap(rhs,pcbddc->original_rhs);CHKERRQ(ierr);
1372fb223d50SStefano Zampini   }
13738d00608fSStefano Zampini   pcbddc->rhs_change = PETSC_FALSE;
13748efcfb23SStefano Zampini   /* restore ksp guess state */
13758efcfb23SStefano Zampini   if (ksp) {
13768efcfb23SStefano Zampini     ierr = KSPSetInitialGuessNonzero(ksp,pcbddc->ksp_guess_nonzero);CHKERRQ(ierr);
13778efcfb23SStefano Zampini   }
1378534831adSStefano Zampini   PetscFunctionReturn(0);
1379534831adSStefano Zampini }
1380534831adSStefano Zampini /* -------------------------------------------------------------------------- */
138153cdbc3dSStefano Zampini #undef __FUNCT__
138253cdbc3dSStefano Zampini #define __FUNCT__ "PCSetUp_BDDC"
13830c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
13840c7d97c5SJed Brown /*
13850c7d97c5SJed Brown    PCSetUp_BDDC - Prepares for the use of the BDDC preconditioner
13860c7d97c5SJed Brown                   by setting data structures and options.
13870c7d97c5SJed Brown 
13880c7d97c5SJed Brown    Input Parameter:
138953cdbc3dSStefano Zampini +  pc - the preconditioner context
13900c7d97c5SJed Brown 
13910c7d97c5SJed Brown    Application Interface Routine: PCSetUp()
13920c7d97c5SJed Brown 
13930c7d97c5SJed Brown    Notes:
13940c7d97c5SJed Brown      The interface routine PCSetUp() is not usually called directly by
13950c7d97c5SJed Brown      the user, but instead is called by PCApply() if necessary.
13960c7d97c5SJed Brown */
139753cdbc3dSStefano Zampini PetscErrorCode PCSetUp_BDDC(PC pc)
13980c7d97c5SJed Brown {
13990c7d97c5SJed Brown   PetscErrorCode ierr;
14000c7d97c5SJed Brown   PC_BDDC*       pcbddc = (PC_BDDC*)pc->data;
14015e8657edSStefano Zampini   Mat_IS*        matis;
140208122e43SStefano Zampini   MatNullSpace   nearnullspace;
1403c9ed8603SStefano Zampini   IS             zerodiag = NULL;
140491e8d312SStefano Zampini   PetscInt       nrows,ncols;
140508122e43SStefano Zampini   PetscBool      computetopography,computesolvers,computesubschurs;
14068de1fae6SStefano Zampini   PetscBool      computeconstraintsmatrix;
14075e8657edSStefano Zampini   PetscBool      new_nearnullspace_provided,ismatis;
14080c7d97c5SJed Brown 
14090c7d97c5SJed Brown   PetscFunctionBegin;
14105e8657edSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)pc->pmat,MATIS,&ismatis);CHKERRQ(ierr);
14116c4ed002SBarry Smith   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_ARG_WRONG,"PCBDDC preconditioner requires matrix of type MATIS");
141291e8d312SStefano Zampini   ierr = MatGetSize(pc->pmat,&nrows,&ncols);CHKERRQ(ierr);
14136c4ed002SBarry Smith   if (nrows != ncols) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"PCBDDC preconditioner requires a square preconditioning matrix");
14145e8657edSStefano Zampini   matis = (Mat_IS*)pc->pmat->data;
1415f4ddd8eeSStefano Zampini   /* the following lines of code should be replaced by a better logic between PCIS, PCNN, PCBDDC and other future nonoverlapping preconditioners */
14163b03a366Sstefano_zampini   /* For BDDC we need to define a local "Neumann" problem different to that defined in PCISSetup
1417fcd409f5SStefano Zampini      Also, BDDC directly build the Dirichlet problem */
1418f4ddd8eeSStefano Zampini   /* split work */
1419674ae819SStefano Zampini   if (pc->setupcalled) {
1420d1e9a80fSBarry Smith     if (pc->flag == SAME_NONZERO_PATTERN) {
1421674ae819SStefano Zampini       computetopography = PETSC_FALSE;
1422674ae819SStefano Zampini       computesolvers = PETSC_TRUE;
1423674ae819SStefano Zampini     } else { /* DIFFERENT_NONZERO_PATTERN */
1424674ae819SStefano Zampini       computetopography = PETSC_TRUE;
1425674ae819SStefano Zampini       computesolvers = PETSC_TRUE;
1426674ae819SStefano Zampini     }
1427674ae819SStefano Zampini   } else {
1428674ae819SStefano Zampini     computetopography = PETSC_TRUE;
1429674ae819SStefano Zampini     computesolvers = PETSC_TRUE;
1430674ae819SStefano Zampini   }
1431fb180af4SStefano Zampini   if (pcbddc->recompute_topography) {
1432fb180af4SStefano Zampini     computetopography = PETSC_TRUE;
1433fb180af4SStefano Zampini   }
143456282151SStefano Zampini   pcbddc->recompute_topography = computetopography;
14358de1fae6SStefano Zampini   computeconstraintsmatrix = PETSC_FALSE;
1436b087196eSStefano Zampini 
1437b087196eSStefano Zampini   /* check parameters' compatibility */
1438b7ab4a40SStefano Zampini   if (!pcbddc->use_deluxe_scaling) pcbddc->deluxe_zerorows = PETSC_FALSE;
14399d54b7f4SStefano Zampini   pcbddc->adaptive_selection = (PetscBool)(pcbddc->adaptive_threshold > 0.0);
1440bf3a8328SStefano Zampini   pcbddc->adaptive_userdefined = (PetscBool)(pcbddc->adaptive_selection && pcbddc->adaptive_userdefined);
1441862806e4SStefano Zampini   if (pcbddc->adaptive_selection) pcbddc->use_faces = PETSC_TRUE;
1442862806e4SStefano Zampini 
14435a95e1ceSStefano Zampini   computesubschurs = (PetscBool)(pcbddc->adaptive_selection || pcbddc->use_deluxe_scaling);
144416909a7fSStefano Zampini   if (pcbddc->switch_static) {
144516909a7fSStefano Zampini     PetscBool ismatis;
144616909a7fSStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)pc->mat,MATIS,&ismatis);CHKERRQ(ierr);
144716909a7fSStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)pc),PETSC_ERR_SUP,"When the static switch is one, the iteration matrix should be of type MATIS");
144816909a7fSStefano Zampini   }
144916909a7fSStefano Zampini 
1450f4ddd8eeSStefano Zampini   /* Get stdout for dbg */
145170cf5478SStefano Zampini   if (pcbddc->dbg_flag) {
145270cf5478SStefano Zampini     if (!pcbddc->dbg_viewer) {
145358a03d70SStefano Zampini       pcbddc->dbg_viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pc));
14541575c14dSBarry Smith       ierr = PetscViewerASCIIPushSynchronized(pcbddc->dbg_viewer);CHKERRQ(ierr);
1455f4ddd8eeSStefano Zampini     }
145658a03d70SStefano Zampini     ierr = PetscViewerASCIIAddTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
1457f4ddd8eeSStefano Zampini   }
1458f4ddd8eeSStefano Zampini 
14595e8657edSStefano Zampini   if (pcbddc->user_ChangeOfBasisMatrix) {
14605e8657edSStefano Zampini     /* use_change_of_basis flag is used to automatically compute a change of basis from constraints */
14615e8657edSStefano Zampini     pcbddc->use_change_of_basis = PETSC_FALSE;
14625e8657edSStefano Zampini     ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->user_ChangeOfBasisMatrix);CHKERRQ(ierr);
14635e8657edSStefano Zampini   } else {
1464b96c3477SStefano Zampini     ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
14655e8657edSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
14665e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
1467d16cbb6bSStefano Zampini   }
1468d16cbb6bSStefano Zampini 
14694f1b2e48SStefano Zampini   /* detect local disconnected subdomains if requested and not done before */
14704f1b2e48SStefano Zampini   if (pcbddc->detect_disconnected && !pcbddc->n_local_subs) {
14714f1b2e48SStefano Zampini     ierr = MatDetectDisconnectedComponents(pcbddc->local_mat,PETSC_FALSE,&pcbddc->n_local_subs,&pcbddc->local_subs);CHKERRQ(ierr);
14724f1b2e48SStefano Zampini   }
14734f1b2e48SStefano Zampini 
14744f1b2e48SStefano Zampini   /*
14751dd7afcfSStefano Zampini      Compute change of basis on local pressures (aka zerodiag dofs)
14764f1b2e48SStefano Zampini      This should come earlier then PCISSetUp for extracting the correct subdomain matrices
14774f1b2e48SStefano Zampini   */
14781dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_TRUE);CHKERRQ(ierr);
1479d16cbb6bSStefano Zampini   if (pcbddc->benign_saddle_point) {
14809f47a83aSStefano Zampini     PC_IS* pcis = (PC_IS*)pc->data;
14819f47a83aSStefano Zampini 
148205b28244SStefano Zampini     if (pcbddc->user_ChangeOfBasisMatrix || pcbddc->use_change_of_basis || !computesubschurs) pcbddc->benign_change_explicit = PETSC_TRUE;
1483339f8db1SStefano Zampini     /* detect local saddle point and change the basis in pcbddc->local_mat */
1484339f8db1SStefano Zampini     ierr = PCBDDCBenignDetectSaddlePoint(pc,&zerodiag);CHKERRQ(ierr);
1485a3df083aSStefano Zampini     /* pop B0 mat from local mat */
1486c263805aSStefano Zampini     ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
14871dd7afcfSStefano Zampini     /* give pcis a hint to not reuse submatrices during PCISCreate */
14881dd7afcfSStefano Zampini     if (pc->flag == SAME_NONZERO_PATTERN && pcis->reusesubmatrices == PETSC_TRUE) {
14891dd7afcfSStefano Zampini       if (pcbddc->benign_n && (pcbddc->benign_change_explicit || pcbddc->dbg_flag)) {
14901dd7afcfSStefano Zampini         pcis->reusesubmatrices = PETSC_FALSE;
14911dd7afcfSStefano Zampini       } else {
1492a3df083aSStefano Zampini         pcis->reusesubmatrices = PETSC_TRUE;
14931dd7afcfSStefano Zampini       }
1494a3df083aSStefano Zampini     } else {
14959f47a83aSStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
1496674ae819SStefano Zampini     }
1497a3df083aSStefano Zampini   }
149827b6a85dSStefano Zampini 
1499f1a72664SStefano Zampini   /* propagate relevant information */
15004f1b2e48SStefano Zampini #if !defined(PETSC_USE_COMPLEX) /* workaround for reals */
15013301b35fSStefano Zampini   if (matis->A->symmetric_set) {
15023301b35fSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_HERMITIAN,matis->A->symmetric);CHKERRQ(ierr);
15033301b35fSStefano Zampini   }
1504e496cd5dSStefano Zampini #endif
150506a4e24aSStefano Zampini   if (matis->A->symmetric_set) {
150606a4e24aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SYMMETRIC,matis->A->symmetric);CHKERRQ(ierr);
150706a4e24aSStefano Zampini   }
150806a4e24aSStefano Zampini   if (matis->A->spd_set) {
150906a4e24aSStefano Zampini     ierr = MatSetOption(pcbddc->local_mat,MAT_SPD,matis->A->spd);CHKERRQ(ierr);
151006a4e24aSStefano Zampini   }
1511e496cd5dSStefano Zampini 
15125e8657edSStefano Zampini   /* Set up all the "iterative substructuring" common block without computing solvers */
15135e8657edSStefano Zampini   {
15145e8657edSStefano Zampini     Mat temp_mat;
15155e8657edSStefano Zampini 
15165e8657edSStefano Zampini     temp_mat = matis->A;
15175e8657edSStefano Zampini     matis->A = pcbddc->local_mat;
15185e8657edSStefano Zampini     ierr = PCISSetUp(pc,PETSC_FALSE);CHKERRQ(ierr);
15195e8657edSStefano Zampini     pcbddc->local_mat = matis->A;
15205e8657edSStefano Zampini     matis->A = temp_mat;
15215e8657edSStefano Zampini   }
1522684f6988SStefano Zampini 
152381d14e9dSStefano Zampini   /* Analyze interface */
1524674ae819SStefano Zampini   if (computetopography) {
1525674ae819SStefano Zampini     ierr = PCBDDCAnalyzeInterface(pc);CHKERRQ(ierr);
15268de1fae6SStefano Zampini     computeconstraintsmatrix = PETSC_TRUE;
1527674ae819SStefano Zampini   }
1528fb8d54d4SStefano Zampini 
15295408967cSStefano Zampini   /* check existence of a divergence free extension, i.e.
15305408967cSStefano Zampini      b(v_I,p_0) = 0 for all v_I (raise error if not).
15315408967cSStefano Zampini      Also, check that PCBDDCBenignGetOrSetP0 works */
15325408967cSStefano Zampini #if defined(PETSC_USE_DEBUG)
153309f581a4SStefano Zampini   if (pcbddc->benign_saddle_point) {
15345408967cSStefano Zampini     ierr = PCBDDCBenignCheck(pc,zerodiag);CHKERRQ(ierr);
153509f581a4SStefano Zampini   }
15365408967cSStefano Zampini #endif
15374f1b2e48SStefano Zampini   ierr = ISDestroy(&zerodiag);CHKERRQ(ierr);
153806f24817SStefano Zampini 
1539b96c3477SStefano Zampini   /* Setup local dirichlet solver ksp_D and sub_schurs solvers */
1540684f6988SStefano Zampini   if (computesolvers) {
1541d5574798SStefano Zampini     PCBDDCSubSchurs sub_schurs=pcbddc->sub_schurs;
1542d5574798SStefano Zampini 
1543d5574798SStefano Zampini     if (computesubschurs && computetopography) {
154408122e43SStefano Zampini       ierr = PCBDDCInitSubSchurs(pc);CHKERRQ(ierr);
1545b1b3d7a2SStefano Zampini     }
15469d54b7f4SStefano Zampini     /* SetUp Scaling operator (scaling matrices could be needed in SubSchursSetUp)*/
15479d54b7f4SStefano Zampini     if (!pcbddc->use_deluxe_scaling) {
15489d54b7f4SStefano Zampini       ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
15499d54b7f4SStefano Zampini     }
1550df4d28bfSStefano Zampini     if (sub_schurs->schur_explicit) {
15512070dbb6SStefano Zampini       if (computesubschurs) {
155208122e43SStefano Zampini         ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
15532070dbb6SStefano Zampini       }
1554d5574798SStefano Zampini       ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
1555d5574798SStefano Zampini     } else {
1556d5574798SStefano Zampini       ierr = PCBDDCSetUpLocalSolvers(pc,PETSC_TRUE,PETSC_FALSE);CHKERRQ(ierr);
15572070dbb6SStefano Zampini       if (computesubschurs) {
1558d5574798SStefano Zampini         ierr = PCBDDCSetUpSubSchurs(pc);CHKERRQ(ierr);
1559d5574798SStefano Zampini       }
15602070dbb6SStefano Zampini     }
156108122e43SStefano Zampini     if (pcbddc->adaptive_selection) {
156208122e43SStefano Zampini       ierr = PCBDDCAdaptiveSelection(pc);CHKERRQ(ierr);
15638de1fae6SStefano Zampini       computeconstraintsmatrix = PETSC_TRUE;
1564b7eb3628SStefano Zampini     }
1565b1b3d7a2SStefano Zampini   }
1566684f6988SStefano Zampini 
1567f4ddd8eeSStefano Zampini   /* infer if NullSpace object attached to Mat via MatSetNearNullSpace has changed */
1568fb8d54d4SStefano Zampini   new_nearnullspace_provided = PETSC_FALSE;
1569f4ddd8eeSStefano Zampini   ierr = MatGetNearNullSpace(pc->pmat,&nearnullspace);CHKERRQ(ierr);
1570f4ddd8eeSStefano Zampini   if (pcbddc->onearnullspace) { /* already used nearnullspace */
1571f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* near null space attached to mat has been destroyed */
1572f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1573f4ddd8eeSStefano Zampini     } else {
1574f4ddd8eeSStefano Zampini       /* determine if the two nullspaces are different (should be lightweight) */
1575f4ddd8eeSStefano Zampini       if (nearnullspace != pcbddc->onearnullspace) {
1576f4ddd8eeSStefano Zampini         new_nearnullspace_provided = PETSC_TRUE;
1577165b64e2SStefano Zampini       } else { /* maybe the user has changed the content of the nearnullspace so check vectors ObjectStateId */
1578f4ddd8eeSStefano Zampini         PetscInt         i;
1579165b64e2SStefano Zampini         const Vec        *nearnullvecs;
1580165b64e2SStefano Zampini         PetscObjectState state;
1581165b64e2SStefano Zampini         PetscInt         nnsp_size;
1582165b64e2SStefano Zampini         ierr = MatNullSpaceGetVecs(nearnullspace,NULL,&nnsp_size,&nearnullvecs);CHKERRQ(ierr);
1583f4ddd8eeSStefano Zampini         for (i=0;i<nnsp_size;i++) {
1584f4ddd8eeSStefano Zampini           ierr = PetscObjectStateGet((PetscObject)nearnullvecs[i],&state);CHKERRQ(ierr);
1585165b64e2SStefano Zampini           if (pcbddc->onearnullvecs_state[i] != state) {
1586f4ddd8eeSStefano Zampini             new_nearnullspace_provided = PETSC_TRUE;
1587f4ddd8eeSStefano Zampini             break;
1588f4ddd8eeSStefano Zampini           }
1589f4ddd8eeSStefano Zampini         }
1590f4ddd8eeSStefano Zampini       }
1591f4ddd8eeSStefano Zampini     }
1592f4ddd8eeSStefano Zampini   } else {
1593f4ddd8eeSStefano Zampini     if (!nearnullspace) { /* both nearnullspaces are null */
1594f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_FALSE;
1595f4ddd8eeSStefano Zampini     } else { /* nearnullspace attached later */
1596f4ddd8eeSStefano Zampini       new_nearnullspace_provided = PETSC_TRUE;
1597f4ddd8eeSStefano Zampini     }
1598f4ddd8eeSStefano Zampini   }
1599f4ddd8eeSStefano Zampini 
1600f4ddd8eeSStefano Zampini   /* Setup constraints and related work vectors */
1601727cdba6SStefano Zampini   /* reset primal space flags */
1602f4ddd8eeSStefano Zampini   pcbddc->new_primal_space = PETSC_FALSE;
1603727cdba6SStefano Zampini   pcbddc->new_primal_space_local = PETSC_FALSE;
16048de1fae6SStefano Zampini   if (computeconstraintsmatrix || new_nearnullspace_provided) {
1605727cdba6SStefano Zampini     /* It also sets the primal space flags */
1606674ae819SStefano Zampini     ierr = PCBDDCConstraintsSetUp(pc);CHKERRQ(ierr);
1607e7b262bdSStefano Zampini     /* Allocate needed local vectors (which depends on quantities defined during ConstraintsSetUp) */
1608f4ddd8eeSStefano Zampini     ierr = PCBDDCSetUpLocalWorkVectors(pc);CHKERRQ(ierr);
16093975b054SStefano Zampini   }
16105e8657edSStefano Zampini 
16113975b054SStefano Zampini   if (computesolvers || pcbddc->new_primal_space) {
16125e8657edSStefano Zampini     if (pcbddc->use_change_of_basis) {
16135e8657edSStefano Zampini       PC_IS *pcis = (PC_IS*)(pc->data);
16145e8657edSStefano Zampini 
16155e8657edSStefano Zampini       ierr = PCBDDCComputeLocalMatrix(pc,pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr);
16164f1b2e48SStefano Zampini       if (pcbddc->benign_change) {
16171dd7afcfSStefano Zampini         ierr = MatDestroy(&pcbddc->benign_B0);CHKERRQ(ierr);
1618c263805aSStefano Zampini         /* pop B0 from pcbddc->local_mat */
1619c263805aSStefano Zampini         ierr = PCBDDCBenignPopOrPushB0(pc,PETSC_TRUE);CHKERRQ(ierr);
1620c263805aSStefano Zampini       }
16215e8657edSStefano Zampini       /* get submatrices */
16225e8657edSStefano Zampini       ierr = MatDestroy(&pcis->A_IB);CHKERRQ(ierr);
16235e8657edSStefano Zampini       ierr = MatDestroy(&pcis->A_BI);CHKERRQ(ierr);
16245e8657edSStefano Zampini       ierr = MatDestroy(&pcis->A_BB);CHKERRQ(ierr);
16255e8657edSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_BB);CHKERRQ(ierr);
16265e8657edSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_I_local,pcis->is_B_local,MAT_INITIAL_MATRIX,&pcis->A_IB);CHKERRQ(ierr);
16275e8657edSStefano Zampini       ierr = MatGetSubMatrix(pcbddc->local_mat,pcis->is_B_local,pcis->is_I_local,MAT_INITIAL_MATRIX,&pcis->A_BI);CHKERRQ(ierr);
16283975b054SStefano Zampini       /* set flag in pcis to not reuse submatrices during PCISCreate */
16293975b054SStefano Zampini       pcis->reusesubmatrices = PETSC_FALSE;
16309c6a02ceSStefano Zampini     } else if (!pcbddc->user_ChangeOfBasisMatrix && !pcbddc->benign_change) {
1631b96c3477SStefano Zampini       ierr = MatDestroy(&pcbddc->local_mat);CHKERRQ(ierr);
16325e8657edSStefano Zampini       ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
16335e8657edSStefano Zampini       pcbddc->local_mat = matis->A;
16345e8657edSStefano Zampini     }
1635b96c3477SStefano Zampini     /* SetUp coarse and local Neumann solvers */
163699cc7994SStefano Zampini     ierr = PCBDDCSetUpSolvers(pc);CHKERRQ(ierr);
1637b96c3477SStefano Zampini     /* SetUp Scaling operator */
16389d54b7f4SStefano Zampini     if (pcbddc->use_deluxe_scaling) {
1639674ae819SStefano Zampini       ierr = PCBDDCScalingSetUp(pc);CHKERRQ(ierr);
16400c7d97c5SJed Brown     }
16419d54b7f4SStefano Zampini   }
16421dd7afcfSStefano Zampini   /* mark topography as done */
164356282151SStefano Zampini   pcbddc->recompute_topography = PETSC_FALSE;
16440369aaf7SStefano Zampini 
16451dd7afcfSStefano Zampini   /* wrap pcis->A_IB and pcis->A_BI if we did not change explicitly the variables on the pressures */
16461dd7afcfSStefano Zampini   ierr = PCBDDCBenignShellMat(pc,PETSC_FALSE);CHKERRQ(ierr);
16471dd7afcfSStefano Zampini 
164858a03d70SStefano Zampini   if (pcbddc->dbg_flag) {
164958a03d70SStefano Zampini     ierr = PetscViewerASCIISubtractTab(pcbddc->dbg_viewer,2*pcbddc->current_level);CHKERRQ(ierr);
16502b510759SStefano Zampini   }
16510c7d97c5SJed Brown   PetscFunctionReturn(0);
16520c7d97c5SJed Brown }
16530c7d97c5SJed Brown 
16540c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
16550c7d97c5SJed Brown /*
165650efa1b5SStefano Zampini    PCApply_BDDC - Applies the BDDC operator to a vector.
16570c7d97c5SJed Brown 
16580c7d97c5SJed Brown    Input Parameters:
16590f202f7eSStefano Zampini +  pc - the preconditioner context
16600f202f7eSStefano Zampini -  r - input vector (global)
16610c7d97c5SJed Brown 
16620c7d97c5SJed Brown    Output Parameter:
16630c7d97c5SJed Brown .  z - output vector (global)
16640c7d97c5SJed Brown 
16650c7d97c5SJed Brown    Application Interface Routine: PCApply()
16660c7d97c5SJed Brown  */
16670c7d97c5SJed Brown #undef __FUNCT__
16680c7d97c5SJed Brown #define __FUNCT__ "PCApply_BDDC"
166953cdbc3dSStefano Zampini PetscErrorCode PCApply_BDDC(PC pc,Vec r,Vec z)
16700c7d97c5SJed Brown {
16710c7d97c5SJed Brown   PC_IS             *pcis = (PC_IS*)(pc->data);
16720c7d97c5SJed Brown   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1673b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
16740c7d97c5SJed Brown   PetscErrorCode    ierr;
16753b03a366Sstefano_zampini   const PetscScalar one = 1.0;
16763b03a366Sstefano_zampini   const PetscScalar m_one = -1.0;
16772617d88aSStefano Zampini   const PetscScalar zero = 0.0;
16780c7d97c5SJed Brown 
16790c7d97c5SJed Brown /* This code is similar to that provided in nn.c for PCNN
16800c7d97c5SJed Brown    NN interface preconditioner changed to BDDC
1681b097fa66SStefano Zampini    Added support for M_3 preconditioner in the reference article (code is active if pcbddc->switch_static == PETSC_TRUE) */
16820c7d97c5SJed Brown 
16830c7d97c5SJed Brown   PetscFunctionBegin;
16841dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
16851dd7afcfSStefano Zampini     Vec swap;
168627b6a85dSStefano Zampini 
168727b6a85dSStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
16881dd7afcfSStefano Zampini     swap = pcbddc->work_change;
16891dd7afcfSStefano Zampini     pcbddc->work_change = r;
16901dd7afcfSStefano Zampini     r = swap;
16911dd7afcfSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
16921dd7afcfSStefano Zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) {
16931dd7afcfSStefano Zampini       ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr);
16941dd7afcfSStefano Zampini       ierr = VecLockPush(pcis->vec1_global);CHKERRQ(ierr);
16951dd7afcfSStefano Zampini     }
16961dd7afcfSStefano Zampini   }
169727b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
1698015636ebSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
1699efc2fbd9SStefano Zampini   }
170027b6a85dSStefano Zampini   if (!pcbddc->use_exact_dirichlet_trick && !pcbddc->benign_apply_coarse_only) {
1701b097fa66SStefano Zampini     ierr = VecCopy(r,z);CHKERRQ(ierr);
17020c7d97c5SJed Brown     /* First Dirichlet solve */
17030c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17040c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17050c7d97c5SJed Brown     /*
17060c7d97c5SJed Brown       Assembling right hand side for BDDC operator
1707b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
1708674ae819SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
17090c7d97c5SJed Brown     */
1710b097fa66SStefano Zampini     if (n_D) {
1711b097fa66SStefano Zampini       ierr = KSPSolve(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
17120c7d97c5SJed Brown       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
171316909a7fSStefano Zampini       if (pcbddc->switch_static) {
171416909a7fSStefano Zampini         Mat_IS *matis = (Mat_IS*)(pc->mat->data);
171516909a7fSStefano Zampini 
171616909a7fSStefano Zampini         ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
171716909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
171816909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
171916909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
172016909a7fSStefano Zampini           ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
172116909a7fSStefano Zampini         } else {
172216909a7fSStefano Zampini           ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
172316909a7fSStefano Zampini           ierr = MatMult(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
172416909a7fSStefano Zampini           ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
172516909a7fSStefano Zampini         }
172616909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
172716909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
172816909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
172916909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
173016909a7fSStefano Zampini       } else {
1731b097fa66SStefano Zampini         ierr = MatMult(pcis->A_BI,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
173216909a7fSStefano Zampini       }
1733b097fa66SStefano Zampini     } else {
1734b097fa66SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1735b097fa66SStefano Zampini     }
17360c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
17370c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1738674ae819SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
1739b76ba322SStefano Zampini   } else {
17404fee134fSStefano Zampini     if (!pcbddc->benign_apply_coarse_only) {
1741674ae819SStefano Zampini       ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
1742b76ba322SStefano Zampini     }
17434fee134fSStefano Zampini   }
1744b76ba322SStefano Zampini 
17452617d88aSStefano Zampini   /* Apply interface preconditioner
17462617d88aSStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
1747dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_FALSE);CHKERRQ(ierr);
17482617d88aSStefano Zampini 
1749674ae819SStefano Zampini   /* Apply transpose of partition of unity operator */
1750674ae819SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
17510c7d97c5SJed Brown 
17523b03a366Sstefano_zampini   /* Second Dirichlet solve and assembling of output */
17530c7d97c5SJed Brown   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
17540c7d97c5SJed Brown   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1755b097fa66SStefano Zampini   if (n_B) {
175616909a7fSStefano Zampini     if (pcbddc->switch_static) {
175716909a7fSStefano Zampini       Mat_IS *matis = (Mat_IS*)(pc->mat->data);
175816909a7fSStefano Zampini 
175916909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
176016909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
176116909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
176216909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
176316909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
176416909a7fSStefano Zampini         ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
176516909a7fSStefano Zampini       } else {
176616909a7fSStefano Zampini         ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
176716909a7fSStefano Zampini         ierr = MatMult(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
176816909a7fSStefano Zampini         ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
176916909a7fSStefano Zampini       }
177016909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
177116909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
177216909a7fSStefano Zampini     } else {
17730c7d97c5SJed Brown       ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
177416909a7fSStefano Zampini     }
177516909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
177616909a7fSStefano Zampini     Mat_IS *matis = (Mat_IS*)(pc->mat->data);
177716909a7fSStefano Zampini 
177816909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
177916909a7fSStefano Zampini       ierr = MatMult(matis->A,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
178016909a7fSStefano Zampini     } else {
178116909a7fSStefano Zampini       ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr);
178216909a7fSStefano Zampini       ierr = MatMult(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
178316909a7fSStefano Zampini       ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr);
178416909a7fSStefano Zampini     }
1785b097fa66SStefano Zampini   }
1786df187020SStefano Zampini   ierr = KSPSolve(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
1787efc2fbd9SStefano Zampini 
178827b6a85dSStefano Zampini   if (!pcbddc->use_exact_dirichlet_trick && !pcbddc->benign_apply_coarse_only) {
1789b097fa66SStefano Zampini     if (pcbddc->switch_static) {
1790b097fa66SStefano Zampini       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
1791b097fa66SStefano Zampini     } else {
1792b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
1793b097fa66SStefano Zampini     }
17940c7d97c5SJed Brown     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
17950c7d97c5SJed Brown     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1796b097fa66SStefano Zampini   } else {
1797b097fa66SStefano Zampini     if (pcbddc->switch_static) {
1798b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
1799b097fa66SStefano Zampini     } else {
1800b097fa66SStefano Zampini       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
1801b097fa66SStefano Zampini     }
1802b097fa66SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1803b097fa66SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1804b097fa66SStefano Zampini   }
1805efc2fbd9SStefano Zampini 
180627b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
18071dd7afcfSStefano Zampini     if (pcbddc->benign_apply_coarse_only) {
18081dd7afcfSStefano Zampini       ierr = PetscMemzero(pcbddc->benign_p0,pcbddc->benign_n*sizeof(PetscScalar));CHKERRQ(ierr);
18091dd7afcfSStefano Zampini     }
1810015636ebSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
1811efc2fbd9SStefano Zampini   }
18121dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
18131dd7afcfSStefano Zampini     Vec swap;
18141dd7afcfSStefano Zampini 
18151dd7afcfSStefano Zampini     swap = r;
18161dd7afcfSStefano Zampini     r = pcbddc->work_change;
18171dd7afcfSStefano Zampini     pcbddc->work_change = swap;
18181dd7afcfSStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
18191dd7afcfSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
18201dd7afcfSStefano Zampini   }
18210c7d97c5SJed Brown   PetscFunctionReturn(0);
18220c7d97c5SJed Brown }
182350efa1b5SStefano Zampini 
182450efa1b5SStefano Zampini /* -------------------------------------------------------------------------- */
182550efa1b5SStefano Zampini /*
182650efa1b5SStefano Zampini    PCApplyTranspose_BDDC - Applies the transpose of the BDDC operator to a vector.
182750efa1b5SStefano Zampini 
182850efa1b5SStefano Zampini    Input Parameters:
18290f202f7eSStefano Zampini +  pc - the preconditioner context
18300f202f7eSStefano Zampini -  r - input vector (global)
183150efa1b5SStefano Zampini 
183250efa1b5SStefano Zampini    Output Parameter:
183350efa1b5SStefano Zampini .  z - output vector (global)
183450efa1b5SStefano Zampini 
183550efa1b5SStefano Zampini    Application Interface Routine: PCApplyTranspose()
183650efa1b5SStefano Zampini  */
183750efa1b5SStefano Zampini #undef __FUNCT__
183850efa1b5SStefano Zampini #define __FUNCT__ "PCApplyTranspose_BDDC"
183950efa1b5SStefano Zampini PetscErrorCode PCApplyTranspose_BDDC(PC pc,Vec r,Vec z)
184050efa1b5SStefano Zampini {
184150efa1b5SStefano Zampini   PC_IS             *pcis = (PC_IS*)(pc->data);
184250efa1b5SStefano Zampini   PC_BDDC           *pcbddc = (PC_BDDC*)(pc->data);
1843b097fa66SStefano Zampini   PetscInt          n_B = pcis->n_B, n_D = pcis->n - n_B;
184450efa1b5SStefano Zampini   PetscErrorCode    ierr;
184550efa1b5SStefano Zampini   const PetscScalar one = 1.0;
184650efa1b5SStefano Zampini   const PetscScalar m_one = -1.0;
184750efa1b5SStefano Zampini   const PetscScalar zero = 0.0;
184850efa1b5SStefano Zampini 
184950efa1b5SStefano Zampini   PetscFunctionBegin;
18501dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
18511dd7afcfSStefano Zampini     Vec swap;
185227b6a85dSStefano Zampini 
185327b6a85dSStefano Zampini     ierr = MatMultTranspose(pcbddc->ChangeOfBasisMatrix,r,pcbddc->work_change);CHKERRQ(ierr);
18541dd7afcfSStefano Zampini     swap = pcbddc->work_change;
18551dd7afcfSStefano Zampini     pcbddc->work_change = r;
18561dd7afcfSStefano Zampini     r = swap;
185727b6a85dSStefano Zampini     /* save rhs so that we don't need to apply the change of basis for the exact dirichlet trick in PreSolve */
185827b6a85dSStefano Zampini     if (pcbddc->benign_apply_coarse_only && pcbddc->use_exact_dirichlet_trick && pcbddc->change_interior) {
185927b6a85dSStefano Zampini       ierr = VecCopy(r,pcis->vec1_global);CHKERRQ(ierr);
186027b6a85dSStefano Zampini       ierr = VecLockPush(pcis->vec1_global);CHKERRQ(ierr);
18611dd7afcfSStefano Zampini     }
186227b6a85dSStefano Zampini   }
186327b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* get p0 from r */
1864537c1cdfSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,r,PETSC_TRUE);CHKERRQ(ierr);
1865537c1cdfSStefano Zampini   }
186627b6a85dSStefano Zampini   if (!pcbddc->use_exact_dirichlet_trick && !pcbddc->benign_apply_coarse_only) {
1867b097fa66SStefano Zampini     ierr = VecCopy(r,z);CHKERRQ(ierr);
186850efa1b5SStefano Zampini     /* First Dirichlet solve */
186950efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
187050efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,r,pcis->vec1_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
187150efa1b5SStefano Zampini     /*
187250efa1b5SStefano Zampini       Assembling right hand side for BDDC operator
1873b097fa66SStefano Zampini       - pcis->vec1_D for the Dirichlet part (if needed, i.e. pcbddc->switch_static == PETSC_TRUE)
187450efa1b5SStefano Zampini       - pcis->vec1_B the interface part of the global vector z
187550efa1b5SStefano Zampini     */
1876b097fa66SStefano Zampini     if (n_D) {
1877b097fa66SStefano Zampini       ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec1_D,pcis->vec2_D);CHKERRQ(ierr);
187850efa1b5SStefano Zampini       ierr = VecScale(pcis->vec2_D,m_one);CHKERRQ(ierr);
187916909a7fSStefano Zampini       if (pcbddc->switch_static) {
188016909a7fSStefano Zampini         Mat_IS *matis = (Mat_IS*)(pc->mat->data);
188116909a7fSStefano Zampini 
188216909a7fSStefano Zampini         ierr = VecSet(pcis->vec1_N,0.);CHKERRQ(ierr);
188316909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
188416909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
188516909a7fSStefano Zampini         if (!pcbddc->switch_static_change) {
188616909a7fSStefano Zampini           ierr = MatMultTranspose(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
188716909a7fSStefano Zampini         } else {
188816909a7fSStefano Zampini           ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
188916909a7fSStefano Zampini           ierr = MatMultTranspose(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
189016909a7fSStefano Zampini           ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
189116909a7fSStefano Zampini         }
189216909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
189316909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec1_D,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
189416909a7fSStefano Zampini         ierr = VecScatterBegin(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
189516909a7fSStefano Zampini         ierr = VecScatterEnd(pcis->N_to_B,pcis->vec2_N,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
189616909a7fSStefano Zampini       } else {
1897b097fa66SStefano Zampini         ierr = MatMultTranspose(pcis->A_IB,pcis->vec2_D,pcis->vec1_B);CHKERRQ(ierr);
189816909a7fSStefano Zampini       }
1899b097fa66SStefano Zampini     } else {
1900b097fa66SStefano Zampini       ierr = VecSet(pcis->vec1_B,zero);CHKERRQ(ierr);
1901b097fa66SStefano Zampini     }
190250efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
190350efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,pcis->vec1_B,z,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
190450efa1b5SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,z,pcis->vec1_B);CHKERRQ(ierr);
190550efa1b5SStefano Zampini   } else {
190650efa1b5SStefano Zampini     ierr = PCBDDCScalingRestriction(pc,r,pcis->vec1_B);CHKERRQ(ierr);
190750efa1b5SStefano Zampini   }
190850efa1b5SStefano Zampini 
190950efa1b5SStefano Zampini   /* Apply interface preconditioner
191050efa1b5SStefano Zampini      input/output vecs: pcis->vec1_B and pcis->vec1_D */
1911dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(pc,PETSC_TRUE);CHKERRQ(ierr);
191250efa1b5SStefano Zampini 
191350efa1b5SStefano Zampini   /* Apply transpose of partition of unity operator */
191450efa1b5SStefano Zampini   ierr = PCBDDCScalingExtension(pc,pcis->vec1_B,z);CHKERRQ(ierr);
191550efa1b5SStefano Zampini 
191650efa1b5SStefano Zampini   /* Second Dirichlet solve and assembling of output */
191750efa1b5SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
191850efa1b5SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,z,pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1919b097fa66SStefano Zampini   if (n_B) {
192016909a7fSStefano Zampini     if (pcbddc->switch_static) {
192116909a7fSStefano Zampini       Mat_IS *matis = (Mat_IS*)(pc->mat->data);
192216909a7fSStefano Zampini 
192316909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
192416909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec1_D,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
192516909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
192616909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_B,pcis->vec1_B,pcis->vec1_N,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
192716909a7fSStefano Zampini       if (!pcbddc->switch_static_change) {
192816909a7fSStefano Zampini         ierr = MatMultTranspose(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
192916909a7fSStefano Zampini       } else {
193016909a7fSStefano Zampini         ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
193116909a7fSStefano Zampini         ierr = MatMultTranspose(matis->A,pcis->vec2_N,pcis->vec1_N);CHKERRQ(ierr);
193216909a7fSStefano Zampini         ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
193316909a7fSStefano Zampini       }
193416909a7fSStefano Zampini       ierr = VecScatterBegin(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
193516909a7fSStefano Zampini       ierr = VecScatterEnd(pcis->N_to_D,pcis->vec2_N,pcis->vec3_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
193616909a7fSStefano Zampini     } else {
193750efa1b5SStefano Zampini       ierr = MatMultTranspose(pcis->A_BI,pcis->vec1_B,pcis->vec3_D);CHKERRQ(ierr);
193816909a7fSStefano Zampini     }
193916909a7fSStefano Zampini   } else if (pcbddc->switch_static) { /* n_B is zero */
194016909a7fSStefano Zampini     Mat_IS *matis = (Mat_IS*)(pc->mat->data);
194116909a7fSStefano Zampini 
194216909a7fSStefano Zampini     if (!pcbddc->switch_static_change) {
194316909a7fSStefano Zampini       ierr = MatMultTranspose(matis->A,pcis->vec1_D,pcis->vec3_D);CHKERRQ(ierr);
194416909a7fSStefano Zampini     } else {
194516909a7fSStefano Zampini       ierr = MatMult(pcbddc->switch_static_change,pcis->vec1_D,pcis->vec1_N);CHKERRQ(ierr);
194616909a7fSStefano Zampini       ierr = MatMultTranspose(matis->A,pcis->vec1_N,pcis->vec2_N);CHKERRQ(ierr);
194716909a7fSStefano Zampini       ierr = MatMultTranspose(pcbddc->switch_static_change,pcis->vec2_N,pcis->vec3_D);CHKERRQ(ierr);
194816909a7fSStefano Zampini     }
1949b097fa66SStefano Zampini   }
1950b0147a47SStefano Zampini   ierr = KSPSolveTranspose(pcbddc->ksp_D,pcis->vec3_D,pcis->vec4_D);CHKERRQ(ierr);
195127b6a85dSStefano Zampini   if (!pcbddc->use_exact_dirichlet_trick && !pcbddc->benign_apply_coarse_only) {
1952b097fa66SStefano Zampini     if (pcbddc->switch_static) {
1953b097fa66SStefano Zampini       ierr = VecAXPBYPCZ(pcis->vec2_D,m_one,one,m_one,pcis->vec4_D,pcis->vec1_D);CHKERRQ(ierr);
1954b097fa66SStefano Zampini     } else {
1955b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec2_D,m_one,m_one,pcis->vec4_D);CHKERRQ(ierr);
1956b097fa66SStefano Zampini     }
195750efa1b5SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
195850efa1b5SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec2_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1959b097fa66SStefano Zampini   } else {
1960b097fa66SStefano Zampini     if (pcbddc->switch_static) {
1961b097fa66SStefano Zampini       ierr = VecAXPBY(pcis->vec4_D,one,m_one,pcis->vec1_D);CHKERRQ(ierr);
1962b097fa66SStefano Zampini     } else {
1963b097fa66SStefano Zampini       ierr = VecScale(pcis->vec4_D,m_one);CHKERRQ(ierr);
1964b097fa66SStefano Zampini     }
1965b097fa66SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1966b097fa66SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_D,pcis->vec4_D,z,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1967b097fa66SStefano Zampini   }
196827b6a85dSStefano Zampini   if (pcbddc->benign_have_null) { /* set p0 (computed in PCBDDCApplyInterface) */
1969537c1cdfSStefano Zampini     ierr = PCBDDCBenignGetOrSetP0(pc,z,PETSC_FALSE);CHKERRQ(ierr);
1970537c1cdfSStefano Zampini   }
19711dd7afcfSStefano Zampini   if (pcbddc->ChangeOfBasisMatrix) {
19721dd7afcfSStefano Zampini     Vec swap;
19731dd7afcfSStefano Zampini 
19741dd7afcfSStefano Zampini     swap = r;
19751dd7afcfSStefano Zampini     r = pcbddc->work_change;
19761dd7afcfSStefano Zampini     pcbddc->work_change = swap;
19771dd7afcfSStefano Zampini     ierr = VecCopy(z,pcbddc->work_change);CHKERRQ(ierr);
19781dd7afcfSStefano Zampini     ierr = MatMult(pcbddc->ChangeOfBasisMatrix,pcbddc->work_change,z);CHKERRQ(ierr);
19791dd7afcfSStefano Zampini   }
198050efa1b5SStefano Zampini   PetscFunctionReturn(0);
198150efa1b5SStefano Zampini }
1982da1bb401SStefano Zampini /* -------------------------------------------------------------------------- */
1983674ae819SStefano Zampini 
1984da1bb401SStefano Zampini #undef __FUNCT__
1985da1bb401SStefano Zampini #define __FUNCT__ "PCDestroy_BDDC"
1986da1bb401SStefano Zampini PetscErrorCode PCDestroy_BDDC(PC pc)
1987da1bb401SStefano Zampini {
1988da1bb401SStefano Zampini   PC_BDDC        *pcbddc = (PC_BDDC*)pc->data;
1989da1bb401SStefano Zampini   PetscErrorCode ierr;
1990da1bb401SStefano Zampini 
1991da1bb401SStefano Zampini   PetscFunctionBegin;
1992674ae819SStefano Zampini   /* free BDDC custom data  */
1993674ae819SStefano Zampini   ierr = PCBDDCResetCustomization(pc);CHKERRQ(ierr);
1994674ae819SStefano Zampini   /* destroy objects related to topography */
1995674ae819SStefano Zampini   ierr = PCBDDCResetTopography(pc);CHKERRQ(ierr);
1996674ae819SStefano Zampini   /* free allocated graph structure */
1997da1bb401SStefano Zampini   ierr = PetscFree(pcbddc->mat_graph);CHKERRQ(ierr);
1998b96c3477SStefano Zampini   /* free allocated sub schurs structure */
1999b96c3477SStefano Zampini   ierr = PetscFree(pcbddc->sub_schurs);CHKERRQ(ierr);
200034a97f8cSStefano Zampini   /* destroy objects for scaling operator */
2001674ae819SStefano Zampini   ierr = PCBDDCScalingDestroy(pc);CHKERRQ(ierr);
200234a97f8cSStefano Zampini   ierr = PetscFree(pcbddc->deluxe_ctx);CHKERRQ(ierr);
2003674ae819SStefano Zampini   /* free solvers stuff */
2004674ae819SStefano Zampini   ierr = PCBDDCResetSolvers(pc);CHKERRQ(ierr);
200562a6ff1dSStefano Zampini   /* free global vectors needed in presolve */
200662a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->temp_solution);CHKERRQ(ierr);
200762a6ff1dSStefano Zampini   ierr = VecDestroy(&pcbddc->original_rhs);CHKERRQ(ierr);
20081dd7afcfSStefano Zampini   /* free data created by PCIS */
20091dd7afcfSStefano Zampini   ierr = PCISDestroy(pc);CHKERRQ(ierr);
20103425bc38SStefano Zampini   /* remove functions */
2011906d46d4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",NULL);CHKERRQ(ierr);
2012674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",NULL);CHKERRQ(ierr);
201330368db7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",NULL);CHKERRQ(ierr);
2014bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",NULL);CHKERRQ(ierr);
20152b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",NULL);CHKERRQ(ierr);
2016b8ffe317SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",NULL);CHKERRQ(ierr);
20172b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",NULL);CHKERRQ(ierr);
2018bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",NULL);CHKERRQ(ierr);
2019bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
202082ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
2021bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
202282ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
2023bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",NULL);CHKERRQ(ierr);
202482ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",NULL);CHKERRQ(ierr);
2025bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",NULL);CHKERRQ(ierr);
2026785d1243SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",NULL);CHKERRQ(ierr);
2027bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",NULL);CHKERRQ(ierr);
202863602bcaSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",NULL);CHKERRQ(ierr);
2029bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",NULL);CHKERRQ(ierr);
2030bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",NULL);CHKERRQ(ierr);
2031bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",NULL);CHKERRQ(ierr);
2032bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",NULL);CHKERRQ(ierr);
2033674ae819SStefano Zampini   /* Free the private data structure */
2034674ae819SStefano Zampini   ierr = PetscFree(pc->data);CHKERRQ(ierr);
2035da1bb401SStefano Zampini   PetscFunctionReturn(0);
2036da1bb401SStefano Zampini }
20373425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
20381e6b0712SBarry Smith 
20393425bc38SStefano Zampini #undef __FUNCT__
20403425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetRHS_BDDC"
20413425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetRHS_BDDC(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
20423425bc38SStefano Zampini {
2043674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
2044c08af4c6SStefano Zampini   Vec            copy_standard_rhs;
20453425bc38SStefano Zampini   PC_IS*         pcis;
20463425bc38SStefano Zampini   PC_BDDC*       pcbddc;
20473425bc38SStefano Zampini   PetscErrorCode ierr;
20480c7d97c5SJed Brown 
20493425bc38SStefano Zampini   PetscFunctionBegin;
20503425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
20513425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
20523425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
20533425bc38SStefano Zampini 
2054c08af4c6SStefano Zampini   /*
2055c08af4c6SStefano Zampini      change of basis for physical rhs if needed
2056c08af4c6SStefano Zampini      It also changes the rhs in case of dirichlet boundaries
2057c08af4c6SStefano Zampini      TODO: better management when FETIDP will have its own class
2058c08af4c6SStefano Zampini   */
2059c08af4c6SStefano Zampini   ierr = VecDuplicate(standard_rhs,&copy_standard_rhs);CHKERRQ(ierr);
2060c08af4c6SStefano Zampini   ierr = VecCopy(standard_rhs,copy_standard_rhs);CHKERRQ(ierr);
2061c08af4c6SStefano Zampini   ierr = PCPreSolve_BDDC(mat_ctx->pc,NULL,copy_standard_rhs,NULL);CHKERRQ(ierr);
20623425bc38SStefano Zampini   /* store vectors for computation of fetidp final solution */
2063c08af4c6SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,copy_standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2064c08af4c6SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_D,copy_standard_rhs,mat_ctx->temp_solution_D,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2065fb223d50SStefano Zampini   /* scale rhs since it should be unassembled */
2066fb223d50SStefano Zampini   /* TODO use counter scaling? (also below) */
2067c08af4c6SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2068c08af4c6SStefano Zampini   ierr = VecScatterEnd(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2069674ae819SStefano Zampini   /* Apply partition of unity */
20703425bc38SStefano Zampini   ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
2071c08af4c6SStefano Zampini   /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,copy_standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
20728eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
20733425bc38SStefano Zampini     /* compute partially subassembled Schur complement right-hand side */
20743425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
20753425bc38SStefano Zampini     ierr = MatMult(pcis->A_BI,pcis->vec1_D,pcis->vec1_B);CHKERRQ(ierr);
20763425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_B,-1.0,pcis->vec1_B);CHKERRQ(ierr);
2077c08af4c6SStefano Zampini     ierr = VecSet(copy_standard_rhs,0.0);CHKERRQ(ierr);
2078c08af4c6SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,mat_ctx->temp_solution_B,copy_standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2079c08af4c6SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,mat_ctx->temp_solution_B,copy_standard_rhs,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2080c08af4c6SStefano Zampini     /* ierr = PCBDDCScalingRestriction(mat_ctx->pc,copy_standard_rhs,mat_ctx->temp_solution_B);CHKERRQ(ierr); */
2081c08af4c6SStefano Zampini     ierr = VecScatterBegin(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2082c08af4c6SStefano Zampini     ierr = VecScatterEnd(pcis->global_to_B,copy_standard_rhs,mat_ctx->temp_solution_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20833425bc38SStefano Zampini     ierr = VecPointwiseMult(mat_ctx->temp_solution_B,pcis->D,mat_ctx->temp_solution_B);CHKERRQ(ierr);
20843425bc38SStefano Zampini   }
2085c08af4c6SStefano Zampini   ierr = VecDestroy(&copy_standard_rhs);CHKERRQ(ierr);
20863425bc38SStefano Zampini   /* BDDC rhs */
20873425bc38SStefano Zampini   ierr = VecCopy(mat_ctx->temp_solution_B,pcis->vec1_B);CHKERRQ(ierr);
20888eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
20893425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
20903425bc38SStefano Zampini   }
20913425bc38SStefano Zampini   /* apply BDDC */
2092dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
20933425bc38SStefano Zampini   /* Application of B_delta and assembling of rhs for fetidp fluxes */
20943425bc38SStefano Zampini   ierr = VecSet(fetidp_flux_rhs,0.0);CHKERRQ(ierr);
20953425bc38SStefano Zampini   ierr = MatMult(mat_ctx->B_delta,pcis->vec1_B,mat_ctx->lambda_local);CHKERRQ(ierr);
20963425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20973425bc38SStefano Zampini   ierr = VecScatterEnd(mat_ctx->l2g_lambda,mat_ctx->lambda_local,fetidp_flux_rhs,ADD_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
20983425bc38SStefano Zampini   PetscFunctionReturn(0);
20993425bc38SStefano Zampini }
21001e6b0712SBarry Smith 
21013425bc38SStefano Zampini #undef __FUNCT__
21023425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetRHS"
21033425bc38SStefano Zampini /*@
21040f202f7eSStefano Zampini  PCBDDCMatFETIDPGetRHS - Compute the right-hand side for FETI-DP linear system using the physical right-hand side
21053425bc38SStefano Zampini 
21063425bc38SStefano Zampini    Collective
21073425bc38SStefano Zampini 
21083425bc38SStefano Zampini    Input Parameters:
21090f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix object obtained by a call to PCBDDCCreateFETIDPOperators
21100f202f7eSStefano Zampini -  standard_rhs    - the right-hand side of the original linear system
21113425bc38SStefano Zampini 
21123425bc38SStefano Zampini    Output Parameters:
21130f202f7eSStefano Zampini .  fetidp_flux_rhs - the right-hand side for the FETI-DP linear system
21143425bc38SStefano Zampini 
21153425bc38SStefano Zampini    Level: developer
21163425bc38SStefano Zampini 
21173425bc38SStefano Zampini    Notes:
21183425bc38SStefano Zampini 
21190f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetSolution
21203425bc38SStefano Zampini @*/
21213425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetRHS(Mat fetidp_mat, Vec standard_rhs, Vec fetidp_flux_rhs)
21223425bc38SStefano Zampini {
2123674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
21243425bc38SStefano Zampini   PetscErrorCode ierr;
21253425bc38SStefano Zampini 
21263425bc38SStefano Zampini   PetscFunctionBegin;
21273425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
21283425bc38SStefano Zampini   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetRHS_C",(Mat,Vec,Vec),(fetidp_mat,standard_rhs,fetidp_flux_rhs));CHKERRQ(ierr);
21293425bc38SStefano Zampini   PetscFunctionReturn(0);
21303425bc38SStefano Zampini }
21313425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
21321e6b0712SBarry Smith 
21333425bc38SStefano Zampini #undef __FUNCT__
21343425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetSolution_BDDC"
21353425bc38SStefano Zampini static PetscErrorCode PCBDDCMatFETIDPGetSolution_BDDC(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
21363425bc38SStefano Zampini {
2137674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
21383425bc38SStefano Zampini   PC_IS*         pcis;
21393425bc38SStefano Zampini   PC_BDDC*       pcbddc;
21403425bc38SStefano Zampini   PetscErrorCode ierr;
21413425bc38SStefano Zampini 
21423425bc38SStefano Zampini   PetscFunctionBegin;
21433425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
21443425bc38SStefano Zampini   pcis = (PC_IS*)mat_ctx->pc->data;
21453425bc38SStefano Zampini   pcbddc = (PC_BDDC*)mat_ctx->pc->data;
21463425bc38SStefano Zampini 
21473425bc38SStefano Zampini   /* apply B_delta^T */
21483425bc38SStefano Zampini   ierr = VecScatterBegin(mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
21493425bc38SStefano Zampini   ierr = VecScatterEnd  (mat_ctx->l2g_lambda,fetidp_flux_sol,mat_ctx->lambda_local,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
21503425bc38SStefano Zampini   ierr = MatMultTranspose(mat_ctx->B_delta,mat_ctx->lambda_local,pcis->vec1_B);CHKERRQ(ierr);
21513425bc38SStefano Zampini   /* compute rhs for BDDC application */
21523425bc38SStefano Zampini   ierr = VecAYPX(pcis->vec1_B,-1.0,mat_ctx->temp_solution_B);CHKERRQ(ierr);
21538eeda7d8SStefano Zampini   if (pcbddc->switch_static) {
21543425bc38SStefano Zampini     ierr = VecCopy(mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
21553425bc38SStefano Zampini   }
21563425bc38SStefano Zampini   /* apply BDDC */
2157dc359a40SStefano Zampini   ierr = PCBDDCApplyInterfacePreconditioner(mat_ctx->pc,PETSC_FALSE);CHKERRQ(ierr);
21583425bc38SStefano Zampini   /* put values into standard global vector */
21593425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
21603425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_B,pcis->vec1_B,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
21618eeda7d8SStefano Zampini   if (!pcbddc->switch_static) {
21623425bc38SStefano Zampini     /* compute values into the interior if solved for the partially subassembled Schur complement */
21633425bc38SStefano Zampini     ierr = MatMult(pcis->A_IB,pcis->vec1_B,pcis->vec1_D);CHKERRQ(ierr);
21643425bc38SStefano Zampini     ierr = VecAXPY(mat_ctx->temp_solution_D,-1.0,pcis->vec1_D);CHKERRQ(ierr);
21653425bc38SStefano Zampini     ierr = KSPSolve(pcbddc->ksp_D,mat_ctx->temp_solution_D,pcis->vec1_D);CHKERRQ(ierr);
21663425bc38SStefano Zampini   }
21673425bc38SStefano Zampini   ierr = VecScatterBegin(pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
21683425bc38SStefano Zampini   ierr = VecScatterEnd  (pcis->global_to_D,pcis->vec1_D,standard_sol,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
21693425bc38SStefano Zampini   /* final change of basis if needed
21703425bc38SStefano Zampini      Is also sums the dirichlet part removed during RHS assembling */
21713308cffdSStefano Zampini   ierr = PCPostSolve_BDDC(mat_ctx->pc,NULL,NULL,standard_sol);CHKERRQ(ierr);
21723425bc38SStefano Zampini   PetscFunctionReturn(0);
21733425bc38SStefano Zampini }
21741e6b0712SBarry Smith 
21753425bc38SStefano Zampini #undef __FUNCT__
21763425bc38SStefano Zampini #define __FUNCT__ "PCBDDCMatFETIDPGetSolution"
21773425bc38SStefano Zampini /*@
21780f202f7eSStefano Zampini  PCBDDCMatFETIDPGetSolution - Compute the physical solution using the solution of the FETI-DP linear system
21793425bc38SStefano Zampini 
21803425bc38SStefano Zampini    Collective
21813425bc38SStefano Zampini 
21823425bc38SStefano Zampini    Input Parameters:
21830f202f7eSStefano Zampini +  fetidp_mat      - the FETI-DP matrix obtained by a call to PCBDDCCreateFETIDPOperators
21840f202f7eSStefano Zampini -  fetidp_flux_sol - the solution of the FETI-DP linear system
21853425bc38SStefano Zampini 
21863425bc38SStefano Zampini    Output Parameters:
21870f202f7eSStefano Zampini .  standard_sol    - the solution defined on the physical domain
21883425bc38SStefano Zampini 
21893425bc38SStefano Zampini    Level: developer
21903425bc38SStefano Zampini 
21913425bc38SStefano Zampini    Notes:
21923425bc38SStefano Zampini 
21930f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCCreateFETIDPOperators, PCBDDCMatFETIDPGetRHS
21943425bc38SStefano Zampini @*/
21953425bc38SStefano Zampini PetscErrorCode PCBDDCMatFETIDPGetSolution(Mat fetidp_mat, Vec fetidp_flux_sol, Vec standard_sol)
21963425bc38SStefano Zampini {
2197674ae819SStefano Zampini   FETIDPMat_ctx  mat_ctx;
21983425bc38SStefano Zampini   PetscErrorCode ierr;
21993425bc38SStefano Zampini 
22003425bc38SStefano Zampini   PetscFunctionBegin;
22013425bc38SStefano Zampini   ierr = MatShellGetContext(fetidp_mat,&mat_ctx);CHKERRQ(ierr);
22023425bc38SStefano Zampini   ierr = PetscTryMethod(mat_ctx->pc,"PCBDDCMatFETIDPGetSolution_C",(Mat,Vec,Vec),(fetidp_mat,fetidp_flux_sol,standard_sol));CHKERRQ(ierr);
22033425bc38SStefano Zampini   PetscFunctionReturn(0);
22043425bc38SStefano Zampini }
22053425bc38SStefano Zampini /* -------------------------------------------------------------------------- */
22061e6b0712SBarry Smith 
2207f23aa3ddSBarry Smith extern PetscErrorCode FETIDPMatMult(Mat,Vec,Vec);
2208edf7251bSStefano Zampini extern PetscErrorCode FETIDPMatMultTranspose(Mat,Vec,Vec);
2209f23aa3ddSBarry Smith extern PetscErrorCode PCBDDCDestroyFETIDPMat(Mat);
2210f23aa3ddSBarry Smith extern PetscErrorCode FETIDPPCApply(PC,Vec,Vec);
2211edf7251bSStefano Zampini extern PetscErrorCode FETIDPPCApplyTranspose(PC,Vec,Vec);
2212f23aa3ddSBarry Smith extern PetscErrorCode PCBDDCDestroyFETIDPPC(PC);
2213674ae819SStefano Zampini 
22143425bc38SStefano Zampini #undef __FUNCT__
22153425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPOperators_BDDC"
22163425bc38SStefano Zampini static PetscErrorCode PCBDDCCreateFETIDPOperators_BDDC(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
22173425bc38SStefano Zampini {
2218674ae819SStefano Zampini 
2219674ae819SStefano Zampini   FETIDPMat_ctx  fetidpmat_ctx;
22203425bc38SStefano Zampini   Mat            newmat;
2221674ae819SStefano Zampini   FETIDPPC_ctx   fetidppc_ctx;
22223425bc38SStefano Zampini   PC             newpc;
2223ce94432eSBarry Smith   MPI_Comm       comm;
22243425bc38SStefano Zampini   PetscErrorCode ierr;
22253425bc38SStefano Zampini 
22263425bc38SStefano Zampini   PetscFunctionBegin;
2227ce94432eSBarry Smith   ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr);
22283425bc38SStefano Zampini   /* FETIDP linear matrix */
22293425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPMatContext(pc,&fetidpmat_ctx);CHKERRQ(ierr);
22303425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPMatContext(fetidpmat_ctx);CHKERRQ(ierr);
22313425bc38SStefano Zampini   ierr = MatCreateShell(comm,PETSC_DECIDE,PETSC_DECIDE,fetidpmat_ctx->n_lambda,fetidpmat_ctx->n_lambda,fetidpmat_ctx,&newmat);CHKERRQ(ierr);
22323425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT,(void (*)(void))FETIDPMatMult);CHKERRQ(ierr);
2233edf7251bSStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_MULT_TRANSPOSE,(void (*)(void))FETIDPMatMultTranspose);CHKERRQ(ierr);
22343425bc38SStefano Zampini   ierr = MatShellSetOperation(newmat,MATOP_DESTROY,(void (*)(void))PCBDDCDestroyFETIDPMat);CHKERRQ(ierr);
22353425bc38SStefano Zampini   ierr = MatSetUp(newmat);CHKERRQ(ierr);
22363425bc38SStefano Zampini   /* FETIDP preconditioner */
22373425bc38SStefano Zampini   ierr = PCBDDCCreateFETIDPPCContext(pc,&fetidppc_ctx);CHKERRQ(ierr);
22383425bc38SStefano Zampini   ierr = PCBDDCSetupFETIDPPCContext(newmat,fetidppc_ctx);CHKERRQ(ierr);
22393425bc38SStefano Zampini   ierr = PCCreate(comm,&newpc);CHKERRQ(ierr);
22403425bc38SStefano Zampini   ierr = PCSetType(newpc,PCSHELL);CHKERRQ(ierr);
22413425bc38SStefano Zampini   ierr = PCShellSetContext(newpc,fetidppc_ctx);CHKERRQ(ierr);
22423425bc38SStefano Zampini   ierr = PCShellSetApply(newpc,FETIDPPCApply);CHKERRQ(ierr);
2243edf7251bSStefano Zampini   ierr = PCShellSetApplyTranspose(newpc,FETIDPPCApplyTranspose);CHKERRQ(ierr);
22443425bc38SStefano Zampini   ierr = PCShellSetDestroy(newpc,PCBDDCDestroyFETIDPPC);CHKERRQ(ierr);
224523ee1639SBarry Smith   ierr = PCSetOperators(newpc,newmat,newmat);CHKERRQ(ierr);
22463425bc38SStefano Zampini   ierr = PCSetUp(newpc);CHKERRQ(ierr);
22473425bc38SStefano Zampini   /* return pointers for objects created */
22483425bc38SStefano Zampini   *fetidp_mat=newmat;
22493425bc38SStefano Zampini   *fetidp_pc=newpc;
22503425bc38SStefano Zampini   PetscFunctionReturn(0);
22513425bc38SStefano Zampini }
22521e6b0712SBarry Smith 
22533425bc38SStefano Zampini #undef __FUNCT__
22543425bc38SStefano Zampini #define __FUNCT__ "PCBDDCCreateFETIDPOperators"
22553425bc38SStefano Zampini /*@
22560f202f7eSStefano Zampini  PCBDDCCreateFETIDPOperators - Create FETI-DP operators
22573425bc38SStefano Zampini 
22583425bc38SStefano Zampini    Collective
22593425bc38SStefano Zampini 
22603425bc38SStefano Zampini    Input Parameters:
22610f202f7eSStefano Zampini .  pc - the BDDC preconditioning context (setup should have been called before)
226228509bceSStefano Zampini 
226328509bceSStefano Zampini    Output Parameters:
22640f202f7eSStefano Zampini +  fetidp_mat - shell FETI-DP matrix object
22650f202f7eSStefano Zampini -  fetidp_pc  - shell Dirichlet preconditioner for FETI-DP matrix
226628509bceSStefano Zampini 
226728509bceSStefano Zampini    Options Database Keys:
22680f202f7eSStefano Zampini .    -fetidp_fullyredundant <false> - use or not a fully redundant set of Lagrange multipliers
22693425bc38SStefano Zampini 
22703425bc38SStefano Zampini    Level: developer
22713425bc38SStefano Zampini 
22723425bc38SStefano Zampini    Notes:
22730f202f7eSStefano Zampini      Currently the only operations provided for FETI-DP matrix are MatMult and MatMultTranspose
22743425bc38SStefano Zampini 
22750f202f7eSStefano Zampini .seealso: PCBDDC, PCBDDCMatFETIDPGetRHS, PCBDDCMatFETIDPGetSolution
22763425bc38SStefano Zampini @*/
22773425bc38SStefano Zampini PetscErrorCode PCBDDCCreateFETIDPOperators(PC pc, Mat *fetidp_mat, PC *fetidp_pc)
22783425bc38SStefano Zampini {
22793425bc38SStefano Zampini   PetscErrorCode ierr;
22803425bc38SStefano Zampini 
22813425bc38SStefano Zampini   PetscFunctionBegin;
22823425bc38SStefano Zampini   PetscValidHeaderSpecific(pc,PC_CLASSID,1);
22833425bc38SStefano Zampini   if (pc->setupcalled) {
2284516d51a7SStefano Zampini     ierr = PetscUseMethod(pc,"PCBDDCCreateFETIDPOperators_C",(PC,Mat*,PC*),(pc,fetidp_mat,fetidp_pc));CHKERRQ(ierr);
2285f23aa3ddSBarry Smith   } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"You must call PCSetup_BDDC() first \n");
22863425bc38SStefano Zampini   PetscFunctionReturn(0);
22873425bc38SStefano Zampini }
22880c7d97c5SJed Brown /* -------------------------------------------------------------------------- */
2289da1bb401SStefano Zampini /*MC
2290da1bb401SStefano Zampini    PCBDDC - Balancing Domain Decomposition by Constraints.
22910c7d97c5SJed Brown 
229228509bceSStefano Zampini    An implementation of the BDDC preconditioner based on
229328509bceSStefano Zampini 
229428509bceSStefano Zampini .vb
229528509bceSStefano Zampini    [1] C. R. Dohrmann. "An approximate BDDC preconditioner", Numerical Linear Algebra with Applications Volume 14, Issue 2, pages 149-168, March 2007
229628509bceSStefano 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
229728509bceSStefano Zampini    [3] J. Mandel, B. Sousedik, C. R. Dohrmann. "Multispace and Multilevel BDDC", http://arxiv.org/abs/0712.3977
22980f202f7eSStefano 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
229928509bceSStefano Zampini .ve
230028509bceSStefano Zampini 
230128509bceSStefano Zampini    The matrix to be preconditioned (Pmat) must be of type MATIS.
230228509bceSStefano Zampini 
23030f202f7eSStefano Zampini    Currently works with MATIS matrices with local matrices of type MATSEQAIJ, MATSEQBAIJ or MATSEQSBAIJ, either with real or complex numbers.
230428509bceSStefano Zampini 
230528509bceSStefano Zampini    It also works with unsymmetric and indefinite problems.
230628509bceSStefano Zampini 
2307b6fdb6dfSStefano 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.
2308b6fdb6dfSStefano Zampini 
23090f202f7eSStefano Zampini    Approximate local solvers are automatically adapted for singular linear problems (see [1]) if the user has provided the nullspace using PCBDDCSetNullSpace()
231028509bceSStefano Zampini 
23110f202f7eSStefano 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()
231230368db7SStefano Zampini    Additional information on dofs can be provided by using PCBDDCSetDofsSplitting(), PCBDDCSetDirichletBoundaries(), PCBDDCSetNeumannBoundaries(), and PCBDDCSetPrimalVerticesIS() and their local counterparts.
231328509bceSStefano Zampini 
23140f202f7eSStefano Zampini    Constraints can be customized by attaching a MatNullSpace object to the MATIS matrix via MatSetNearNullSpace(). Non-singular modes are retained via SVD.
231528509bceSStefano Zampini 
23160f202f7eSStefano 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.
23170f202f7eSStefano Zampini    User defined change of basis can be passed to PCBDDC by using PCBDDCSetChangeOfBasisMat()
231828509bceSStefano Zampini 
23190f202f7eSStefano Zampini    The PETSc implementation also supports multilevel BDDC [3]. Coarse grids are partitioned using a MatPartitioning object.
232028509bceSStefano Zampini 
2321df4d28bfSStefano 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.
232228509bceSStefano Zampini 
23230f202f7eSStefano 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.
23240f202f7eSStefano Zampini    Deluxe scaling is not supported yet for FETI-DP.
23250f202f7eSStefano Zampini 
23260f202f7eSStefano Zampini    Options Database Keys (some of them, run with -h for a complete list):
23270f202f7eSStefano Zampini 
23280f202f7eSStefano Zampini .    -pc_bddc_use_vertices <true> - use or not vertices in primal space
23290f202f7eSStefano Zampini .    -pc_bddc_use_edges <true> - use or not edges in primal space
23300f202f7eSStefano Zampini .    -pc_bddc_use_faces <false> - use or not faces in primal space
23310f202f7eSStefano Zampini .    -pc_bddc_symmetric <true> - symmetric computation of primal basis functions. Specify false for unsymmetric problems
23320f202f7eSStefano Zampini .    -pc_bddc_use_change_of_basis <false> - use change of basis approach (on edges only)
23330f202f7eSStefano Zampini .    -pc_bddc_use_change_on_faces <false> - use change of basis approach on faces if change of basis has been requested
23340f202f7eSStefano Zampini .    -pc_bddc_switch_static <false> - switches from M_2 (default) to M_3 operator (see reference article [1])
233528509bceSStefano Zampini .    -pc_bddc_levels <0> - maximum number of levels for multilevel
23360f202f7eSStefano 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)
23370f202f7eSStefano 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)
23380f202f7eSStefano Zampini .    -pc_bddc_use_deluxe_scaling <false> - use deluxe scaling
23390f202f7eSStefano 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)
2340df4d28bfSStefano 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)
234128509bceSStefano Zampini -    -pc_bddc_check_level <0> - set verbosity level of debugging output
234228509bceSStefano Zampini 
234328509bceSStefano Zampini    Options for Dirichlet, Neumann or coarse solver can be set with
234428509bceSStefano Zampini .vb
234528509bceSStefano Zampini       -pc_bddc_dirichlet_
234628509bceSStefano Zampini       -pc_bddc_neumann_
234728509bceSStefano Zampini       -pc_bddc_coarse_
234828509bceSStefano Zampini .ve
23490f202f7eSStefano Zampini    e.g -pc_bddc_dirichlet_ksp_type richardson -pc_bddc_dirichlet_pc_type gamg. PCBDDC uses by default KPSPREONLY and PCLU.
235028509bceSStefano Zampini 
23510f202f7eSStefano Zampini    When using a multilevel approach, solvers' options at the N-th level (N > 1) can be specified as
235228509bceSStefano Zampini .vb
2353312be037SStefano Zampini       -pc_bddc_dirichlet_lN_
2354312be037SStefano Zampini       -pc_bddc_neumann_lN_
2355312be037SStefano Zampini       -pc_bddc_coarse_lN_
235628509bceSStefano Zampini .ve
23570f202f7eSStefano Zampini    Note that level number ranges from the finest (0) to the coarsest (N).
23580f202f7eSStefano 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.
23590f202f7eSStefano Zampini .vb
23600f202f7eSStefano Zampini      -pc_bddc_coarse_pc_bddc_adaptive_threshold 5 -pc_bddc_coarse_l1_pc_bddc_redistribute 3
23610f202f7eSStefano Zampini .ve
23620f202f7eSStefano 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
2363da1bb401SStefano Zampini 
2364da1bb401SStefano Zampini    Level: intermediate
2365da1bb401SStefano Zampini 
2366b6fdb6dfSStefano Zampini    Developer notes:
2367da1bb401SStefano Zampini 
2368da1bb401SStefano Zampini    Contributed by Stefano Zampini
2369da1bb401SStefano Zampini 
2370da1bb401SStefano Zampini .seealso:  PCCreate(), PCSetType(), PCType (for list of available types), PC,  MATIS
2371da1bb401SStefano Zampini M*/
2372b2573a8aSBarry Smith 
2373da1bb401SStefano Zampini #undef __FUNCT__
2374da1bb401SStefano Zampini #define __FUNCT__ "PCCreate_BDDC"
23758cc058d9SJed Brown PETSC_EXTERN PetscErrorCode PCCreate_BDDC(PC pc)
2376da1bb401SStefano Zampini {
2377da1bb401SStefano Zampini   PetscErrorCode      ierr;
2378da1bb401SStefano Zampini   PC_BDDC             *pcbddc;
2379da1bb401SStefano Zampini 
2380da1bb401SStefano Zampini   PetscFunctionBegin;
2381da1bb401SStefano Zampini   /* Creates the private data structure for this preconditioner and attach it to the PC object. */
2382b00a9115SJed Brown   ierr      = PetscNewLog(pc,&pcbddc);CHKERRQ(ierr);
2383da1bb401SStefano Zampini   pc->data  = (void*)pcbddc;
2384da1bb401SStefano Zampini 
2385da1bb401SStefano Zampini   /* create PCIS data structure */
2386da1bb401SStefano Zampini   ierr = PCISCreate(pc);CHKERRQ(ierr);
2387da1bb401SStefano Zampini 
238847d04d0dSStefano Zampini   /* BDDC customization */
238908a5cf49SStefano Zampini   pcbddc->use_local_adj       = PETSC_TRUE;
239047d04d0dSStefano Zampini   pcbddc->use_vertices        = PETSC_TRUE;
239147d04d0dSStefano Zampini   pcbddc->use_edges           = PETSC_TRUE;
239247d04d0dSStefano Zampini   pcbddc->use_faces           = PETSC_FALSE;
239347d04d0dSStefano Zampini   pcbddc->use_change_of_basis = PETSC_FALSE;
239447d04d0dSStefano Zampini   pcbddc->use_change_on_faces = PETSC_FALSE;
239547d04d0dSStefano Zampini   pcbddc->switch_static       = PETSC_FALSE;
2396fa434743SStefano Zampini   pcbddc->use_nnsp_true       = PETSC_FALSE;
2397fa434743SStefano Zampini   pcbddc->use_qr_single       = PETSC_FALSE;
23983301b35fSStefano Zampini   pcbddc->symmetric_primal    = PETSC_TRUE;
239906a4e24aSStefano Zampini   pcbddc->benign_saddle_point = PETSC_FALSE;
240027b6a85dSStefano Zampini   pcbddc->benign_have_null    = PETSC_FALSE;
240114f95afaSStefano Zampini   pcbddc->vertex_size         = 1;
240247d04d0dSStefano Zampini   pcbddc->dbg_flag            = 0;
2403b9d89cd5SStefano Zampini   /* private */
2404727cdba6SStefano Zampini   pcbddc->local_primal_size          = 0;
24050e6343abSStefano Zampini   pcbddc->local_primal_size_cc       = 0;
24060e6343abSStefano Zampini   pcbddc->local_primal_ref_node      = 0;
24070e6343abSStefano Zampini   pcbddc->local_primal_ref_mult      = 0;
2408e9189074SStefano Zampini   pcbddc->n_vertices                 = 0;
2409727cdba6SStefano Zampini   pcbddc->primal_indices_local_idxs  = 0;
2410fb180af4SStefano Zampini   pcbddc->recompute_topography       = PETSC_FALSE;
241168457ee5SStefano Zampini   pcbddc->coarse_size                = -1;
2412f4ddd8eeSStefano Zampini   pcbddc->new_primal_space           = PETSC_FALSE;
2413727cdba6SStefano Zampini   pcbddc->new_primal_space_local     = PETSC_FALSE;
2414f4ddd8eeSStefano Zampini   pcbddc->global_primal_indices      = 0;
2415f4ddd8eeSStefano Zampini   pcbddc->onearnullspace             = 0;
2416f4ddd8eeSStefano Zampini   pcbddc->onearnullvecs_state        = 0;
2417674ae819SStefano Zampini   pcbddc->user_primal_vertices       = 0;
241830368db7SStefano Zampini   pcbddc->user_primal_vertices_local = 0;
24190bdf917eSStefano Zampini   pcbddc->NullSpace                  = 0;
24203972b0daSStefano Zampini   pcbddc->temp_solution              = 0;
2421534831adSStefano Zampini   pcbddc->original_rhs               = 0;
2422534831adSStefano Zampini   pcbddc->local_mat                  = 0;
2423534831adSStefano Zampini   pcbddc->ChangeOfBasisMatrix        = 0;
2424b9b85e73SStefano Zampini   pcbddc->user_ChangeOfBasisMatrix   = 0;
2425da1bb401SStefano Zampini   pcbddc->coarse_vec                 = 0;
2426da1bb401SStefano Zampini   pcbddc->coarse_ksp                 = 0;
2427da1bb401SStefano Zampini   pcbddc->coarse_phi_B               = 0;
2428da1bb401SStefano Zampini   pcbddc->coarse_phi_D               = 0;
242915aaf578SStefano Zampini   pcbddc->coarse_psi_B               = 0;
243015aaf578SStefano Zampini   pcbddc->coarse_psi_D               = 0;
2431da1bb401SStefano Zampini   pcbddc->vec1_P                     = 0;
2432da1bb401SStefano Zampini   pcbddc->vec1_R                     = 0;
2433da1bb401SStefano Zampini   pcbddc->vec2_R                     = 0;
2434da1bb401SStefano Zampini   pcbddc->local_auxmat1              = 0;
2435da1bb401SStefano Zampini   pcbddc->local_auxmat2              = 0;
2436da1bb401SStefano Zampini   pcbddc->R_to_B                     = 0;
2437da1bb401SStefano Zampini   pcbddc->R_to_D                     = 0;
2438da1bb401SStefano Zampini   pcbddc->ksp_D                      = 0;
2439da1bb401SStefano Zampini   pcbddc->ksp_R                      = 0;
2440da1bb401SStefano Zampini   pcbddc->NeumannBoundaries          = 0;
2441785d1243SStefano Zampini   pcbddc->NeumannBoundariesLocal     = 0;
2442785d1243SStefano Zampini   pcbddc->DirichletBoundaries        = 0;
2443785d1243SStefano Zampini   pcbddc->DirichletBoundariesLocal   = 0;
244460d44989SStefano Zampini   pcbddc->user_provided_isfordofs    = PETSC_FALSE;
244560d44989SStefano Zampini   pcbddc->n_ISForDofs                = 0;
244663602bcaSStefano Zampini   pcbddc->n_ISForDofsLocal           = 0;
2447da1bb401SStefano Zampini   pcbddc->ISForDofs                  = 0;
244863602bcaSStefano Zampini   pcbddc->ISForDofsLocal             = 0;
2449da1bb401SStefano Zampini   pcbddc->ConstraintMatrix           = 0;
245085c4d303SStefano Zampini   pcbddc->use_exact_dirichlet_trick  = PETSC_TRUE;
245147d04d0dSStefano Zampini   pcbddc->coarse_loc_to_glob         = 0;
245247d04d0dSStefano Zampini   pcbddc->coarsening_ratio           = 8;
2453b0c7d250SStefano Zampini   pcbddc->coarse_adj_red             = 0;
24544fad6a16SStefano Zampini   pcbddc->current_level              = 0;
24552b510759SStefano Zampini   pcbddc->max_levels                 = 0;
2456323d395dSStefano Zampini   pcbddc->use_coarse_estimates       = PETSC_FALSE;
245757de7509SStefano Zampini   pcbddc->coarse_eqs_per_proc        = 1;
2458f3bde8b3SStefano Zampini   pcbddc->coarse_subassembling       = 0;
24594f1b2e48SStefano Zampini   pcbddc->detect_disconnected        = PETSC_FALSE;
24604f1b2e48SStefano Zampini   pcbddc->n_local_subs               = 0;
24614f1b2e48SStefano Zampini   pcbddc->local_subs                 = NULL;
246281d14e9dSStefano Zampini 
246381d14e9dSStefano Zampini   /* benign subspace trick */
246481d14e9dSStefano Zampini   pcbddc->benign_change              = 0;
246527b6a85dSStefano Zampini   pcbddc->benign_compute_correction  = PETSC_TRUE;
24660369aaf7SStefano Zampini   pcbddc->benign_vec                 = 0;
24670369aaf7SStefano Zampini   pcbddc->benign_original_mat        = 0;
24680369aaf7SStefano Zampini   pcbddc->benign_sf                  = 0;
24694f1b2e48SStefano Zampini   pcbddc->benign_B0                  = 0;
24704f1b2e48SStefano Zampini   pcbddc->benign_n                   = 0;
24714f1b2e48SStefano Zampini   pcbddc->benign_p0                  = NULL;
24724f1b2e48SStefano Zampini   pcbddc->benign_p0_lidx             = NULL;
24734f1b2e48SStefano Zampini   pcbddc->benign_p0_gidx             = NULL;
2474b0f5fe93SStefano Zampini   pcbddc->benign_null                = PETSC_FALSE;
247581d14e9dSStefano Zampini 
2476674ae819SStefano Zampini   /* create local graph structure */
2477674ae819SStefano Zampini   ierr = PCBDDCGraphCreate(&pcbddc->mat_graph);CHKERRQ(ierr);
2478674ae819SStefano Zampini 
2479674ae819SStefano Zampini   /* scaling */
2480674ae819SStefano Zampini   pcbddc->work_scaling          = 0;
248134a97f8cSStefano Zampini   pcbddc->use_deluxe_scaling    = PETSC_FALSE;
2482b96c3477SStefano Zampini 
2483b96c3477SStefano Zampini   /* create sub schurs structure */
2484b96c3477SStefano Zampini   ierr = PCBDDCSubSchursCreate(&pcbddc->sub_schurs);CHKERRQ(ierr);
2485b96c3477SStefano Zampini   pcbddc->sub_schurs_rebuild     = PETSC_FALSE;
2486b96c3477SStefano Zampini   pcbddc->sub_schurs_layers      = -1;
2487b96c3477SStefano Zampini   pcbddc->sub_schurs_use_useradj = PETSC_FALSE;
2488b96c3477SStefano Zampini 
2489b96c3477SStefano Zampini   pcbddc->computed_rowadj = PETSC_FALSE;
2490da1bb401SStefano Zampini 
2491b7eb3628SStefano Zampini   /* adaptivity */
2492f6f667cfSStefano Zampini   pcbddc->adaptive_threshold      = 0.0;
249308122e43SStefano Zampini   pcbddc->adaptive_nmax           = 0;
2494f6f667cfSStefano Zampini   pcbddc->adaptive_nmin           = 0;
2495b7eb3628SStefano Zampini 
2496da1bb401SStefano Zampini   /* function pointers */
2497da1bb401SStefano Zampini   pc->ops->apply               = PCApply_BDDC;
249893bd9ae7SStefano Zampini   pc->ops->applytranspose      = PCApplyTranspose_BDDC;
2499da1bb401SStefano Zampini   pc->ops->setup               = PCSetUp_BDDC;
2500da1bb401SStefano Zampini   pc->ops->destroy             = PCDestroy_BDDC;
2501da1bb401SStefano Zampini   pc->ops->setfromoptions      = PCSetFromOptions_BDDC;
25026b78500eSPatrick Sanan   pc->ops->view                = PCView_BDDC;
2503da1bb401SStefano Zampini   pc->ops->applyrichardson     = 0;
2504da1bb401SStefano Zampini   pc->ops->applysymmetricleft  = 0;
2505da1bb401SStefano Zampini   pc->ops->applysymmetricright = 0;
2506534831adSStefano Zampini   pc->ops->presolve            = PCPreSolve_BDDC;
2507534831adSStefano Zampini   pc->ops->postsolve           = PCPostSolve_BDDC;
2508da1bb401SStefano Zampini 
2509da1bb401SStefano Zampini   /* composing function */
2510906d46d4SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetChangeOfBasisMat_C",PCBDDCSetChangeOfBasisMat_BDDC);CHKERRQ(ierr);
2511674ae819SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesLocalIS_C",PCBDDCSetPrimalVerticesLocalIS_BDDC);CHKERRQ(ierr);
251230368db7SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetPrimalVerticesIS_C",PCBDDCSetPrimalVerticesIS_BDDC);CHKERRQ(ierr);
2513bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetCoarseningRatio_C",PCBDDCSetCoarseningRatio_BDDC);CHKERRQ(ierr);
25142b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevel_C",PCBDDCSetLevel_BDDC);CHKERRQ(ierr);
2515b8ffe317SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetUseExactDirichlet_C",PCBDDCSetUseExactDirichlet_BDDC);CHKERRQ(ierr);
25162b510759SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLevels_C",PCBDDCSetLevels_BDDC);CHKERRQ(ierr);
2517bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNullSpace_C",PCBDDCSetNullSpace_BDDC);CHKERRQ(ierr);
2518bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundaries_C",PCBDDCSetDirichletBoundaries_BDDC);CHKERRQ(ierr);
251982ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDirichletBoundariesLocal_C",PCBDDCSetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
2520bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundaries_C",PCBDDCSetNeumannBoundaries_BDDC);CHKERRQ(ierr);
252182ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetNeumannBoundariesLocal_C",PCBDDCSetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
2522bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundaries_C",PCBDDCGetDirichletBoundaries_BDDC);CHKERRQ(ierr);
252382ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetDirichletBoundariesLocal_C",PCBDDCGetDirichletBoundariesLocal_BDDC);CHKERRQ(ierr);
2524bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundaries_C",PCBDDCGetNeumannBoundaries_BDDC);CHKERRQ(ierr);
252582ba6b80SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCGetNeumannBoundariesLocal_C",PCBDDCGetNeumannBoundariesLocal_BDDC);CHKERRQ(ierr);
2526bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplitting_C",PCBDDCSetDofsSplitting_BDDC);CHKERRQ(ierr);
252763602bcaSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetDofsSplittingLocal_C",PCBDDCSetDofsSplittingLocal_BDDC);CHKERRQ(ierr);
2528bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCSetLocalAdjacencyGraph_C",PCBDDCSetLocalAdjacencyGraph_BDDC);CHKERRQ(ierr);
2529bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCCreateFETIDPOperators_C",PCBDDCCreateFETIDPOperators_BDDC);CHKERRQ(ierr);
2530bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetRHS_C",PCBDDCMatFETIDPGetRHS_BDDC);CHKERRQ(ierr);
2531bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)pc,"PCBDDCMatFETIDPGetSolution_C",PCBDDCMatFETIDPGetSolution_BDDC);CHKERRQ(ierr);
2532da1bb401SStefano Zampini   PetscFunctionReturn(0);
2533da1bb401SStefano Zampini }
25343425bc38SStefano Zampini 
2535