16618991cSMark Adams /* 26618991cSMark Adams GAMG geometric-algebric multigrid PC - Mark Adams 2011 36618991cSMark Adams */ 46618991cSMark Adams #include <petsc/private/matimpl.h> 56618991cSMark Adams #include <../src/ksp/pc/impls/gamg/gamg.h> /*I "petscpc.h" I*/ 685cd6069SMark Adams #include <petsc/private/kspimpl.h> 76618991cSMark Adams 86618991cSMark Adams /* -------------------------------------------------------------------------- */ 96618991cSMark Adams /* 10*bae903cbSmarkadams4 PCGAMGGetDataWithGhosts - Get array of local + ghost data with local data 11*bae903cbSmarkadams4 hacks into Mat MPIAIJ so this must have size > 1 126618991cSMark Adams 136618991cSMark Adams Input Parameter: 14*bae903cbSmarkadams4 . Gmat - MPIAIJ matrix for scatters 156618991cSMark Adams . data_sz - number of data terms per node (# cols in output) 16*bae903cbSmarkadams4 . data_in[nloc*data_sz] - column oriented local data 17*bae903cbSmarkadams4 186618991cSMark Adams Output Parameter: 19*bae903cbSmarkadams4 . a_stride - number of rows of output (locals+ghosts) 206618991cSMark Adams . a_data_out[stride*data_sz] - output data with ghosts 21*bae903cbSmarkadams4 226618991cSMark Adams */ 236618991cSMark Adams PetscErrorCode PCGAMGGetDataWithGhosts(Mat Gmat,PetscInt data_sz,PetscReal data_in[],PetscInt *a_stride,PetscReal **a_data_out) 246618991cSMark Adams { 256618991cSMark Adams Vec tmp_crds; 266618991cSMark Adams Mat_MPIAIJ *mpimat = (Mat_MPIAIJ*)Gmat->data; 276618991cSMark Adams PetscInt nnodes,num_ghosts,dir,kk,jj,my0,Iend,nloc; 286618991cSMark Adams PetscScalar *data_arr; 296618991cSMark Adams PetscReal *datas; 306618991cSMark Adams PetscBool isMPIAIJ; 316618991cSMark Adams 326618991cSMark Adams PetscFunctionBegin; 339566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompare((PetscObject)Gmat, MATMPIAIJ, &isMPIAIJ)); 349566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(Gmat, &my0, &Iend)); 356618991cSMark Adams nloc = Iend - my0; 369566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(mpimat->lvec, &num_ghosts)); 376618991cSMark Adams nnodes = num_ghosts + nloc; 386618991cSMark Adams *a_stride = nnodes; 399566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(Gmat, &tmp_crds, NULL)); 406618991cSMark Adams 419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(data_sz*nnodes, &datas)); 426618991cSMark Adams for (dir=0; dir<data_sz; dir++) { 436618991cSMark Adams /* set local, and global */ 446618991cSMark Adams for (kk=0; kk<nloc; kk++) { 456618991cSMark Adams PetscInt gid = my0 + kk; 466618991cSMark Adams PetscScalar crd = (PetscScalar)data_in[dir*nloc + kk]; /* col oriented */ 47*bae903cbSmarkadams4 datas[dir*nnodes + kk] = PetscRealPart(crd); // get local part now 486618991cSMark Adams 499566063dSJacob Faibussowitsch PetscCall(VecSetValues(tmp_crds, 1, &gid, &crd, INSERT_VALUES)); 506618991cSMark Adams } 519566063dSJacob Faibussowitsch PetscCall(VecAssemblyBegin(tmp_crds)); 529566063dSJacob Faibussowitsch PetscCall(VecAssemblyEnd(tmp_crds)); 53*bae903cbSmarkadams4 /* scatter / gather ghost data and add to end of output data */ 549566063dSJacob Faibussowitsch PetscCall(VecScatterBegin(mpimat->Mvctx,tmp_crds,mpimat->lvec,INSERT_VALUES,SCATTER_FORWARD)); 559566063dSJacob Faibussowitsch PetscCall(VecScatterEnd(mpimat->Mvctx,tmp_crds,mpimat->lvec,INSERT_VALUES,SCATTER_FORWARD)); 569566063dSJacob Faibussowitsch PetscCall(VecGetArray(mpimat->lvec, &data_arr)); 576618991cSMark Adams for (kk=nloc,jj=0;jj<num_ghosts;kk++,jj++) datas[dir*nnodes + kk] = PetscRealPart(data_arr[jj]); 589566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(mpimat->lvec, &data_arr)); 596618991cSMark Adams } 609566063dSJacob Faibussowitsch PetscCall(VecDestroy(&tmp_crds)); 616618991cSMark Adams *a_data_out = datas; 626618991cSMark Adams PetscFunctionReturn(0); 636618991cSMark Adams } 646618991cSMark Adams 651943db53SBarry Smith PetscErrorCode PCGAMGHashTableCreate(PetscInt a_size, PCGAMGHashTable *a_tab) 666618991cSMark Adams { 676618991cSMark Adams PetscInt kk; 686618991cSMark Adams 696618991cSMark Adams PetscFunctionBegin; 706618991cSMark Adams a_tab->size = a_size; 719566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(a_size, &a_tab->table,a_size, &a_tab->data)); 726618991cSMark Adams for (kk=0; kk<a_size; kk++) a_tab->table[kk] = -1; 736618991cSMark Adams PetscFunctionReturn(0); 746618991cSMark Adams } 756618991cSMark Adams 761943db53SBarry Smith PetscErrorCode PCGAMGHashTableDestroy(PCGAMGHashTable *a_tab) 776618991cSMark Adams { 786618991cSMark Adams PetscFunctionBegin; 799566063dSJacob Faibussowitsch PetscCall(PetscFree2(a_tab->table,a_tab->data)); 806618991cSMark Adams PetscFunctionReturn(0); 816618991cSMark Adams } 826618991cSMark Adams 831943db53SBarry Smith PetscErrorCode PCGAMGHashTableAdd(PCGAMGHashTable *a_tab, PetscInt a_key, PetscInt a_data) 846618991cSMark Adams { 856618991cSMark Adams PetscInt kk,idx; 866618991cSMark Adams 876618991cSMark Adams PetscFunctionBegin; 8863a3b9bcSJacob Faibussowitsch PetscCheck(a_key>=0,PETSC_COMM_SELF,PETSC_ERR_USER,"Negative key %" PetscInt_FMT ".",a_key); 898f3cd775SBarry Smith for (kk = 0, idx = GAMG_HASH(a_key); kk < a_tab->size; kk++, idx = (idx==(a_tab->size-1)) ? 0 : idx + 1) { 906618991cSMark Adams if (a_tab->table[idx] == a_key) { 916618991cSMark Adams /* exists */ 926618991cSMark Adams a_tab->data[idx] = a_data; 936618991cSMark Adams break; 946618991cSMark Adams } else if (a_tab->table[idx] == -1) { 956618991cSMark Adams /* add */ 966618991cSMark Adams a_tab->table[idx] = a_key; 976618991cSMark Adams a_tab->data[idx] = a_data; 986618991cSMark Adams break; 996618991cSMark Adams } 1006618991cSMark Adams } 1016618991cSMark Adams if (kk==a_tab->size) { 1026618991cSMark Adams /* this is not to efficient, waiting until completely full */ 1036618991cSMark Adams PetscInt oldsize = a_tab->size, new_size = 2*a_tab->size + 5, *oldtable = a_tab->table, *olddata = a_tab->data; 1046618991cSMark Adams 1056618991cSMark Adams a_tab->size = new_size; 1069566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(a_tab->size, &a_tab->table,a_tab->size, &a_tab->data)); 1076618991cSMark Adams for (kk=0;kk<a_tab->size;kk++) a_tab->table[kk] = -1; 1086618991cSMark Adams for (kk=0;kk<oldsize;kk++) { 1096618991cSMark Adams if (oldtable[kk] != -1) { 1109566063dSJacob Faibussowitsch PetscCall(PCGAMGHashTableAdd(a_tab, oldtable[kk], olddata[kk])); 1116618991cSMark Adams } 1126618991cSMark Adams } 1139566063dSJacob Faibussowitsch PetscCall(PetscFree2(oldtable,olddata)); 1149566063dSJacob Faibussowitsch PetscCall(PCGAMGHashTableAdd(a_tab, a_key, a_data)); 1156618991cSMark Adams } 1166618991cSMark Adams PetscFunctionReturn(0); 1176618991cSMark Adams } 118