xref: /petsc/src/ksp/pc/impls/gamg/util.c (revision bae903cb6e5fe998dd743ea97ba6d0e4e52494ec)
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