- Timestamp:
- Apr 22, 2008, 10:49:59 AM (17 years ago)
- Children:
- 0da6d5
- Parents:
- 2399875
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
pcp/src/perturbed.c
r2399875 rb0225a 1711 1711 } 1712 1712 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 */ 1721 double 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 */ 1769 double 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 */ 1817 double 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 } 1713 1849 1714 1850 /** Fouriertransforms given \a source.
Note:
See TracChangeset
for help on using the changeset viewer.