1 #ifndef _PVFMM_KERNEL_MATRIX_HPP_ 2 #define _PVFMM_KERNEL_MATRIX_HPP_ 6 #include <pvfmm/cheb_utils.hpp> 12 static const Integer DIM = 3;
13 static const Integer ELEMDIM = DIM - 1;
14 static const Integer Nface = 2 * DIM;
19 size_t N = std::max(m, n);
20 Integer order = 6, depth = 0;
22 Integer Ncoeff = order * (order + 1) / 2 * ker.Dim(0);
23 depth = log(N / (2.0 * DIM * Ncoeff))/log(4.0);
24 Initialize(order, depth, ker);
27 Real operator() (
size_t i,
size_t j)
const {
28 return (GetElem(i,j) + GetElem(j,i)) * 0.5;
35 Long Columns()
const {
47 for (Integer i = 0; i < ELEMDIM; i++) Ncoeff_ = (Ncoeff_ * (order_ + i)) / (i + 1);
49 GridDim_ = pvfmm::pow<Long>(2, depth);
50 row_ = Nface * pvfmm::pow<ELEMDIM, Long>(GridDim_) * ker_->Dim(0) * Ncoeff_;
51 col_ = Nface * pvfmm::pow<ELEMDIM, Long>(GridDim_) * ker_->Dim(1) * Ncoeff_;
54 Real GetElem(Long t, Long s)
const {
55 if (t >= row_ || s >= col_)
return (s==t ? 1.0 : 0.0);
57 Integer src_coeff_idx = s % (ker_->Dim(0) * Ncoeff_);
58 Integer trg_coeff_idx = t % (ker_->Dim(1) * Ncoeff_);
60 Integer src_elem = s / (pvfmm::pow<ELEMDIM, Long>(GridDim_) * ker_->Dim(0) * Ncoeff_);
61 Integer trg_elem = t / (pvfmm::pow<ELEMDIM, Long>(GridDim_) * ker_->Dim(1) * Ncoeff_);
63 StaticArray<Real, DIM> scoord, tcoord;
65 Long idx = (s / (ker_->Dim(0) * Ncoeff_)) % pvfmm::pow<ELEMDIM, Long>(GridDim_);
66 Real s = pvfmm::pow<Real>(0.5, depth_);
67 for (Integer i = 0; i < DIM; i++) {
68 if (i == src_elem / 2) {
69 scoord[i] = (src_elem % 2 ? 1.0 - s : 0.0);
71 scoord[i] = (idx % GridDim_) * (1.0 / GridDim_);
77 Long idx = (t / (ker_->Dim(1) * Ncoeff_)) % pvfmm::pow<ELEMDIM, Long>(GridDim_);
78 Real s = pvfmm::pow<Real>(0.5, depth_);
79 for (Integer i = 0; i < DIM; i++) {
80 if (i == trg_elem / 2) {
81 tcoord[i] = (trg_elem % 2 ? 1.0 - s : 0.0);
83 tcoord[i] = (idx % GridDim_) * (1.0 / GridDim_);
89 return GetMatrixElem(order_, scoord, src_elem, tcoord, trg_elem, src_coeff_idx, trg_coeff_idx);
92 Real GetMatrixElem(Integer order, ConstIterator<Real> scoord, Integer src_elem, ConstIterator<Real> tcoord, Integer trg_elem, Long src_coeff_idx, Long trg_coeff_idx)
const {
94 StaticArray<Long, DIM + 2> idx_arr;
95 for (Integer i = 0; i < DIM; i++) idx_arr[i] = (tcoord[i] - scoord[i]) * GridDim_;
96 if ( 0 || std::abs(idx_arr[0]) < 500
97 && std::abs(idx_arr[1]) < 500
98 && std::abs(idx_arr[2]) < 500 )
100 idx_arr[DIM + 0] = src_elem;
101 idx_arr[DIM + 1] = trg_elem;
102 Long idx = cantor_signed(idx_arr, DIM + 2);
105 if (mat.find(idx) == mat.end()) {
106 mat[idx] = Integ(order_, scoord, src_elem, depth_, tcoord, trg_elem, depth_, *ker_);
108 elem = mat[idx][src_coeff_idx][trg_coeff_idx];
111 elem = IntegFar(order_, scoord, src_elem, depth_, tcoord, trg_elem, depth_, *ker_, src_coeff_idx, trg_coeff_idx);
122 ref_coord.ReInit(Nface);
123 Long Neval = pvfmm::pow<Long>(order, ELEMDIM);
127 assert(ref_coord_.Dim() == Neval * ELEMDIM);
128 if (ELEMDIM == DIM) {
130 ref_coord[0].Swap(ref_coord_);
131 }
else if (ELEMDIM == DIM - 1) {
132 for (Integer elem = 0; elem < Nface; elem++) {
133 Integer k0 = (elem >> 1);
134 ref_coord[elem].ReInit(Neval * DIM);
135 for (Long j = 0; j < Neval; j++) {
136 for (Integer k = 0; k < ELEMDIM; k++) {
137 ref_coord[elem][j * DIM + ((k + k0 + 1) % DIM)] = ref_coord_[j * ELEMDIM + k];
141 for (Long j = 0; j < Neval; j++) {
142 ref_coord[elem][j * DIM + k0] = 1;
145 for (Long j = 0; j < Neval; j++) {
146 ref_coord[elem][j * DIM + k0] = 0;
154 static Vector<Real> ChebNodes(ConstIterator<Real> coord, Integer elem, Integer depth, Integer order) {
156 #pragma omp critical (REF_NODES_CRITICAL) 157 if (!ref_nodes.Dim()) {
158 ReferenceElemNodes(order, ref_nodes);
162 nodes = ref_nodes[elem];
164 Integer N = nodes.Dim() / DIM;
165 Real s = pvfmm::pow<Real>(0.5, depth);
166 for (Integer i = 0; i < N; i++) {
167 for (Integer j = DIM - DIM; j < DIM; j++) {
168 nodes[i * DIM + j] = nodes[i * DIM + j] * s + coord[j];
174 static Matrix<Real> Integ(Integer order, ConstIterator<Real> scoord, Integer src_elem, Integer src_depth, ConstIterator<Real> tcoord, Integer trg_elem, Integer trg_depth,
const KernelFunction<Real, DIM> &ker, Real tol = -1) {
177 Vector<Real> trg_nodes = ChebNodes(tcoord, trg_elem, trg_depth, order);
178 Integer Ntrg = trg_nodes.Dim() / DIM;
181 for (Integer i = 0; i < Ntrg; i++) {
182 for (Integer j = 0; j < DIM; j++) {
183 trg_nodes[i * DIM + j] -= scoord[j];
188 Real s = pvfmm::pow<Real>(0.5, src_depth);
189 #pragma omp parallel for schedule(dynamic) 190 for (Integer i = 0; i < Ntrg; i++) {
194 Mcoeff2nodes.ReInit(Mcoeff[0].Dim(0), Mcoeff[0].Dim(1) * Ntrg);
195 for (Integer j = 0; j < Mcoeff[0].Dim(0); j++) {
196 for (Integer i0 = 0; i0 < Mcoeff[0].Dim(1); i0++) {
197 for (Integer i1 = 0; i1 < Ntrg; i1++) {
198 Mcoeff2nodes[j][i1 * Mcoeff[0].Dim(1) + i0] = Mcoeff[i1][j][i0];
206 Integer Ntrg = Mcoeff2nodes.Dim(1) / ker.Dim(1);
207 assert(Ntrg * ker.Dim(1) == Mcoeff2nodes.Dim(1));
208 for (Integer i = 0; i < Mcoeff2nodes.Dim(0); i++) {
209 Matrix<Real> M(Ntrg, ker.Dim(1), Mcoeff2nodes[i],
false);
214 const Vector<Real> fn_v(Mcoeff2nodes.Dim(0) * Mcoeff2nodes.Dim(1), Mcoeff2nodes.Begin(),
false);
217 Mcoeff2coeff.ReInit(Mcoeff2nodes.Dim(0), coeff.Dim() / Mcoeff2nodes.Dim(0), coeff.Begin());
223 static Long cantor_idx(ConstIterator<Long> x, Integer N) {
225 for (Integer d = 0; d < N; d++) {
227 for (Integer i = 0; i < N - d; i++) {
228 sum += std::abs(x[i]);
231 for (Integer i = 0; i < N - d; i++) {
232 offset = offset * (sum + i) / (i + 1);
239 static Long cantor_signed(ConstIterator<Long> x, Integer N) {
240 Long idx = cantor_idx(x, N);
241 for (Integer i = 0; i < N; i++) {
242 idx = 2 * idx + (x[i] < 0 ? 0 : 1);
250 template <Integer DIM, Integer SUBDIM>
static Real IntegFar(Integer order,
const Vector<Real>& r_trg, Real side, Integer src_face,
const KernelFunction<Real, DIM>& ker, Integer src_coeff_idx, Integer trg_coeff_idx) {
252 Real side_inv = 1.0 / side;
265 for (Integer i = 0; i < SUBDIM; i++) Ncoeff = (Ncoeff * (order + i)) / (i + 1);
267 StaticArray<Integer, 2> kdim;
268 kdim[0] = ker.Dim(0);
269 kdim[1] = ker.Dim(1);
271 Integer sidx0=0, sidx1=0, sidx2=0;
272 Integer tidx0=0, tidx1=0, tidx2=0;
274 sidx2 = src_coeff_idx / Ncoeff;
275 Integer idx=0, sidx = src_coeff_idx % Ncoeff;
276 for (Integer i0=0;i0<order;i0++){
277 for (Integer i1=0;i0+i1<order;i1++){
287 tidx2 = trg_coeff_idx / Ncoeff;
288 Integer idx=0, tidx = trg_coeff_idx % Ncoeff;
289 for (Integer i0=0;i0<order;i0++){
290 for (Integer i1=0;i0+i1<order;i1++){
300 PVFMM_ASSERT(SUBDIM==2 && DIM==3);
301 Vector<Real> n_src(pvfmm::pow<SUBDIM, Integer>(Nq)*DIM);
302 Vector<Real> r_src(pvfmm::pow<SUBDIM, Integer>(Nq)*DIM);
303 Vector<Real> v_src(pvfmm::pow<SUBDIM, Integer>(Nq)*kdim[0]);
306 for (Integer i0=0;i0<Nq;i0++){
307 for (Integer i1=0;i1<Nq;i1++){
308 n_src[(i0 * Nq + i1) * DIM + src_face >> 1] = (src_face & 1 ? -1.0 : 1.0);
309 r_src[(i0 * Nq + i1) * DIM + ((src_face>>1)+0)%DIM] = (src_face & 1 ? 1.0 : 0.0) * side;
310 r_src[(i0 * Nq + i1) * DIM + ((src_face>>1)+1)%DIM] = qp[i0] * side;
311 r_src[(i0 * Nq + i1) * DIM + ((src_face>>1)+2)%DIM] = qp[i1] * side;
312 v_src[(i0 * Nq + i1) * kdim[0] + sidx2] = p0[sidx0 * Nq + i0] * p0[sidx1 * Nq + i1] * qw[i0] * qw[i1]*side*side;
316 Long Ntrg = r_trg.Dim() / DIM;
319 ker(r_src, n_src, v_src, r_trg, v_trg);
322 for (Long i=0;i<Ntrg;i++) fn_v[i] = v_trg[i * kdim[1] + tidx2];
324 return coeff[trg_coeff_idx % Ncoeff];
327 static Real IntegFar(Integer order, ConstIterator<Real> scoord, Integer src_elem, Integer src_depth, ConstIterator<Real> tcoord, Integer trg_elem, Integer trg_depth,
const KernelFunction<Real, DIM> &ker, Integer src_coeff_idx, Integer trg_coeff_idx) {
328 Vector<Real> trg_nodes = ChebNodes(tcoord, trg_elem, trg_depth, order);
329 Integer Ntrg = trg_nodes.Dim() / DIM; PVFMM_ASSERT(Ntrg);
330 for (Integer i = 0; i < Ntrg; i++) {
331 for (Integer j = 0; j < DIM; j++) {
332 trg_nodes[i * DIM + j] -= scoord[j];
335 Real s = pvfmm::pow<Real>(0.5, src_depth);
336 return IntegFar<DIM, ELEMDIM>(order, trg_nodes, s, src_elem, ker, src_coeff_idx, trg_coeff_idx);
339 mutable std::map<Long, Matrix<Real>> mat;
341 Integer order_, depth_, Ncoeff_;
342 Long GridDim_, row_, col_;
347 #endif //_PVFMM_KERNEL_MATRIX_HPP_ Definition: cheb_utils.hpp:12
Definition: cheb_utils.hpp:1394
Definition: kernel_matrix.hpp:10
Definition: matrix.hpp:15
Definition: kernel.hpp:1010
Definition: matrix.hpp:12
static void EvalBasis1D(Integer order, const Vector< ValueType > &x, Vector< ValueType > &y)
Returns the values of all Chebyshev polynomials up to degree d, evaluated at points in the input vect...
Definition: cheb_utils.hpp:1406