Delta::Delta(int _N, double _L, int _nover, double thresh, Mask3D& _mask) // RS 2010/07/06: Comments! { // Cache values N=_N; L=_L; nover=_nover; maskptr=&_mask; rmasksmooth = 0.0; // Set up the density // RS: dg2 is some kind of local variable; dg1 is a class member. // W and _W are contents of a grid of the same size and dimensions // as dg1 and dg2. DensityGrid dg2(N, L); dg1.Init(N, L); _W = dg1.Allocate(); W = dg1.Allocate(); VecSet(W, 0.0); // Now do the randoms // RS: "Doing" the randoms in this context means "oversampling" each grid // cell into subcells, where the main cell is nover times as large as each // subcell and hence there are nover^3 subcells to a cell. nrand=0.0; double nexp, nthresh; nexp = pow((double) nover, 3); // RS: thresh is the *fraction* of the main cell's volume to be included // inside the mask for it to be counted as not masked, so nthresh is the // corresponding number of subcells. nthresh = nexp*thresh; { double tmp = 1./nover, dx, dy, dz; VecSet(_W, 0.0); // Manually set to zero Vec W1; VecDuplicate(_W, &W1); // RS: Loop over all subcell *offsets*. The loop over actual grid cells // is implicit in the calls to methods like GridInitialize below. for (int ix = 0; ix < nover; ++ix) { PetscPrintf(PETSC_COMM_WORLD,"Starting random loop %i of %i....\n",ix,nover-1); dx = ix*tmp + tmp/2.0; for (int iy = 0; iy < nover; ++iy) { dy = iy*tmp + tmp/2.0; for (int iz = 0; iz < nover; ++iz) { dz = iz*tmp + tmp/2.0; Particle rr; // Definition here is important, since it ensures destruction, before recreating // RS: Generate a bunch of particles uniformly spaced, and offset // from the low-(x,y,z) corner of each grid cell by (dx,dy,dz). rr.GridInitialize(N, dx, dy, dz, L); // RS: Remove from the list any particles which were not allowed // by the mask. Add to the total. rr.TrimMask(*maskptr); nrand += rr.npart; // rr.SlabDecompose(dg2); We don't need to slab decompose because nproc divides N by construction // RS: CIC assign remaining particles to temporary grid vector W1. dg1.CIC(W1, rr, false); // No overdensity // RS: Now add to _W the CIC contents of W1. VecAXPY(_W, 1.0, W1); } } } } // RS: At this point, nrand equals the total number of oversampled subcells // found to be allowed by the masked region. _W contains the number of // particles allowed by an oversampled mask at each grid location. PetscPrintf(PETSC_COMM_WORLD, "%f grid particles accumulated....\n", nrand); // Now set the mask // RS: For each cell, if the contents of _W exceed nthresh, set W = 1. // Use dg1 and dg2 as wrappers to index the copies of _W and W. int lo, hi; dg1.slab(lo, hi); dg1.Pull(_W); dg2.Pull(W); for (int ix=lo; ix < hi; ++ix) for (int iy=0; iy < N; ++iy) for (int iz=0; iz < N; ++iz) if (dg1(ix, iy,iz) > nthresh) { dg2(ix, iy,iz) = 1.0; } else { dg1(ix, iy, iz) = 0.0; // Good to explicitly set this to zero as well } dg1.Push(_W, INSERT_VALUES, false); dg2.Push(W, INSERT_VALUES, false); double tmp; VecSum(W, &tmp); PetscPrintf(PETSC_COMM_WORLD,"Nonzero grid points in W : %f\n",tmp); VecSum(_W, &nrand); PetscPrintf(PETSC_COMM_WORLD,"Sum of background density vector : %f\n",nrand); }
void BuildDensityGrid(int N, double L, Mask3D& mask, Particle& pp, int nover, double thresh, Vec& delta, Vec& W, double smooth) { /* Parameters : * INPUT --- * N : grid size * L : box size * mask : A 3D positive mask (assumed to be 1 or 0) * nover : Oversampling rate for defining the mean density (we use the GridInitialize routine) * This determines the displacement. * For a periodic box, nover means there will be nover**3 particles per grid. * thresh: Fractional threshold below which to remove grid point from survey * smooth: This is an optional parameter -- if set to > 0, it will smooth the density and mask * fields before computing the overdensity. * OUTPUT --- * delta : What do think this is??? * W : Window function, 1 in survey, 0 elsewhere. * Note that the output vectors are not cleared, so you had better make sure you don't leak memory. */ // Allocate two density grids DensityGrid dg1(N,L), dg2(N,L); delta = dg1.Allocate(); W = dg2.Allocate(); // First the particles pp.TrimMask(mask); pp.SlabDecompose(dg1); dg2.CIC(delta,pp, false); PetscPrintf(PETSC_COMM_WORLD, "Particles assigned to the grid.....\n"); // Now do the randoms double nrand=0.0, nexp, nthresh; nexp = pow((double) nover, 3); nthresh = nexp*thresh; { double tmp = 1./nover, dx, dy, dz; VecSet(W, 0.0); // Manually set to zero Vec W1; VecDuplicate(W, &W1); for (int ix = 0; ix < nover; ++ix) { PetscPrintf(PETSC_COMM_WORLD,"Starting random loop %i of %i....\n",ix,nover-1); dx = ix*tmp + tmp/2.0; for (int iy = 0; iy < nover; ++iy) { dy = iy*tmp + tmp/2.0; for (int iz = 0; iz < nover; ++iz) { dz = iz*tmp + tmp/2.0; Particle rr; // Definition here is important, since it ensures destruction, before recreating rr.GridInitialize(N, dx, dy, dz, L); rr.TrimMask(mask); nrand += rr.npart; // rr.SlabDecompose(dg2); We don't need to slab decompose because nproc divides N by construction dg2.CIC(W1, rr, false); // No overdensity VecAXPY(W, 1.0, W1); } } } } PetscPrintf(PETSC_COMM_WORLD, "%f grid particles accumulated....\n", nrand); PetscPrintf(PETSC_COMM_WORLD, "Expected number of particles=%f, threshold=%f\n", nexp, nthresh); // Smooth if desired if (smooth > 1.e-5) { dg1.GaussSmooth(delta, smooth); dg2.GaussSmooth(W, smooth); } // Now build up delta int lo, hi; nrand /= pp.npart; dg1.slab(lo, hi); dg1.Pull(delta); dg2.Pull(W); for (int ix=lo; ix < hi; ++ix) for (int iy=0; iy < N; ++iy) for (int iz=0; iz < N; ++iz) { if (dg2(ix, iy,iz) > nthresh) { dg1(ix, iy,iz) = (dg1(ix,iy,iz)/dg2(ix, iy, iz)) * nrand - 1.0; dg2(ix, iy,iz) = 1.0; } else { dg1(ix, iy, iz) = 0.0; dg2(ix, iy, iz) = 0.0; } } dg1.Push(delta, INSERT_VALUES, false); dg2.Push(W, INSERT_VALUES, false); VecSum(W, &nrand); PetscPrintf(PETSC_COMM_WORLD,"Nonzero grid points in W : %f\n",nrand); }