Changeset b0225a for pcp


Ignore:
Timestamp:
Apr 22, 2008, 10:49:59 AM (17 years ago)
Author:
Frederik Heber <heber@…>
Children:
0da6d5
Parents:
2399875
Message:

added LinearInterpolationBetweenGrid(), LinearPullDownFromUpperLevel() and FirstDiscreteDerivative() for future Gradient Correction methods

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pcp/src/perturbed.c

    r2399875 rb0225a  
    17111711}
    17121712
     1713/** Linear interpolation for coordinate \a R that lies between grid nodes of \a *grid.
     1714 * \param *P Problem at hand
     1715 * \param *Lat Lattice structure for grid axis
     1716 * \param *Lev LatticeLevel structure for grid axis node counts
     1717 * \param R[] coordinate vector
     1718 * \param *grid grid with fixed nodes
     1719 * \return linearly interpolated value of \a *grid for position \a R[NDIM]
     1720 */
     1721double LinearInterpolationBetweenGrid(struct Problem *P, struct Lattice *Lat, struct LatticeLevel *Lev, double R[NDIM], fftw_real *grid)
     1722{
     1723  double x[2][NDIM];
     1724  const int myPE = P->Par.me_comm_ST_Psi;
     1725  int N[NDIM];
     1726  const int N0 = Lev->Plan0.plan->local_nx;
     1727  N[0] = Lev->Plan0.plan->N[0];
     1728  N[1] = Lev->Plan0.plan->N[1];
     1729  N[2] = Lev->Plan0.plan->N[2];
     1730  int g;
     1731  double n[NDIM];
     1732  int k[2][NDIM];
     1733  double sigma;
     1734 
     1735  RMat33Vec3(n, Lat->ReciBasis, &R[0]); // transform real coordinates to [0,1]^3 vector
     1736  for (g=0;g<NDIM;g++) {
     1737    // k[i] are right and left nearest neighbour node to true position
     1738    k[0][g] = floor(n[g]/(2.*PI)*(double)N[g]);  // n[2] is floor grid
     1739    k[1][g] = ceil(n[g]/(2.*PI)*(double)N[g]); // n[1] is ceil grid
     1740    // x[i] give weights of left and right neighbours (the nearer the true point is to one, the closer its weight to 1)
     1741    x[0][g] = (k[1][g] - n[g]/(2.*PI)*(double)N[g]);
     1742    x[1][g] = 1. - x[0][g];
     1743    //fprintf(stderr,"(%i) n = %lg, n_floor[%i] = %i\tn_ceil[%i] = %i --- x_floor[%i] = %e\tx_ceil[%i] = %e\n",P->Par.me, n[g], g,k[0][g], g,k[1][g], g,x[0][g], g,x[1][g]);
     1744  }
     1745  sigma = 0.;
     1746  for (g=0;g<2;g++) { // interpolate linearly between adjacent grid points per axis
     1747    if ((k[g][0] >= N0*myPE) && (k[g][0] < N0*(myPE+1))) {
     1748      //fprintf(stderr,"(%i) grid[%i]: sigma = %e\n", P->Par.me,  k[g][2]+N[2]*(k[g][1]+N[1]*(k[g][0]-N0*myPE)), sigma);
     1749      sigma += (x[g][0]*x[0][1]*x[0][2])*grid[k[0][2]+N[2]*(k[0][1]+N[1]*(k[g][0]-N0*myPE))]*mu0; // if it's local and factor from inverse fft
     1750      //fprintf(stderr,"(%i) grid[%i]: sigma += %e * %e \n", P->Par.me,  k[g][2]+N[2]*(k[g][1]+N[1]*(k[g][0]-N0*myPE)), (x[g][0]*x[0][1]*x[0][2]), grid[k[0][2]+N[2]*(k[0][1]+N[1]*(k[g][0]-N0*myPE))]*mu0);
     1751      sigma += (x[g][0]*x[0][1]*x[1][2])*grid[k[1][2]+N[2]*(k[0][1]+N[1]*(k[g][0]-N0*myPE))]*mu0; // if it's local and factor from inverse fft
     1752      //fprintf(stderr,"(%i) grid[%i]: sigma += %e * %e \n", P->Par.me,  k[g][2]+N[2]*(k[g][1]+N[1]*(k[g][0]-N0*myPE)), (x[g][0]*x[0][1]*x[1][2]), grid[k[1][2]+N[2]*(k[0][1]+N[1]*(k[g][0]-N0*myPE))]*mu0);
     1753      sigma += (x[g][0]*x[1][1]*x[0][2])*grid[k[0][2]+N[2]*(k[1][1]+N[1]*(k[g][0]-N0*myPE))]*mu0; // if it's local and factor from inverse fft
     1754      //fprintf(stderr,"(%i) grid[%i]: sigma += %e * %e \n", P->Par.me,  k[g][2]+N[2]*(k[g][1]+N[1]*(k[g][0]-N0*myPE)), (x[g][0]*x[1][1]*x[0][2]), grid[k[0][2]+N[2]*(k[1][1]+N[1]*(k[g][0]-N0*myPE))]*mu0);
     1755      sigma += (x[g][0]*x[1][1]*x[1][2])*grid[k[1][2]+N[2]*(k[1][1]+N[1]*(k[g][0]-N0*myPE))]*mu0; // if it's local and factor from inverse fft
     1756      //fprintf(stderr,"(%i) grid[%i]: sigma += %e * %e \n", P->Par.me,  k[g][2]+N[2]*(k[g][1]+N[1]*(k[g][0]-N0*myPE)), (x[g][0]*x[1][1]*x[1][2]), grid[k[1][2]+N[2]*(k[1][1]+N[1]*(k[g][0]-N0*myPE))]*mu0);
     1757    }
     1758  }
     1759  return sigma;
     1760}
     1761
     1762/** Linear Interpolation from all eight corners of the box that singles down to a point on the lower level.
     1763 * \param *P Problem at hand
     1764 * \param *Lev LatticeLevel structure for node numbers
     1765 * \param upperNode Node around which to interpolate
     1766 * \param *upperGrid array of grid points
     1767 * \return summed up and then averaged octant around \a upperNode
     1768 */ 
     1769double LinearPullDownFromUpperLevel(struct Problem *P, struct LatticeLevel *Lev, int upperNode, fftw_real *upperGrid)
     1770{
     1771  const int N0 = Lev->Plan0.plan->local_nx;
     1772  const int N1 = Lev->Plan0.plan->N[1];
     1773  const int N2 = Lev->Plan0.plan->N[2];
     1774  double lowerGrid = 0.;
     1775  int nr=1;
     1776  lowerGrid += upperGrid[upperNode];
     1777  if (upperNode % N0 != N0-1) {
     1778    lowerGrid += upperGrid[upperNode+1];
     1779    nr++;
     1780    if (upperNode % N1 != N1-1) {
     1781      lowerGrid += upperGrid[upperNode + 0 + N2*(1 + N1*1)];
     1782      nr++;
     1783      if (upperNode % N2 != N2-1) {
     1784       lowerGrid += upperGrid[upperNode + 1 + N2*(1 + N1*1)];
     1785        nr++;
     1786      }
     1787    }
     1788    if (upperNode % N2 != N2-1) {
     1789      lowerGrid += upperGrid[upperNode + 1 + N2*(0 + N1*1)];
     1790      nr++;
     1791    }
     1792  }
     1793  if (upperNode % N1 != N1-1) {
     1794    lowerGrid += upperGrid[upperNode + 0 + N2*(1 + N1*0)];
     1795    nr++;
     1796    if (upperNode % N2 != N2-1) {
     1797      lowerGrid += upperGrid[upperNode + 1 + N2*(1 + N1*0)];
     1798      nr++;
     1799    }
     1800  }
     1801  if (upperNode % N2 != N2-1) {
     1802    lowerGrid += upperGrid[upperNode + 1 + N2*(0 + N1*0)];
     1803    nr++;
     1804  }
     1805  return (lowerGrid/(double)nr);
     1806}
     1807
     1808/** Evaluates the 1-stern in order to evaluate the first derivative on the grid.
     1809 * \param *P Problem at hand
     1810 * \param *Lev Level to interpret the \a *density on
     1811 * \param *density array with gridded values
     1812 * \param *n 3 vector with indices on the grid
     1813 * \param axis axis along which is derived
     1814 * \param myPE number of processes who share the density
     1815 * \return  [+1/2 -1/2] of \a *n
     1816 */
     1817double FirstDiscreteDerivative(struct Problem *P, struct LatticeLevel *Lev, fftw_real *density, int *n, int axis, int myPE)
     1818{
     1819  int *N = Lev->Plan0.plan->N;  // maximum nodes per axis
     1820  const int N0 = Lev->Plan0.plan->local_nx; // special local number due to parallel split up
     1821  double ret[NDIM],  Ret[NDIM];  // return value local/global
     1822  int i;
     1823
     1824  for (i=0;i<NDIM;i++) {
     1825    ret[i] = Ret[i] = 0.;
     1826  }
     1827  if (((n[0]+1)%N[0] >= N0*myPE) && ((n[0]+1)%N[0] < N0*(myPE+1)))   // next cell belongs to this process
     1828    ret[0] += 1./2. * (density[n[2]+N[2]*(n[1]+N[1]*(n[0]+1-N0*myPE))]);
     1829  if (((n[0]-1)%N[0] >= N0*myPE) && ((n[0]-1)%N[0] < N0*(myPE+1))) // previous cell belongs to this process
     1830    ret[0] -= 1./2. * (density[n[2]+N[2]*(n[1]+N[1]*(n[0]-1-N0*myPE))]);
     1831  if ((n[0] >= N0*myPE) && (n[0] < N0*(myPE+1))) {
     1832    ret[1] += 1./2. * (density[n[2]+N[2]*((n[1]+1)%N[1] + N[1]*(n[0]%N0))]);
     1833    ret[1] -= 1./2. * (density[n[2]+N[2]*((n[1]-1)%N[1] + N[1]*(n[0]%N0))]);
     1834  }     
     1835  if ((n[0] >= N0*myPE) && (n[0] < N0*(myPE+1))) {
     1836    ret[2] += 1./2. * (density[(n[2]+1)%N[2] + N[2]*(n[1]+N[1]*(n[0]%N0))]);
     1837    ret[2] -= 1./2. * (density[(n[2]-1)%N[2] + N[2]*(n[1]+N[1]*(n[0]%N0))]);
     1838  }
     1839 
     1840  if (MPI_Allreduce(ret, Ret, 3, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi) != MPI_SUCCESS)
     1841    Error(SomeError, "FirstDiscreteDerivative: MPI_Allreduce failure!");
     1842   
     1843  for (i=0;i<NDIM;i++)  // transform from node count to [0,1]^3
     1844    Ret[i] *= N[i];
     1845  RMat33Vec3(ret, P->Lat.ReciBasis, Ret); // this actually divides it by mesh length in real coordinates
     1846  //fprintf(stderr, "(%i) sum at (%i,%i,%i) : %lg\n",P->Par.me, n[0],n[1],n[2], ret[axis]); 
     1847  return ret[axis]; ///(P->Lat.RealBasisQ[axis]/N[axis]);
     1848}
    17131849
    17141850/** Fouriertransforms given \a source.
Note: See TracChangeset for help on using the changeset viewer.