real max_rel_inner_error(pcbem3d bem, helmholtz_data * hdata, pcavector x, boundary_func3d rhs) { uint nx, nz, npoints; real(*xdata)[3]; field *ydata; uint i, j; real error, maxerror; real eta_bw = REAL_SQRT(ABSSQR(bem->kvec[0]) + ABSSQR(bem->kvec[1]) + ABSSQR(bem->kvec[2])); nx = 20; nz = 20; npoints = nx * nz; xdata = (real(*)[3]) allocreal(3 * npoints); npoints = 0; for (j = 0; j < nz; ++j) { for (i = 0; i < nx; ++i) { xdata[npoints][0] = -1.0 + (2.0 / (nx - 1)) * i; xdata[npoints][1] = 0.0; xdata[npoints][2] = -1.0 + (2.0 / (nz - 1)) * j; if (REAL_SQR(xdata[npoints][0]) + REAL_SQR(xdata[npoints][2]) < 1) { npoints++; } } } ydata = allocfield(npoints); #pragma omp parallel for for (j = 0; j < npoints; ++j) { ydata[j] = eval_brakhage_werner_c(bem, x, eta_bw, xdata[j]); } j = 0; maxerror = ABS(ydata[j] - rhs(xdata[j], NULL, hdata)) / ABS(rhs(xdata[j], NULL, hdata)); for (j = 1; j < npoints; ++j) { error = ABS(ydata[j] - rhs(xdata[j], NULL, hdata)) / ABS(rhs(xdata[j], NULL, hdata)); maxerror = error > maxerror ? error : maxerror; } freemem(ydata); freemem(xdata); return maxerror; }
field rhs_dirichlet_point_helmholtzbem3d(const real * x, const real * n, const void *data) { helmholtz_data *hdata = (helmholtz_data *) data; field *kvec = hdata->kvec; field k = REAL_SQRT(ABSSQR(kvec[0]) + ABSSQR(kvec[1]) + ABSSQR(kvec[2])); real *s = hdata->source; real r = REAL_SQRT(REAL_SQR(x[0] - s[0]) + REAL_SQR(x[1] - s[1]) + REAL_SQR(x[2] - s[2])); (void) n; return cexp(I * k * r) / r; }
field rhs_neumann_point_helmholtzbem3d(const real * x, const real * n, const void *data) { helmholtz_data *hdata = (helmholtz_data *) data; field *kvec = hdata->kvec; field k = REAL_SQRT(ABSSQR(kvec[0]) + ABSSQR(kvec[1]) + ABSSQR(kvec[2])); real *s = hdata->source; real r = REAL_SQRT(REAL_SQR(x[0] - s[0]) + REAL_SQR(x[1] - s[1]) + REAL_SQR(x[2] - s[2])); field res; res = cexp(I * k * r) / (r * r * r) * (I * k * r - 1.0); res = res * (n[0] * (x[0] - s[0]) + n[1] * (x[1] - s[1]) + n[2] * (x[2] - s[2])); return res; }
/* Compute the L_2-error for constant basis functions */ static real L2gamma_c_diff_norm2(pbem2d bem, pavector x, boundary_func2d rhs) { pccurve2d gr = bem->gr; const real(*gr_x)[2] = (const real(*)[2]) gr->x; const uint(*gr_e)[2] = (const uint(*)[2]) gr->e; const real(*gr_n)[2] = (const real(*)[2]) gr->n; const preal gr_g = (const preal) gr->g; uint n = x->dim; uint nq = bem->sq->n_single; real *xx = bem->sq->x_single; real *ww = bem->sq->w_single; const real *A, *B, *N; uint e, q; real norm, sum, X[2], tx, Ax, Bx; assert(n == gr->edges); norm = 0.0; for (e = 0; e < n; ++e) { A = gr_x[gr_e[e][0]]; B = gr_x[gr_e[e][1]]; N = gr_n[e]; sum = 0.0; for (q = 0; q < nq; ++q) { tx = xx[q]; Ax = 1.0 - tx; Bx = tx; X[0] = A[0] * Ax + B[0] * Bx; X[1] = A[1] * Ax + B[1] * Bx; sum += ww[q] * ABSSQR(rhs(X, N) - x->v[e]); } norm += sum * gr_g[e]; } norm = REAL_SQRT(norm); return norm; }
static void test_h2matrix_system(const char *apprxtype, pcamatrix Vfull, pcamatrix KMfull, pblock block, pbem3d bem_slp, ph2matrix V, pbem3d bem_dlp, ph2matrix KM, bool linear, bool exterior, real low, real high) { struct _eval_A eval; helmholtz_data hdata; pavector x, b; real errorV, errorKM, error_solve, eps_solve; uint steps; boundary_func3d rhs = (boundary_func3d) rhs_dirichlet_point_helmholtzbem3d; eps_solve = 1.0e-12; steps = 1000; printf("Testing: %s H2matrix %s\n" "====================================\n\n", (exterior == true ? "exterior" : "interior"), apprxtype); assemble_bem3d_h2matrix_row_clusterbasis(bem_slp, V->rb); assemble_bem3d_h2matrix_col_clusterbasis(bem_slp, V->cb); SCHEDULE_OPENCL(0, 1, assemble_bem3d_h2matrix, bem_slp, block, V); assemble_bem3d_h2matrix_row_clusterbasis(bem_dlp, KM->rb); assemble_bem3d_h2matrix_col_clusterbasis(bem_dlp, KM->cb); SCHEDULE_OPENCL(0, 1, assemble_bem3d_h2matrix, bem_dlp, block, KM); eval.V = V; eval.Vtype = H2MATRIX; eval.KM = KM; eval.KMtype = H2MATRIX; eval.eta = REAL_SQRT(ABSSQR(bem_slp->kvec[0]) + ABSSQR(bem_slp->kvec[1]) + ABSSQR(bem_slp->kvec[2])); hdata.kvec = bem_slp->kvec; hdata.source = allocreal(3); if (exterior) { hdata.source[0] = 0.0, hdata.source[1] = 0.0, hdata.source[2] = 0.2; } else { hdata.source[0] = 0.0, hdata.source[1] = 0.0, hdata.source[2] = 5.0; } errorV = norm2diff_amatrix_h2matrix(V, Vfull) / norm2_amatrix(Vfull); printf("rel. error V : %.5e\n", errorV); errorKM = norm2diff_amatrix_h2matrix(KM, KMfull) / norm2_amatrix(KMfull); printf("rel. error K%c0.5*M : %.5e\n", (exterior == true ? '-' : '+'), errorKM); x = new_avector(Vfull->rows); b = new_avector(KMfull->cols); printf("Solving Dirichlet problem:\n"); integrate_bem3d_const_avector(bem_dlp, rhs, b, (void *) &hdata); solve_gmres_bem3d(HMATRIX, &eval, b, x, eps_solve, steps); error_solve = max_rel_outer_error(bem_slp, &hdata, x, rhs); printf("max. rel. error : %.5e %s\n", error_solve, (IS_IN_RANGE(low, error_solve, high) ? " okay" : "NOT okay")); if (!IS_IN_RANGE(low, error_solve, high)) problems++; printf("\n"); del_avector(x); del_avector(b); freemem(hdata.source); }
field eval_brakhage_werner_c(pcbem3d bem, pcavector w, field eta, real * x) { pcsurface3d gr = bem->gr; const real(*gr_x)[3] = (const real(*)[3]) gr->x; const uint(*gr_t)[3] = (const uint(*)[3]) gr->t; const real(*gr_n)[3] = (const real(*)[3]) gr->n; const preal gr_g = (const preal) gr->g; const uint rows = gr->triangles; const field *kvec = bem->kvec; uint nq = bem->sq->n_single; real *xx = bem->sq->x_single; real *yy = bem->sq->y_single; real *ww = bem->sq->w_single + 3 * nq; const real *A, *B, *C, *ns; uint s, ss, q; real gs_fac, dx, dy, dz, tx, sx, Ax, Bx, Cx, norm, rnorm, norm2; field k, sum; field res; k = REAL_SQRT(ABSSQR(kvec[0]) + ABSSQR(kvec[1]) + ABSSQR(kvec[2])); /* * integrate kernel function over first variable with constant basisfunctions */ res = 0.0; for (s = 0; s < rows; ++s) { ss = s; gs_fac = gr_g[ss] * 0.0795774715459476679; ns = gr_n[ss]; A = gr_x[gr_t[ss][0]]; B = gr_x[gr_t[ss][1]]; C = gr_x[gr_t[ss][2]]; sum = 0.0; for (q = 0; q < nq; ++q) { tx = xx[q]; sx = yy[q]; Ax = 1.0 - tx; Bx = tx - sx; Cx = sx; dx = x[0] - (A[0] * Ax + B[0] * Bx + C[0] * Cx); dy = x[1] - (A[1] * Ax + B[1] * Bx + C[1] * Cx); dz = x[2] - (A[2] * Ax + B[2] * Bx + C[2] * Cx); norm2 = dx * dx + dy * dy + dz * dz; rnorm = REAL_RSQRT(norm2); norm = norm2 * rnorm; rnorm *= rnorm * rnorm; sum += ww[q] * cexp(I * k * norm) * rnorm * ((1.0 - I * k * norm) * (dx * ns[0] + dy * ns[1] + dz * ns[2]) - I * eta * norm2); } res += sum * gs_fac * w->v[ss]; } return res; }