/* Simple convenience wrapper for GMRES solver */ static void solve_gmres_bem3d(matrixtype type, void *A, pavector b, pavector x, real accuracy, uint steps) { addeval_t addevalA; pavector rhat, q, tau; pamatrix qr; uint i, j, n, kk, kmax; real norm; addevalA = (addeval_t) addeval_A; kmax = 500; n = b->dim; assert(x->dim == n); qr = new_zero_amatrix(n, kmax); rhat = new_avector(n); q = new_avector(n); tau = new_avector(kmax); clear_avector(x); init_gmres(addevalA, A, b, x, rhat, q, &kk, qr, tau); for (i = 0; i < steps; i += kmax) { for (j = 0; j < kmax && i + j < steps; ++j) { step_gmres(addevalA, A, b, x, rhat, q, &kk, qr, tau); norm = residualnorm_gmres(rhat, kk); #ifndef NDEBUG printf(" Residual: %.5e\t Iterations: %u\r", norm, j + i); fflush(stdout); #endif if (norm <= accuracy) { finish_gmres(addevalA, A, b, x, rhat, q, &kk, qr, tau); break; } } if (norm <= accuracy) { break; } else { finish_gmres(addevalA, A, b, x, rhat, q, &kk, qr, tau); } } printf("\n"); del_avector(rhat); del_avector(q); del_avector(tau); del_amatrix(qr); }
pcluster build_pca_cluster(pclustergeometry cf, uint size, uint * idx, uint clf) { const uint dim = cf->dim; pamatrix C, Q; pavector v; prealavector lambda; real *x, *y; real w; uint i, j, k, size0, size1; pcluster t; assert(size > 0); size0 = 0; size1 = 0; if (size > clf) { x = allocreal(dim); y = allocreal(dim); /* determine weight of current cluster */ w = 0.0; for (i = 0; i < size; ++i) { w += cf->w[idx[i]]; } w = 1.0 / w; for (j = 0; j < dim; ++j) { x[j] = 0.0; } /* determine center of mass */ for (i = 0; i < size; ++i) { for (j = 0; j < dim; ++j) { x[j] += cf->w[idx[i]] * cf->x[idx[i]][j]; } } for (j = 0; j < dim; ++j) { x[j] *= w; } C = new_zero_amatrix(dim, dim); Q = new_zero_amatrix(dim, dim); lambda = new_realavector(dim); /* setup covariance matrix */ for (i = 0; i < size; ++i) { for (j = 0; j < dim; ++j) { y[j] = cf->x[idx[i]][j] - x[j]; } for (j = 0; j < dim; ++j) { for (k = 0; k < dim; ++k) { C->a[j + k * C->ld] += cf->w[idx[i]] * y[j] * y[k]; } } } /* get eigenvalues and eigenvectors of covariance matrix */ eig_amatrix(C, lambda, Q); /* get eigenvector from largest eigenvalue */ v = new_avector(0); init_column_avector(v, Q, dim - 1); /* separate cluster with v as separation-plane */ for (i = 0; i < size; ++i) { /* x_i - X */ for (j = 0; j < dim; ++j) { y[j] = cf->x[idx[i]][j] - x[j]; } /* <y,v> */ w = 0.0; for (j = 0; j < dim; ++j) { w += y[j] * v->v[j]; } if (w >= 0.0) { j = idx[i]; idx[i] = idx[size0]; idx[size0] = j; size0++; } else { size1++; } } assert(size0 + size1 == size); del_amatrix(Q); del_amatrix(C); del_realavector(lambda); del_avector(v); freemem(x); freemem(y); /* recursion */ if (size0 > 0) { if (size1 > 0) { t = new_cluster(size, idx, 2, cf->dim); t->son[0] = build_pca_cluster(cf, size0, idx, clf); t->son[1] = build_pca_cluster(cf, size1, idx + size0, clf); update_bbox_cluster(t); } else { t = new_cluster(size, idx, 1, cf->dim); t->son[0] = build_pca_cluster(cf, size0, idx, clf); update_bbox_cluster(t); } } else { assert(size1 > 0); t = new_cluster(size, idx, 1, cf->dim); t->son[0] = build_pca_cluster(cf, size1, idx, clf); update_bbox_cluster(t); } } else { t = new_cluster(size, idx, 0, cf->dim); update_support_bbox_cluster(cf, t); } update_cluster(t); return t; }