/*@C AOCreateBasicIS - Creates a basic application ordering using two index sets. Collective on IS Input Parameters: + isapp - index set that defines an ordering - ispetsc - index set that defines another ordering (may be NULL to use the natural ordering) Output Parameter: . aoout - the new application ordering Level: beginner Notes: the index sets isapp and ispetsc must contain the all the integers 0 to napp-1 (where napp is the length of the index sets) with no duplicates; that is there cannot be any "holes" .keywords: AO, create .seealso: AOCreateBasic(), AODestroy() @*/ PetscErrorCode AOCreateBasicIS(IS isapp,IS ispetsc,AO *aoout) { PetscErrorCode ierr; MPI_Comm comm; AO ao; PetscFunctionBegin; ierr = PetscObjectGetComm((PetscObject)isapp,&comm);CHKERRQ(ierr); ierr = AOCreate(comm,&ao);CHKERRQ(ierr); ierr = AOSetIS(ao,isapp,ispetsc);CHKERRQ(ierr); ierr = AOSetType(ao,AOBASIC);CHKERRQ(ierr); ierr = AOViewFromOptions(ao,NULL,"-ao_view");CHKERRQ(ierr); *aoout = ao; PetscFunctionReturn(0); }
/*@C AOCreateMapping - Creates a basic application mapping using two integer arrays. Input Parameters: + comm - MPI communicator that is to share AO . napp - size of integer arrays . myapp - integer array that defines an ordering - mypetsc - integer array that defines another ordering (may be NULL to indicate the identity ordering) Output Parameter: . aoout - the new application mapping Options Database Key: . -ao_view : call AOView() at the conclusion of AOCreateMapping() Level: beginner Notes: the arrays myapp and mypetsc need NOT contain the all the integers 0 to napp-1, that is there CAN be "holes" in the indices. Use AOCreateBasic() or AOCreateBasicIS() if they do not have holes for better performance. .keywords: AO, create .seealso: AOCreateBasic(), AOCreateBasic(), AOCreateMappingIS(), AODestroy() @*/ PetscErrorCode AOCreateMapping(MPI_Comm comm,PetscInt napp,const PetscInt myapp[],const PetscInt mypetsc[],AO *aoout) { AO ao; AO_Mapping *aomap; PetscInt *allpetsc, *allapp; PetscInt *petscPerm, *appPerm; PetscInt *petsc; PetscMPIInt size, rank,*lens, *disp,nnapp; PetscInt N, start; PetscInt i; PetscErrorCode ierr; PetscFunctionBegin; PetscValidPointer(aoout,5); *aoout = 0; ierr = AOInitializePackage();CHKERRQ(ierr); ierr = PetscHeaderCreate(ao, AO_CLASSID, "AO", "Application Ordering", "AO", comm, AODestroy, AOView);CHKERRQ(ierr); ierr = PetscNewLog(ao,&aomap);CHKERRQ(ierr); ierr = PetscMemcpy(ao->ops, &AOps, sizeof(AOps));CHKERRQ(ierr); ao->data = (void*) aomap; /* transmit all lengths to all processors */ ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); ierr = PetscMalloc2(size, &lens,size,&disp);CHKERRQ(ierr); nnapp = napp; ierr = MPI_Allgather(&nnapp, 1, MPI_INT, lens, 1, MPI_INT, comm);CHKERRQ(ierr); N = 0; for (i = 0; i < size; i++) { disp[i] = N; N += lens[i]; } aomap->N = N; ao->N = N; ao->n = N; /* If mypetsc is 0 then use "natural" numbering */ if (!mypetsc) { start = disp[rank]; ierr = PetscMalloc1(napp+1, &petsc);CHKERRQ(ierr); for (i = 0; i < napp; i++) petsc[i] = start + i; } else { petsc = (PetscInt*)mypetsc; } /* get all indices on all processors */ ierr = PetscMalloc4(N, &allapp,N,&appPerm,N,&allpetsc,N,&petscPerm);CHKERRQ(ierr); ierr = MPI_Allgatherv((void*)myapp, napp, MPIU_INT, allapp, lens, disp, MPIU_INT, comm);CHKERRQ(ierr); ierr = MPI_Allgatherv((void*)petsc, napp, MPIU_INT, allpetsc, lens, disp, MPIU_INT, comm);CHKERRQ(ierr); ierr = PetscFree2(lens,disp);CHKERRQ(ierr); /* generate a list of application and PETSc node numbers */ ierr = PetscMalloc4(N, &aomap->app,N,&aomap->appPerm,N,&aomap->petsc,N,&aomap->petscPerm);CHKERRQ(ierr); ierr = PetscLogObjectMemory((PetscObject)ao, 4*N * sizeof(PetscInt));CHKERRQ(ierr); for (i = 0; i < N; i++) { appPerm[i] = i; petscPerm[i] = i; } ierr = PetscSortIntWithPermutation(N, allpetsc, petscPerm);CHKERRQ(ierr); ierr = PetscSortIntWithPermutation(N, allapp, appPerm);CHKERRQ(ierr); /* Form sorted arrays of indices */ for (i = 0; i < N; i++) { aomap->app[i] = allapp[appPerm[i]]; aomap->petsc[i] = allpetsc[petscPerm[i]]; } /* Invert petscPerm[] into aomap->petscPerm[] */ for (i = 0; i < N; i++) aomap->petscPerm[petscPerm[i]] = i; /* Form map between aomap->app[] and aomap->petsc[] */ for (i = 0; i < N; i++) aomap->appPerm[i] = aomap->petscPerm[appPerm[i]]; /* Invert appPerm[] into allapp[] */ for (i = 0; i < N; i++) allapp[appPerm[i]] = i; /* Form map between aomap->petsc[] and aomap->app[] */ for (i = 0; i < N; i++) aomap->petscPerm[i] = allapp[petscPerm[i]]; #if defined(PETSC_USE_DEBUG) /* Check that the permutations are complementary */ for (i = 0; i < N; i++) { if (i != aomap->appPerm[aomap->petscPerm[i]]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB, "Invalid ordering"); } #endif /* Cleanup */ if (!mypetsc) { ierr = PetscFree(petsc);CHKERRQ(ierr); } ierr = PetscFree4(allapp,appPerm,allpetsc,petscPerm);CHKERRQ(ierr); ierr = AOViewFromOptions(ao,NULL,"-ao_view");CHKERRQ(ierr); *aoout = ao; PetscFunctionReturn(0); }