Commit 3d3480b1 authored by Martin Reinecke's avatar Martin Reinecke

sync with wsclean version

parent 601993e3
...@@ -152,27 +152,6 @@ template<typename T, size_t ndim> const_mav<T, ndim> nullmav() ...@@ -152,27 +152,6 @@ template<typename T, size_t ndim> const_mav<T, ndim> nullmav()
shp.fill(0); shp.fill(0);
return const_mav<T, ndim>(nullptr, shp); return const_mav<T, ndim>(nullptr, shp);
} }
template<typename T, size_t ndim> class tmpStorage
{
private:
vector<T> d;
mav<T,ndim> mav_;
static size_t prod(const array<size_t,ndim> &shp)
{
size_t res=1;
for (auto v: shp) res*=v;
return res;
}
public:
tmpStorage(const array<size_t,ndim> &shp)
: d(prod(shp)), mav_(d.data(), shp) {}
mav<T,ndim> &getMav() { return mav_; }
const_mav<T,ndim> getCmav() { return cmav(mav_); }
void fill(const T & val)
{ std::fill(d.begin(), d.end(), val); }
};
// //
// basic utilities // basic utilities
...@@ -239,6 +218,28 @@ template<size_t ndim> void checkShape ...@@ -239,6 +218,28 @@ template<size_t ndim> void checkShape
template<typename T> inline T fmod1 (T v) template<typename T> inline T fmod1 (T v)
{ return v-floor(v); } { return v-floor(v); }
template<typename T, size_t ndim> class tmpStorage
{
private:
vector<T> d;
mav<T,ndim> mav_;
static size_t prod(const array<size_t,ndim> &shp)
{
size_t res=1;
for (auto v: shp) res*=v;
return res;
}
public:
tmpStorage(const array<size_t,ndim> &shp)
: d(prod(shp)), mav_(d.data(), shp) {}
mav<T,ndim> &getMav() { return mav_; }
const_mav<T,ndim> getCmav() { return cmav(mav_); }
void fill(const T & val)
{ std::fill(d.begin(), d.end(), val); }
};
// //
// Utilities for Gauss-Legendre quadrature // Utilities for Gauss-Legendre quadrature
// //
...@@ -254,8 +255,8 @@ void legendre_prep(int n, vector<double> &x, vector<double> &w, size_t nthreads) ...@@ -254,8 +255,8 @@ void legendre_prep(int n, vector<double> &x, vector<double> &w, size_t nthreads)
x.resize(m); x.resize(m);
w.resize(m); w.resize(m);
double t0 = 1 - (1-1./n) / (8.*n*n); const double t0 = 1 - (1-1./n) / (8.*n*n);
double t1 = 1./(4.*n+2.); const double t1 = 1./(4.*n+2.);
#pragma omp parallel num_threads(nthreads) #pragma omp parallel num_threads(nthreads)
{ {
...@@ -592,15 +593,16 @@ class GridderConfig ...@@ -592,15 +593,16 @@ class GridderConfig
double ushift, vshift; double ushift, vshift;
int maxiu0, maxiv0; int maxiu0, maxiv0;
complex<double> wscreen(double x, double y, double w, bool adjoint) const complex<double> wscreen(double x, double y, double w, bool adjoint,
bool divide_by_n) const
{ {
constexpr double pi = 3.141592653589793238462643383279502884197; constexpr double pi = 3.141592653589793238462643383279502884197;
double tmp = 1-x-y; double tmp = 1-x-y;
if (tmp<0) return 0.; if (tmp<=0) return divide_by_n ? 0. : 1.; // no phase factor beyond the horizon
double nm1 = (-x-y)/(sqrt(tmp)+1); // more accurate form of sqrt(1-x-y) double nm1 = (-x-y)/(sqrt(tmp)+1); // more accurate form of sqrt(1-x-y)-1
double n = nm1+1., xn = 1./n;
double phase = 2*pi*w*nm1; double phase = 2*pi*w*nm1;
if (adjoint) phase *= -1; if (adjoint) phase *= -1;
double xn = divide_by_n ? 1./(nm1+1) : 1;
return complex<double>(cos(phase)*xn, sin(phase)*xn); return complex<double>(cos(phase)*xn, sin(phase)*xn);
} }
...@@ -760,7 +762,7 @@ class GridderConfig ...@@ -760,7 +762,7 @@ class GridderConfig
} }
template<typename T> void apply_wscreen(const const_mav<complex<T>,2> &dirty, template<typename T> void apply_wscreen(const const_mav<complex<T>,2> &dirty,
mav<complex<T>,2> &dirty2, double w, bool adjoint) const mav<complex<T>,2> &dirty2, double w, bool adjoint, bool divide_by_n) const
{ {
checkShape(dirty.shape(), {nx_dirty, ny_dirty}); checkShape(dirty.shape(), {nx_dirty, ny_dirty});
checkShape(dirty2.shape(), {nx_dirty, ny_dirty}); checkShape(dirty2.shape(), {nx_dirty, ny_dirty});
...@@ -774,7 +776,7 @@ class GridderConfig ...@@ -774,7 +776,7 @@ class GridderConfig
for (size_t j=0; j<=ny_dirty/2; ++j) for (size_t j=0; j<=ny_dirty/2; ++j)
{ {
double fy = y0+j*psy; double fy = y0+j*psy;
auto ws = complex<T>(wscreen(fx, fy*fy, w, adjoint)); auto ws = complex<T>(wscreen(fx, fy*fy, w, adjoint, divide_by_n));
dirty2(i,j) = dirty(i,j)*ws; // lower left dirty2(i,j) = dirty(i,j)*ws; // lower left
size_t i2 = nx_dirty-i, j2 = ny_dirty-j; size_t i2 = nx_dirty-i, j2 = ny_dirty-j;
if ((i>0)&&(i<i2)) if ((i>0)&&(i<i2))
...@@ -847,8 +849,6 @@ template<typename T, typename T2=complex<T>> class Helper ...@@ -847,8 +849,6 @@ template<typename T, typename T2=complex<T>> class Helper
{ {
if (bu0<-nsafe) return; // nothing written into buffer yet if (bu0<-nsafe) return; // nothing written into buffer yet
#pragma omp critical (gridder_writing_to_grid)
{
int idxu = (bu0+nu)%nu; int idxu = (bu0+nu)%nu;
int idxv0 = (bv0+nv)%nv; int idxv0 = (bv0+nv)%nv;
for (int iu=0; iu<su; ++iu) for (int iu=0; iu<su; ++iu)
...@@ -863,7 +863,6 @@ template<typename T, typename T2=complex<T>> class Helper ...@@ -863,7 +863,6 @@ template<typename T, typename T2=complex<T>> class Helper
locks[idxu].unlock(); locks[idxu].unlock();
if (++idxu>=nu) idxu=0; if (++idxu>=nu) idxu=0;
} }
}
} }
void load() void load()
...@@ -1323,8 +1322,13 @@ template<typename T> void apply_wcorr(const GridderConfig &gconf, ...@@ -1323,8 +1322,13 @@ template<typename T> void apply_wcorr(const GridderConfig &gconf,
double tmp = 1.-fx-fy; double tmp = 1.-fx-fy;
if (tmp>=0) if (tmp>=0)
{ {
auto nm1 = (-fx-fy)/(sqrt(1.-fx-fy)+1.); // accurate form of sqrt(1-x-y) auto nm1 = (-fx-fy)/(sqrt(tmp)+1.); // accurate form of sqrt(1-x-y)-1
fct = T((nm1<=-1) ? 0. : kernel.corfac(nm1*dw)); fct = T(kernel.corfac(nm1*dw));
}
else // beyond the horizon, don't really know what to do here
{
double nm1 = sqrt(-tmp)-1;
fct = T(kernel.corfac(nm1*dw));
} }
size_t i2 = nx_dirty-i, j2 = ny_dirty-j; size_t i2 = nx_dirty-i, j2 = ny_dirty-j;
dirty(i,j)*=fct; dirty(i,j)*=fct;
...@@ -1411,9 +1415,12 @@ template<typename Serv> class WgridHelper ...@@ -1411,9 +1415,12 @@ template<typename Serv> class WgridHelper
if (verbosity>0) cout << "Using single-threaded mode" << endl; if (verbosity>0) cout << "Using single-threaded mode" << endl;
#endif #endif
if (verbosity>0) cout << "W range: " << wmin << " to " << wmax << endl; if (verbosity>0) cout << "W range: " << wmin << " to " << wmax << endl;
double x0 = -0.5*gconf.Nxdirty()*gconf.Pixsize_x(), double x0 = -0.5*gconf.Nxdirty()*gconf.Pixsize_x(),
y0 = -0.5*gconf.Nydirty()*gconf.Pixsize_y(); y0 = -0.5*gconf.Nydirty()*gconf.Pixsize_y();
double nmin = sqrt(max(1.-x0*x0-y0*y0,0.))-1.; double nmin = sqrt(max(1.-x0*x0-y0*y0,0.))-1.;
if (x0*x0+y0*y0>1.)
nmin = -sqrt(abs(1.-x0*x0-y0*y0))-1.;
dw = 0.25/abs(nmin); dw = 0.25/abs(nmin);
nplanes = size_t((wmax-wmin)/dw+2); nplanes = size_t((wmax-wmin)/dw+2);
dw = (1.+1e-13)*(wmax-wmin)/(nplanes-1); dw = (1.+1e-13)*(wmax-wmin)/(nplanes-1);
...@@ -1426,6 +1433,15 @@ template<typename Serv> class WgridHelper ...@@ -1426,6 +1433,15 @@ template<typename Serv> class WgridHelper
if (verbosity>0) cout << "nplanes: " << nplanes << endl; if (verbosity>0) cout << "nplanes: " << nplanes << endl;
minplane.resize(nplanes); minplane.resize(nplanes);
#if 0
// extra short, but potentially inefficient version:
for (size_t ipart=0; ipart<nvis; ++ipart)
{
int plane0 = max(0,int(1+(abs(srv.getCoord(ipart).w)-(0.5*supp*dw)-wmin)/dw));
minplane[plane0].push_back(idx_t(ipart));
}
#else
// full fledged, overdesigned OpenMP version
vector<size_t> tcnt(max<int>(nthreads, my_max_threads())*nplanes,0); vector<size_t> tcnt(max<int>(nthreads, my_max_threads())*nplanes,0);
#pragma omp parallel num_threads(nthreads) #pragma omp parallel num_threads(nthreads)
{ {
...@@ -1461,6 +1477,7 @@ template<typename Serv> class WgridHelper ...@@ -1461,6 +1477,7 @@ template<typename Serv> class WgridHelper
minplane[plane0][myofs[plane0]++]=idx_t(ipart); minplane[plane0][myofs[plane0]++]=idx_t(ipart);
} }
} }
#endif
} }
typename Serv::Tsub getSubserv() const typename Serv::Tsub getSubserv() const
...@@ -1503,7 +1520,7 @@ template<typename T, typename Serv> void x2dirty( ...@@ -1503,7 +1520,7 @@ template<typename T, typename Serv> void x2dirty(
grid.fill(0); grid.fill(0);
x2grid_c(gconf, hlp.getSubserv(), grid, hlp.W(), dw); x2grid_c(gconf, hlp.getSubserv(), grid, hlp.W(), dw);
gconf.grid2dirty_c_overwrite(grid, tdirty); gconf.grid2dirty_c_overwrite(grid, tdirty);
gconf.apply_wscreen(cmav(tdirty), tdirty, hlp.W(), true); gconf.apply_wscreen(cmav(tdirty), tdirty, hlp.W(), true, true);
#pragma omp parallel for num_threads(nthreads) #pragma omp parallel for num_threads(nthreads)
for (size_t i=0; i<gconf.Nxdirty(); ++i) for (size_t i=0; i<gconf.Nxdirty(); ++i)
for (size_t j=0; j<gconf.Nydirty(); ++j) for (size_t j=0; j<gconf.Nydirty(); ++j)
...@@ -1568,7 +1585,7 @@ template<typename T, typename Serv> void dirty2x( ...@@ -1568,7 +1585,7 @@ template<typename T, typename Serv> void dirty2x(
for (size_t i=0; i<nx_dirty; ++i) for (size_t i=0; i<nx_dirty; ++i)
for (size_t j=0; j<ny_dirty; ++j) for (size_t j=0; j<ny_dirty; ++j)
tdirty2(i,j) = tdirty(i,j); tdirty2(i,j) = tdirty(i,j);
gconf.apply_wscreen(cmav(tdirty2), tdirty2, hlp.W(), false); gconf.apply_wscreen(cmav(tdirty2), tdirty2, hlp.W(), false, true);
gconf.dirty2grid_c(cmav(tdirty2), grid); gconf.dirty2grid_c(cmav(tdirty2), grid);
grid2x_c(gconf, cmav(grid), hlp.getSubserv(), hlp.W(), dw); grid2x_c(gconf, cmav(grid), hlp.getSubserv(), hlp.W(), dw);
......
...@@ -284,6 +284,8 @@ w : float ...@@ -284,6 +284,8 @@ w : float
the w value to use the w value to use
adjoint: bool adjoint: bool
if True, apply the complex conjugate of the w screen if True, apply the complex conjugate of the w screen
ivide_by_n: bool, default=True
if True, divide ny n.
Returns Returns
======= =======
...@@ -420,23 +422,25 @@ class PyGridderConfig: public GridderConfig ...@@ -420,23 +422,25 @@ class PyGridderConfig: public GridderConfig
myfail("type matching failed: 'dirty' has neither type 'c8' nor 'c16'"); myfail("type matching failed: 'dirty' has neither type 'c8' nor 'c16'");
} }
template<typename T> pyarr<complex<T>> apply_wscreen2 template<typename T> pyarr<complex<T>> apply_wscreen2
(const pyarr<complex<T>> &dirty, double w, bool adjoint) const (const pyarr<complex<T>> &dirty, double w, bool adjoint,
bool divide_by_n) const
{ {
auto dirty2 = make_const_mav<2>(dirty); auto dirty2 = make_const_mav<2>(dirty);
auto res = makeArray<complex<T>>({nx_dirty, ny_dirty}); auto res = makeArray<complex<T>>({nx_dirty, ny_dirty});
auto res2 = make_mav<2>(res); auto res2 = make_mav<2>(res);
{ {
py::gil_scoped_release release; py::gil_scoped_release release;
GridderConfig::apply_wscreen(dirty2, res2, w, adjoint); GridderConfig::apply_wscreen(dirty2, res2, w, adjoint, divide_by_n);
} }
return res; return res;
} }
py::array apply_wscreen(const py::array &dirty, double w, bool adjoint) const py::array apply_wscreen(const py::array &dirty, double w, bool adjoint,
bool divide_by_n) const
{ {
if (isPytype<complex<float>>(dirty)) if (isPytype<complex<float>>(dirty))
return apply_wscreen2<float>(dirty, w, adjoint); return apply_wscreen2<float>(dirty, w, adjoint, divide_by_n);
if (isPytype<complex<double>>(dirty)) if (isPytype<complex<double>>(dirty))
return apply_wscreen2<double>(dirty, w, adjoint); return apply_wscreen2<double>(dirty, w, adjoint, divide_by_n);
myfail("type matching failed: 'dirty' has neither type 'c8' nor 'c16'"); myfail("type matching failed: 'dirty' has neither type 'c8' nor 'c16'");
} }
}; };
...@@ -1087,7 +1091,7 @@ PYBIND11_MODULE(nifty_gridder, m) ...@@ -1087,7 +1091,7 @@ PYBIND11_MODULE(nifty_gridder, m)
dirty2grid_DS, "dirty"_a) dirty2grid_DS, "dirty"_a)
.def("dirty2grid_c", &PyGridderConfig::dirty2grid_c, "dirty"_a) .def("dirty2grid_c", &PyGridderConfig::dirty2grid_c, "dirty"_a)
.def("apply_wscreen", &PyGridderConfig::apply_wscreen, .def("apply_wscreen", &PyGridderConfig::apply_wscreen,
apply_wscreen_DS, "dirty"_a, "w"_a, "adjoint"_a) apply_wscreen_DS, "dirty"_a, "w"_a, "adjoint"_a, "divide_by_n"_a=true)
// pickle support // pickle support
.def(py::pickle( .def(py::pickle(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment