void prepare_surface3d(psurface3d gr) { const real(*x)[3] = (const real(*)[3]) gr->x; const uint(*t)[3] = (const uint(*)[3]) gr->t; real(*n)[3] = gr->n; real *g = gr->g; real dx[3], dy[3], dz[3]; real norm, height, hmin, hmax, a, b, c; uint triangles = gr->triangles; uint i; hmin = 1e30; hmax = 0.0; for (i = 0; i < triangles; i++) { dx[0] = x[t[i][1]][0] - x[t[i][0]][0]; dx[1] = x[t[i][1]][1] - x[t[i][0]][1]; dx[2] = x[t[i][1]][2] - x[t[i][0]][2]; dy[0] = x[t[i][2]][0] - x[t[i][0]][0]; dy[1] = x[t[i][2]][1] - x[t[i][0]][1]; dy[2] = x[t[i][2]][2] - x[t[i][0]][2]; dz[0] = x[t[i][2]][0] - x[t[i][1]][0]; dz[1] = x[t[i][2]][1] - x[t[i][1]][1]; dz[2] = x[t[i][2]][2] - x[t[i][1]][2]; n[i][0] = dx[1] * dy[2] - dx[2] * dy[1]; n[i][1] = dx[2] * dy[0] - dx[0] * dy[2]; n[i][2] = dx[0] * dy[1] - dx[1] * dy[0]; norm = REAL_SQRT(REAL_SQR(n[i][0]) + REAL_SQR(n[i][1]) + REAL_SQR(n[i][2])); g[i] = norm; n[i][0] /= norm; n[i][1] /= norm; n[i][2] /= norm; a = REAL_SQRT(REAL_SQR(dx[0]) + REAL_SQR(dx[1]) + REAL_SQR(dx[2])); b = REAL_SQRT(REAL_SQR(dy[0]) + REAL_SQR(dy[1]) + REAL_SQR(dy[2])); c = REAL_SQRT(REAL_SQR(dz[0]) + REAL_SQR(dz[1]) + REAL_SQR(dz[2])); height = 2.0 * REAL_MIN3(a, b, c); a *= a; b *= b; c *= c; height = REAL_SQRT(2 * (a * b + b * c + a * c) - (a * a + b * b + c * c)) / height; hmin = REAL_MIN(hmin, height); hmax = REAL_MAX(hmax, height); } gr->hmin = hmin; gr->hmax = hmax; }
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; }
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; }
real getdiam_2_cluster(pccluster t) { real diam2; uint i; diam2 = 0.0; for (i = 0; i < t->dim; i++) diam2 += REAL_SQR(t->bmax[i] - t->bmin[i]); return REAL_SQRT(diam2); }
bool parabolic_admissibility(pdcluster rc, pdcluster cc, uint l, uint * rd, uint * cd, void *data) { pcdiradmdata dad = (pcdiradmdata) data; real eta2 = dad->eta2; real wave_k = dad->wave_k; preal xy = dad->xy; real rdiam, cdiam, dist, dist2, invdist; uint dim; uint i, iota; dim = rc->dim; assert(cc->dim == dim); /* Compute cluster diameters */ rdiam = diam_dcluster(rc); cdiam = diam_dcluster(cc); /* Compute distance */ dist = dist_dcluster(rc, cc); /* Check parabolic admissibility condition */ if (wave_k * rdiam * rdiam <= eta2 * dist && wave_k * cdiam * cdiam <= eta2 * dist && rdiam <= eta2 * dist && cdiam <= eta2 * dist) { /* Compute distance of midpoints */ dist2 = 0.0; for (i = 0; i < dim; i++) { xy[i] = 0.5 * (rc->bmax[i] + rc->bmin[i] - cc->bmax[i] - cc->bmin[i]); dist2 += REAL_SQR(xy[i]); } invdist = 1.0 / REAL_SQRT(dist2); /* Scale distance vector... */ for (i = 0; i < dim; i++) xy[i] *= invdist; /* ... and choose a direction that is sufficiently close */ iota = finddirection_leveldir(dad->ld, l, 1.0, xy); *rd = iota; *cd = iota; return true; } *rd = 0; *cd = 0; return false; }
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; }
void smooth_unitcircle_tri2d(ptri2d t2) { uint i; real normL2, normL1; /* Scaling vertices */ for (i = 0; i < t2->vertices; i++) { normL1 = REAL_ABS(t2->x[i][0]) + REAL_ABS(t2->x[i][1]); normL2 = REAL_SQRT(t2->x[i][0] * t2->x[i][0] + t2->x[i][1] * t2->x[i][1]); if (normL1 != 0.0) { t2->x[i][0] = t2->x[i][0] * normL1 / normL2; t2->x[i][1] = t2->x[i][1] * normL1 / normL2; } } }
real getdist_2_cluster(pccluster t, pccluster s) { real dist2; uint i; assert(t->dim == s->dim); dist2 = 0.0; for (i = 0; i < t->dim; i++) if (t->bmax[i] < s->bmin[i]) /* t to the "left" of s */ dist2 += REAL_SQR(s->bmin[i] - t->bmax[i]); else if (s->bmax[i] < t->bmin[i]) /* t to the "right" of s */ dist2 += REAL_SQR(t->bmin[i] - s->bmax[i]); return REAL_SQRT(dist2); }
/* 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; }
void prepare_curve2d(pcurve2d gr) { const real(*x)[2] = (const real(*)[2]) gr->x; const uint(*e)[2] = (const uint(*)[2]) gr->e; real(*n)[2] = gr->n; real *g = gr->g; real norm; uint edges = gr->edges; uint i; for (i = 0; i < edges; i++) { n[i][0] = x[e[i][1]][1] - x[e[i][0]][1]; n[i][1] = x[e[i][0]][0] - x[e[i][1]][0]; norm = REAL_SQRT(REAL_SQR(n[i][0]) + REAL_SQR(n[i][1])); g[i] = norm; n[i][0] /= norm; n[i][1] /= norm; } }
real norm2chol_sparsematrix(pchmatrix LU, pcsparsematrix sp) { avector tmp1, tmp2; uint rows = LU->rc->size; uint cols = LU->cc->size; pavector x, y; real norm; uint j; assert(sp->rows == rows); assert(sp->cols == cols); x = init_avector(&tmp1, cols); y = init_avector(&tmp2, rows); random_avector(x); norm = norm2_avector(x); scale_avector(1.0 / norm, x); for (j = 0; j < NORM_STEPS; j++) { // printf("norm = %g \n", sqrt( norm)); clear_avector(y); mvm_sparsematrix_avector(1.0, false, sp, x, y); triangularsolve_hmatrix_avector(true, false, false, LU, y); triangularsolve_hmatrix_avector(true, false, true, LU, y); add_avector(-1.0, y, x); copy_avector(x, y); triangularsolve_hmatrix_avector(true, false, false, LU, y); triangularsolve_hmatrix_avector(true, false, true, LU, y); mvm_sparsematrix_avector(-1.0, true, sp, y, x); norm = norm2_avector(x); scale_avector(1.0 / norm, x); } uninit_avector(y); uninit_avector(x); return REAL_SQRT(norm); }
void statistics_tet3d(pctet3d t3, preal hmin, preal hmax, preal volmin, preal volmax, preal relvolmin, preal relvolmax) { const real(*x)[3] = (const real(*)[3]) t3->x; uint tetrahedra = t3->tetrahedra; real xl[4][3]; real xd[6][3]; real h, norm, vol; uint v[4]; uint i, j; for (i = 0; i < tetrahedra; i++) { getvertices_tet3d(t3, i, v); /* Get coordinates of vertices */ for (j = 0; j < 4; j++) { xl[j][0] = x[v[j]][0]; xl[j][1] = x[v[j]][1]; xl[j][2] = x[v[j]][2]; } /* Compute edge vectors */ xd[0][0] = xl[1][0] - xl[0][0]; xd[0][1] = xl[1][1] - xl[0][1]; xd[0][2] = xl[1][2] - xl[0][2]; xd[1][0] = xl[2][0] - xl[0][0]; xd[1][1] = xl[2][1] - xl[0][1]; xd[1][2] = xl[2][2] - xl[0][2]; xd[2][0] = xl[3][0] - xl[0][0]; xd[2][1] = xl[3][1] - xl[0][1]; xd[2][2] = xl[3][2] - xl[0][2]; xd[3][0] = xl[2][0] - xl[1][0]; xd[3][1] = xl[2][1] - xl[1][1]; xd[3][2] = xl[2][2] - xl[1][2]; xd[4][0] = xl[3][0] - xl[1][0]; xd[4][1] = xl[3][1] - xl[1][1]; xd[4][2] = xl[3][2] - xl[1][2]; xd[5][0] = xl[3][0] - xl[2][0]; xd[5][1] = xl[3][1] - xl[2][1]; xd[5][2] = xl[3][2] - xl[2][2]; /* Update h, hmin and hmax */ h = 0.0; for (j = 0; j < 6; j++) { norm = REAL_SQRT(REAL_SQR(xd[j][0]) + REAL_SQR(xd[j][1]) + REAL_SQR(xd[j][2])); if (i == 0 || norm < *hmin) *hmin = norm; if (i == 0 || norm > *hmax) *hmax = norm; if (norm > h) h = norm; } /* Compute volume */ vol = fabs(xd[0][0] * xd[1][1] * xd[2][2] + xd[1][0] * xd[2][1] * xd[0][2] + xd[2][0] * xd[0][1] * xd[1][2] - xd[0][0] * xd[2][1] * xd[1][2] - xd[1][0] * xd[0][1] * xd[2][2] - xd[2][0] * xd[1][1] * xd[0][2]) / 6.0; if (i == 0 || vol < *volmin) *volmin = vol; if (i == 0 || vol > *volmax) *volmax = vol; /* Compute relative volume */ vol /= h * h * h; if (i == 0 || vol < *relvolmin) *relvolmin = vol; if (i == 0 || vol > *relvolmax) *relvolmax = vol; } }
ptet3d new_regular_tet3d() { ptet3d t3; real r, h, c, y; r = 1.0; h = REAL_SQRT(2.0) - 1.0; c = REAL_SQRT(0.75); y = 1.0 - REAL_SQRT(0.5); t3 = new_tet3d(4, 6, 4, 1); t3->x[0][0] = 0.0; t3->x[0][1] = -h - y; t3->x[0][2] = -r; t3->x[1][0] = -c * r; t3->x[1][1] = -h - y; t3->x[1][2] = 0.5 * r; t3->x[2][0] = c * r; t3->x[2][1] = -h - y; t3->x[2][2] = 0.5 * r; t3->x[3][0] = 0.0; t3->x[3][1] = 1.0 - y; t3->x[3][2] = 0.0; t3->e[0][0] = 1; t3->e[0][1] = 2; t3->e[1][0] = 2; t3->e[1][1] = 3; t3->e[2][0] = 3; t3->e[2][1] = 1; t3->e[3][0] = 0; t3->e[3][1] = 1; t3->e[4][0] = 0; t3->e[4][1] = 2; t3->e[5][0] = 0; t3->e[5][1] = 3; t3->f[0][0] = 1; t3->f[0][1] = 2; t3->f[0][2] = 0; t3->f[1][0] = 1; t3->f[1][1] = 4; t3->f[1][2] = 5; t3->f[2][0] = 2; t3->f[2][1] = 5; t3->f[2][2] = 3; t3->f[3][0] = 0; t3->f[3][1] = 3; t3->f[3][2] = 4; t3->t[0][0] = 0; t3->t[0][1] = 1; t3->t[0][2] = 2; t3->t[0][3] = 3; t3->xb[0] = t3->xb[1] = t3->xb[2] = t3->xb[3] = 1; t3->eb[0] = t3->eb[1] = t3->eb[2] = t3->eb[3] = t3->eb[4] = t3->eb[5] = 1; t3->fb[0] = t3->fb[1] = t3->fb[2] = t3->fb[3] = 1; t3->vertices = 4; t3->edges = 6; t3->faces = 4; t3->tetrahedra = 1; return t3; }
int main(int argc, char **argv) { pmacrosurface3d mg; psurface3d gr; pamatrix Vfull, KMfull; pbem3d bem_slp, bem_dlp; pcluster root; pblock block; phmatrix V, KM; pclusterbasis Vrb, Vcb, KMrb, KMcb; ph2matrix V2, KM2; uint n, q, clf, m, l; real eta, delta, eps_aca; field kvec[3]; cl_device_id *devices; cl_uint ndevices; uint *idx; uint i; init_h2lib(&argc, &argv); get_opencl_devices(&devices, &ndevices); ndevices = 1; set_opencl_devices(devices, ndevices, 2); kvec[0] = 2.0, kvec[1] = 0.0, kvec[2] = 0.0; n = 512; q = 2; clf = 16; eta = 1.0; mg = new_sphere_macrosurface3d(); gr = build_from_macrosurface3d_surface3d(mg, REAL_SQRT(n * 0.125)); n = gr->triangles; printf("Testing unit sphere with %d triangles\n", n); bem_slp = new_slp_helmholtz_ocl_bem3d(kvec, gr, q, q + 2, BASIS_CONSTANT_BEM3D); bem_dlp = new_dlp_helmholtz_ocl_bem3d(kvec, gr, q, q + 2, BASIS_CONSTANT_BEM3D, BASIS_CONSTANT_BEM3D, 0.5); root = build_bem3d_cluster(bem_slp, clf, BASIS_CONSTANT_BEM3D); block = build_nonstrict_block(root, root, &eta, admissible_max_cluster); max_pardepth = 0; Vfull = new_amatrix(n, n); KMfull = new_amatrix(n, n); idx = allocuint(n); for (i = 0; i < n; ++i) { idx[i] = i; } SCHEDULE_OPENCL(0, 1, bem_slp->nearfield, idx, idx, bem_slp, false, Vfull); SCHEDULE_OPENCL(0, 1, bem_dlp->nearfield, idx, idx, bem_dlp, false, KMfull); V = build_from_block_hmatrix(block, 0); KM = build_from_block_hmatrix(block, 0); printf("----------------------------------------\n"); printf("Testing outer Boundary integral equations:\n"); printf("----------------------------------------\n\n"); /* * Test Interpolation */ m = 4; setup_hmatrix_aprx_inter_row_bem3d(bem_slp, root, root, block, m); setup_hmatrix_aprx_inter_row_bem3d(bem_dlp, root, root, block, m); test_hmatrix_system("Interpolation row", Vfull, KMfull, block, bem_slp, V, bem_dlp, KM, false, true, 1.0e-3, 2.0e-3); setup_hmatrix_aprx_inter_col_bem3d(bem_slp, root, root, block, m); setup_hmatrix_aprx_inter_col_bem3d(bem_dlp, root, root, block, m); test_hmatrix_system("Interpolation column", Vfull, KMfull, block, bem_slp, V, bem_dlp, KM, false, true, 1.0e-3, 2.0e-3); setup_hmatrix_aprx_inter_mixed_bem3d(bem_slp, root, root, block, m); setup_hmatrix_aprx_inter_mixed_bem3d(bem_dlp, root, root, block, m); test_hmatrix_system("Interpolation mixed", Vfull, KMfull, block, bem_slp, V, bem_dlp, KM, false, true, 1.0e-3, 2.0e-3); /* * Test Green */ m = 5; l = 1; delta = 0.5; setup_hmatrix_aprx_green_row_bem3d(bem_slp, root, root, block, m, l, delta, build_bem3d_cube_quadpoints); setup_hmatrix_aprx_green_row_bem3d(bem_dlp, root, root, block, m, l, delta, build_bem3d_cube_quadpoints); test_hmatrix_system("Green row", Vfull, KMfull, block, bem_slp, V, bem_dlp, KM, false, true, 1.0e-3, 2.0e-3); setup_hmatrix_aprx_green_col_bem3d(bem_slp, root, root, block, m, l, delta, build_bem3d_cube_quadpoints); setup_hmatrix_aprx_green_col_bem3d(bem_dlp, root, root, block, m, l, delta, build_bem3d_cube_quadpoints); test_hmatrix_system("Green column", Vfull, KMfull, block, bem_slp, V, bem_dlp, KM, false, true, 1.0e-3, 2.0e-3); setup_hmatrix_aprx_green_mixed_bem3d(bem_slp, root, root, block, m, l, delta, build_bem3d_cube_quadpoints); setup_hmatrix_aprx_green_mixed_bem3d(bem_dlp, root, root, block, m, l, delta, build_bem3d_cube_quadpoints); test_hmatrix_system("Green mixed", Vfull, KMfull, block, bem_slp, V, bem_dlp, KM, false, true, 1.0e-3, 2.0e-3); /* * Test Greenhybrid */ m = 2; l = 1; delta = 1.0; eps_aca = 2.0e-2; setup_hmatrix_aprx_greenhybrid_row_bem3d(bem_slp, root, root, block, m, l, delta, eps_aca, build_bem3d_cube_quadpoints); setup_hmatrix_aprx_greenhybrid_row_bem3d(bem_dlp, root, root, block, m, l, delta, eps_aca, build_bem3d_cube_quadpoints); test_hmatrix_system("Greenhybrid row", Vfull, KMfull, block, bem_slp, V, bem_dlp, KM, false, true, 1.0e-3, 2.0e-3); setup_hmatrix_aprx_greenhybrid_col_bem3d(bem_slp, root, root, block, m, l, delta, eps_aca, build_bem3d_cube_quadpoints); setup_hmatrix_aprx_greenhybrid_col_bem3d(bem_dlp, root, root, block, m, l, delta, eps_aca, build_bem3d_cube_quadpoints); test_hmatrix_system("Greenhybrid column", Vfull, KMfull, block, bem_slp, V, bem_dlp, KM, false, true, 1.0e-3, 2.0e-3); setup_hmatrix_aprx_greenhybrid_mixed_bem3d(bem_slp, root, root, block, m, l, delta, eps_aca, build_bem3d_cube_quadpoints); setup_hmatrix_aprx_greenhybrid_mixed_bem3d(bem_dlp, root, root, block, m, l, delta, eps_aca, build_bem3d_cube_quadpoints); test_hmatrix_system("Greenhybrid mixed", Vfull, KMfull, block, bem_slp, V, bem_dlp, KM, false, true, 1.0e-3, 2.0e-3); /* * Test ACA / PACA / HCA */ m = 2; eps_aca = 1.0e-2; /* Nearfield computation on GPU not applicable here yet! */ // setup_hmatrix_aprx_aca_bem3d(bem_slp, root, root, block, eps_aca); // setup_hmatrix_aprx_aca_bem3d(bem_dlp, root, root, block, eps_aca); // test_hmatrix_system("ACA full pivoting", Vfull, KMfull, block, bem_slp, V, // bem_dlp, KM, false, true, 1.0e-3, 2.0e-3); // // setup_hmatrix_aprx_paca_bem3d(bem_slp, root, root, block, eps_aca); // setup_hmatrix_aprx_paca_bem3d(bem_slp, root, root, block, eps_aca); // test_hmatrix_system("ACA partial pivoting", Vfull, KMfull, block, bem_slp, V, // bem_dlp, KM, false, true, 1.0e-3, 2.0e-3); setup_hmatrix_aprx_hca_bem3d(bem_slp, root, root, block, m, eps_aca); setup_hmatrix_aprx_hca_bem3d(bem_slp, root, root, block, m, eps_aca); test_hmatrix_system("HCA2", Vfull, KMfull, block, bem_slp, V, bem_dlp, KM, false, true, 1.0e-3, 2.0e-3); del_hmatrix(V); del_hmatrix(KM); del_block(block); /* * H2-matrix */ block = build_strict_block(root, root, &eta, admissible_max_cluster); Vrb = build_from_cluster_clusterbasis(root); Vcb = build_from_cluster_clusterbasis(root); KMrb = build_from_cluster_clusterbasis(root); KMcb = build_from_cluster_clusterbasis(root); V2 = build_from_block_h2matrix(block, Vrb, Vcb); KM2 = build_from_block_h2matrix(block, KMrb, KMcb); /* * Test Interpolation */ m = 3; setup_h2matrix_aprx_inter_bem3d(bem_slp, Vrb, Vcb, block, m); setup_h2matrix_aprx_inter_bem3d(bem_dlp, KMrb, KMcb, block, m); test_h2matrix_system("Interpolation", Vfull, KMfull, block, bem_slp, V2, bem_dlp, KM2, false, true, 1.0e-3, 2.0e-3); /* * Test Greenhybrid */ m = 2; l = 1; delta = 1.0; eps_aca = 2.0e-2; setup_h2matrix_aprx_greenhybrid_bem3d(bem_slp, Vrb, Vcb, block, m, l, delta, eps_aca, build_bem3d_cube_quadpoints); setup_h2matrix_aprx_greenhybrid_bem3d(bem_dlp, KMrb, KMcb, block, m, l, delta, eps_aca, build_bem3d_cube_quadpoints); test_h2matrix_system("Greenhybrid", Vfull, KMfull, block, bem_slp, V2, bem_dlp, KM2, false, true, 1.0e-3, 2.0e-3); /* Nearfield computation on GPU not applicable here yet! */ // setup_h2matrix_aprx_greenhybrid_ortho_bem3d(bem_slp, Vrb, Vcb, block, m, l, // delta, eps_aca, build_bem3d_cube_quadpoints); // setup_h2matrix_aprx_greenhybrid_ortho_bem3d(bem_dlp, KMrb, KMcb, block, m, l, // delta, eps_aca, build_bem3d_cube_quadpoints); // test_h2matrix_system("Greenhybrid ortho", Vfull, KMfull, block, bem_slp, V2, // bem_dlp, KM2, false, true, 1.0e-3, 2.0e-3); del_h2matrix(V2); del_h2matrix(KM2); del_block(block); freemem(root->idx); del_cluster(root); del_helmholtz_ocl_bem3d(bem_slp); del_helmholtz_ocl_bem3d(bem_dlp); del_amatrix(Vfull); del_amatrix(KMfull); del_surface3d(gr); del_macrosurface3d(mg); freemem(idx); (void) printf("----------------------------------------\n" " %u matrices and\n" " %u vectors still active\n" " %u errors found\n", getactives_amatrix(), getactives_avector(), problems); uninit_h2lib(); return problems; }
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); }
void draw_cairo_tri2d(pctri2d t2, const char *filename, bool mark_refedges, int mark_triangle) { #ifdef USE_CAIRO cairo_surface_t *surface; cairo_t *cr; const real(*x)[2] = (const real(*)[2]) t2->x; const uint(*e)[2] = (const uint(*)[2]) t2->e; const uint(*t)[3] = (const uint(*)[3]) t2->t; uint vertices = t2->vertices; uint edges = t2->edges; uint triangles = t2->triangles; double xmin, xmax, ymin, ymax; double hmin, hk, x0, y0, dx, dy, nx, ny; uint k; xmin = xmax = x[0][0]; ymin = ymax = x[0][1]; for (k = 1; k < vertices; k++) { if (x[k][0] < xmin) xmin = x[k][0]; else if (x[k][0] > xmax) xmax = x[k][0]; if (x[k][1] < ymin) ymin = x[k][1]; else if (x[k][1] > ymax) ymax = x[k][1]; } surface = cairo_pdf_surface_create(filename, 100.0 * (xmax - xmin), 100.0 * (ymax - ymin)); cr = cairo_create(surface); cairo_surface_destroy(surface); cairo_translate(cr, -100.0 * xmin, -100.0 * ymin); cairo_scale(cr, 95.0, 95.0); cairo_set_line_width(cr, cairo_get_line_width(cr) / 95.0); cairo_scale(cr, 1.0, -1.0); cairo_set_source_rgb(cr, 1.0, 0.0, 0.0); if (mark_triangle >= 0) { k = mark_triangle; cairo_move_to(cr, x[e[t[k][0]][0]][0], x[e[t[k][0]][0]][1]); cairo_line_to(cr, x[e[t[k][0]][1]][0], x[e[t[k][0]][1]][1]); if (e[t[k][1]][0] == e[t[k][0]][0] || e[t[k][1]][0] == e[t[k][0]][1]) cairo_line_to(cr, x[e[t[k][1]][1]][0], x[e[t[k][1]][1]][1]); else cairo_line_to(cr, x[e[t[k][1]][0]][0], x[e[t[k][1]][0]][1]); cairo_close_path(cr); cairo_fill(cr); } if (mark_refedges) { hmin = REAL_SQRT(REAL_SQR(x[e[0][0]][0] - x[e[0][1]][0]) + REAL_SQR(x[e[0][0]][1] - x[e[0][1]][1])); for (k = 1; k < edges; k++) { hk = REAL_SQRT(REAL_SQR(x[e[k][0]][0] - x[e[k][1]][0]) + REAL_SQR(x[e[k][0]][1] - x[e[k][1]][1])); if (hk < hmin) hmin = hk; } hk = xmax - xmin; if (ymax - ymin < hk) hk = ymax - ymin; if (hmin > 0.05 * hk) hmin = 0.05 * hk; cairo_set_source_rgb(cr, 0.0, 0.0, 1.0); for (k = 0; k < triangles; k++) { cairo_move_to(cr, x[e[t[k][0]][0]][0], x[e[t[k][0]][0]][1]); cairo_line_to(cr, x[e[t[k][0]][1]][0], x[e[t[k][0]][1]][1]); nx = x[e[t[k][0]][1]][1] - x[e[t[k][0]][0]][1]; ny = x[e[t[k][0]][0]][0] - x[e[t[k][0]][1]][0]; hk = REAL_SQRT(REAL_SQR(nx) + REAL_SQR(ny)); nx /= hk; ny /= hk; if (e[t[k][1]][0] == e[t[k][2]][0] || e[t[k][1]][0] == e[t[k][2]][1]) { x0 = x[e[t[k][1]][0]][0]; y0 = x[e[t[k][1]][0]][1]; } else { assert(e[t[k][1]][1] == e[t[k][2]][0] || e[t[k][1]][1] == e[t[k][2]][1]); x0 = x[e[t[k][1]][1]][0]; y0 = x[e[t[k][1]][1]][1]; } dx = x0 - x[e[t[k][0]][1]][0]; dy = y0 - x[e[t[k][0]][1]][1]; hk = REAL_ABS(dx * nx + dy * ny); dx /= hk; dy /= hk; cairo_line_to(cr, x[e[t[k][0]][1]][0] + hmin * 0.2 * dx, x[e[t[k][0]][1]][1] + hmin * 0.2 * dy); dx = x0 - x[e[t[k][0]][0]][0]; dy = y0 - x[e[t[k][0]][0]][1]; hk = REAL_ABS(dx * nx + dy * ny); dx /= hk; dy /= hk; cairo_line_to(cr, x[e[t[k][0]][0]][0] + hmin * 0.2 * dx, x[e[t[k][0]][0]][1] + hmin * 0.2 * dy); cairo_close_path(cr); cairo_fill(cr); } } cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); for (k = 0; k < edges; k++) { cairo_move_to(cr, x[e[k][0]][0], x[e[k][0]][1]); cairo_line_to(cr, x[e[k][1]][0], x[e[k][1]][1]); cairo_stroke(cr); } cairo_destroy(cr); #else fprintf(stderr, "CAIRO not supported.\n"); #endif }
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; }
void getproperties_surface3d(pcsurface3d gr, preal hmin, preal hmax, preal anglemin, preal angleedge) { uint edges = gr->edges; uint triangles = gr->triangles; const real(*x)[3] = (const real(*)[3]) gr->x; const uint(*t)[3] = (const uint(*)[3]) gr->t; const uint(*s)[3] = (const uint(*)[3]) gr->s; const real(*n)[3] = (const real(*)[3]) gr->n; const real *g = (const real *) gr->g; uint *neighbour; real dt[3], ds[3], h[3], nn, angle; real h_min, h_max, angle_min, angle_edge; uint i, j; /* Just to avoid warnings */ h_min = h_max = angle_min = 0.0; for (i = 0; i < triangles; i++) { dt[0] = x[t[i][1]][0] - x[t[i][0]][0]; dt[1] = x[t[i][1]][1] - x[t[i][0]][1]; dt[2] = x[t[i][1]][2] - x[t[i][0]][2]; ds[0] = x[t[i][2]][0] - x[t[i][0]][0]; ds[1] = x[t[i][2]][1] - x[t[i][0]][1]; ds[2] = x[t[i][2]][2] - x[t[i][0]][2]; h[0] = (REAL_SQR(dt[0]) + REAL_SQR(dt[1]) + REAL_SQR(dt[2])); h[1] = (REAL_SQR(ds[0]) + REAL_SQR(ds[1]) + REAL_SQR(ds[2])); h[2] = (REAL_SQR(dt[0] - ds[0]) + REAL_SQR(dt[1] - ds[1]) + REAL_SQR(dt[2] - ds[2])); if (i == 0 || h[0] < h_min) h_min = h[0]; if (i == 0 || h[0] > h_max) h_max = h[0]; if (h[1] < h_min) h_min = h[1]; if (h[1] > h_max) h_max = h[1]; if (h[2] < h_min) h_min = h[2]; if (h[2] > h_max) h_max = h[2]; angle = g[i] / REAL_SQRT(h[0] * h[1]); if (i == 0 || angle < angle_min) angle_min = angle; } if (hmin) *hmin = REAL_SQRT(h_min); if (hmax) *hmax = REAL_SQRT(h_max); if (anglemin) *anglemin = REAL_ASIN(angle_min); if (angleedge) { neighbour = (uint *) allocmem(sizeof(uint) * edges); for (i = 0; i < edges; i++) neighbour[i] = triangles; angle_edge = 1.0; for (i = 0; i < triangles; i++) { if (neighbour[s[i][0]] < triangles) { j = neighbour[s[i][0]]; nn = (n[i][0] * n[j][0] + n[i][1] * n[j][1] + n[i][2] * n[j][2]); if (nn < angle_edge) angle_edge = nn; } else neighbour[s[i][0]] = i; if (neighbour[s[i][1]] < triangles) { j = neighbour[s[i][1]]; nn = (n[i][0] * n[j][0] + n[i][1] * n[j][1] + n[i][2] * n[j][2]); if (nn < angle_edge) angle_edge = nn; } else neighbour[s[i][1]] = i; if (neighbour[s[i][2]] < triangles) { j = neighbour[s[i][2]]; nn = (n[i][0] * n[j][0] + n[i][1] * n[j][1] + n[i][2] * n[j][2]); if (nn < angle_edge) angle_edge = nn; } else neighbour[s[i][2]] = i; } *angleedge = REAL_ACOS(angle_edge); freemem(neighbour); } }