PETSC_EXTERN void PETSC_STDCALL pcbddcsetnullspace_(PC pc,MatNullSpace NullSpace, int *__ierr ){ *__ierr = PCBDDCSetNullSpace( (PC)PetscToPointer((pc) ), (MatNullSpace)PetscToPointer((NullSpace) )); }
PetscErrorCode PCBDDCNullSpaceAdaptGlobal(PC pc) { PC_IS* pcis = (PC_IS*)(pc->data); PC_BDDC* pcbddc = (PC_BDDC*)(pc->data); KSP inv_change; const Vec *nsp_vecs; Vec *new_nsp_vecs; PetscInt i,nsp_size,new_nsp_size,start_new; PetscBool nsp_has_cnst; MatNullSpace new_nsp; PetscErrorCode ierr; PetscFunctionBegin; /* create KSP for change of basis */ ierr = MatGetSize(pcbddc->ChangeOfBasisMatrix,&i,NULL);CHKERRQ(ierr); ierr = KSPCreate(PetscObjectComm((PetscObject)pc),&inv_change);CHKERRQ(ierr); ierr = KSPSetErrorIfNotConverged(inv_change,pc->erroriffailure);CHKERRQ(ierr); ierr = KSPSetOperators(inv_change,pcbddc->ChangeOfBasisMatrix,pcbddc->ChangeOfBasisMatrix);CHKERRQ(ierr); ierr = KSPSetTolerances(inv_change,1.e-8,1.e-8,PETSC_DEFAULT,2*i);CHKERRQ(ierr); if (pcbddc->dbg_flag) { ierr = KSPMonitorSet(inv_change,KSPMonitorDefault,pcbddc->dbg_viewer,NULL);CHKERRQ(ierr); } ierr = KSPSetUp(inv_change);CHKERRQ(ierr); /* get nullspace and transform it */ ierr = MatNullSpaceGetVecs(pcbddc->NullSpace,&nsp_has_cnst,&nsp_size,&nsp_vecs);CHKERRQ(ierr); new_nsp_size = nsp_size; if (nsp_has_cnst) { new_nsp_size++; } ierr = VecDuplicateVecs(pcis->vec1_global,new_nsp_size,&new_nsp_vecs);CHKERRQ(ierr); start_new = 0; if (nsp_has_cnst) { start_new = 1; ierr = VecSet(new_nsp_vecs[0],1.0);CHKERRQ(ierr); if (pcbddc->dbg_flag) { ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Mapping constant in nullspace\n");CHKERRQ(ierr); } ierr = KSPSolve(inv_change,new_nsp_vecs[0],new_nsp_vecs[0]);CHKERRQ(ierr); } for (i=0;i<nsp_size;i++) { ierr = PetscViewerFlush(pcbddc->dbg_viewer);CHKERRQ(ierr); ierr = PetscViewerASCIIPrintf(pcbddc->dbg_viewer,"Mapping %dth vector in nullspace\n",i);CHKERRQ(ierr); ierr = KSPSolve(inv_change,nsp_vecs[i],new_nsp_vecs[i+start_new]);CHKERRQ(ierr); } ierr = PCBDDCOrthonormalizeVecs(new_nsp_size,new_nsp_vecs);CHKERRQ(ierr); ierr = MatNullSpaceCreate(PetscObjectComm((PetscObject)pc),PETSC_FALSE,new_nsp_size,new_nsp_vecs,&new_nsp);CHKERRQ(ierr); ierr = PCBDDCSetNullSpace(pc,new_nsp);CHKERRQ(ierr); /* free */ ierr = KSPDestroy(&inv_change);CHKERRQ(ierr); ierr = MatNullSpaceDestroy(&new_nsp);CHKERRQ(ierr); ierr = VecDestroyVecs(new_nsp_size,&new_nsp_vecs);CHKERRQ(ierr); /* check */ if (pcbddc->dbg_flag) { PetscBool nsp_t=PETSC_FALSE; Mat temp_mat; Mat_IS* matis = (Mat_IS*)pc->pmat->data; temp_mat = matis->A; matis->A = pcbddc->local_mat; pcbddc->local_mat = temp_mat; ierr = MatNullSpaceTest(pcbddc->NullSpace,pc->pmat,&nsp_t);CHKERRQ(ierr); ierr = PetscPrintf(PetscObjectComm((PetscObject)(pc->pmat)),"Check nullspace with change of basis: %d\n",nsp_t);CHKERRQ(ierr); temp_mat = matis->A; matis->A = pcbddc->local_mat; pcbddc->local_mat = temp_mat; } PetscFunctionReturn(0); }
PetscErrorCode PCBDDCNullSpaceAdaptGlobal(PC pc) { PC_IS* pcis = (PC_IS*) (pc->data); PC_BDDC* pcbddc = (PC_BDDC*)(pc->data); KSP inv_change; PC pc_change; const Vec *nsp_vecs; Vec *new_nsp_vecs; PetscInt i,nsp_size,new_nsp_size,start_new; PetscBool nsp_has_cnst; MatNullSpace new_nsp; PetscErrorCode ierr; MPI_Comm comm; PetscFunctionBegin; /* create KSP for change of basis */ ierr = KSPCreate(PETSC_COMM_SELF,&inv_change);CHKERRQ(ierr); ierr = KSPSetOperators(inv_change,pcbddc->ChangeOfBasisMatrix,pcbddc->ChangeOfBasisMatrix,SAME_PRECONDITIONER);CHKERRQ(ierr); ierr = KSPSetType(inv_change,KSPPREONLY);CHKERRQ(ierr); ierr = KSPGetPC(inv_change,&pc_change);CHKERRQ(ierr); ierr = PCSetType(pc_change,PCLU);CHKERRQ(ierr); ierr = KSPSetUp(inv_change);CHKERRQ(ierr); /* get nullspace and transform it */ ierr = MatNullSpaceGetVecs(pcbddc->NullSpace,&nsp_has_cnst,&nsp_size,&nsp_vecs);CHKERRQ(ierr); new_nsp_size = nsp_size; if (nsp_has_cnst) { new_nsp_size++; } ierr = PetscMalloc(new_nsp_size*sizeof(Vec),&new_nsp_vecs);CHKERRQ(ierr); for (i=0;i<new_nsp_size;i++) { ierr = VecDuplicate(pcis->vec1_global,&new_nsp_vecs[i]);CHKERRQ(ierr); } start_new = 0; if (nsp_has_cnst) { start_new = 1; ierr = VecSet(new_nsp_vecs[0],1.0);CHKERRQ(ierr); ierr = VecSet(pcis->vec1_B,1.0);CHKERRQ(ierr); ierr = KSPSolve(inv_change,pcis->vec1_B,pcis->vec1_B); ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,new_nsp_vecs[0],INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); ierr = VecScatterEnd (pcis->global_to_B,pcis->vec1_B,new_nsp_vecs[0],INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); } for (i=0;i<nsp_size;i++) { ierr = VecCopy(nsp_vecs[i],new_nsp_vecs[i+start_new]);CHKERRQ(ierr); ierr = VecScatterBegin(pcis->global_to_B,nsp_vecs[i],pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = VecScatterEnd (pcis->global_to_B,nsp_vecs[i],pcis->vec1_B,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr); ierr = KSPSolve(inv_change,pcis->vec1_B,pcis->vec1_B); ierr = VecScatterBegin(pcis->global_to_B,pcis->vec1_B,new_nsp_vecs[i+start_new],INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); ierr = VecScatterEnd (pcis->global_to_B,pcis->vec1_B,new_nsp_vecs[i+start_new],INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr); } ierr = PCBDDCOrthonormalizeVecs(new_nsp_size,new_nsp_vecs);CHKERRQ(ierr); #if 0 PetscBool nsp_t=PETSC_FALSE; ierr = MatNullSpaceTest(pcbddc->NullSpace,pc->pmat,&nsp_t);CHKERRQ(ierr); printf("Original Null Space test: %d\n",nsp_t); Mat temp_mat; Mat_IS* matis = (Mat_IS*)pc->pmat->data; temp_mat = matis->A; matis->A = pcbddc->local_mat; pcbddc->local_mat = temp_mat; ierr = MatNullSpaceTest(pcbddc->NullSpace,pc->pmat,&nsp_t);CHKERRQ(ierr); printf("Original Null Space, mat changed test: %d\n",nsp_t); { PetscReal test_norm; for (i=0;i<new_nsp_size;i++) { ierr = MatMult(pc->pmat,new_nsp_vecs[i],pcis->vec1_global);CHKERRQ(ierr); ierr = VecNorm(pcis->vec1_global,NORM_2,&test_norm);CHKERRQ(ierr); if (test_norm > 1.e-12) { printf("------------ERROR VEC %d------------------\n",i); ierr = VecView(pcis->vec1_global,PETSC_VIEWER_STDOUT_WORLD); printf("------------------------------------------\n"); } } } #endif ierr = KSPDestroy(&inv_change);CHKERRQ(ierr); ierr = PetscObjectGetComm((PetscObject)pc,&comm);CHKERRQ(ierr); ierr = MatNullSpaceCreate(comm,PETSC_FALSE,new_nsp_size,new_nsp_vecs,&new_nsp);CHKERRQ(ierr); ierr = PCBDDCSetNullSpace(pc,new_nsp);CHKERRQ(ierr); ierr = MatNullSpaceDestroy(&new_nsp);CHKERRQ(ierr); #if 0 ierr = MatNullSpaceTest(pcbddc->NullSpace,pc->pmat,&nsp_t);CHKERRQ(ierr); printf("New Null Space, mat changed: %d\n",nsp_t); temp_mat = matis->A; matis->A = pcbddc->local_mat; pcbddc->local_mat = temp_mat; ierr = MatNullSpaceTest(pcbddc->NullSpace,pc->pmat,&nsp_t);CHKERRQ(ierr); printf("New Null Space, mat original: %d\n",nsp_t); #endif for (i=0;i<new_nsp_size;i++) { ierr = VecDestroy(&new_nsp_vecs[i]);CHKERRQ(ierr); } ierr = PetscFree(new_nsp_vecs);CHKERRQ(ierr); PetscFunctionReturn(0); }