static PyObject *center(PyObject *self, PyObject *args) { int molid, frame; PyObject *selected; PyObject *weightobj = NULL; AtomSel *sel; // parse arguments if (!PyArg_ParseTuple(args, (char *)"iiO!|O", &molid, &frame, &PyTuple_Type, &selected, &weightobj)) return NULL; VMDApp *app = get_vmdapp(); // get selection if (!(sel = sel_from_py(molid, frame, selected, app))) return NULL; // get weight float *weight = parse_weight(sel, weightobj); if (!weight) return NULL; float cen[3]; // compute center int ret_val = measure_center(sel, sel->coordinates(app->moleculeList), weight, cen); delete [] weight; delete sel; if (ret_val < 0) { PyErr_SetString(PyExc_ValueError, measure_error(ret_val)); return NULL; } // return as (x, y, z) PyObject *cenobj = PyTuple_New(3); for (int i=0; i<3; i++) PyTuple_SET_ITEM(cenobj, i, PyFloat_FromDouble(cen[i])); return cenobj; }
static PyObject *py_rmsd(PyObject *self, PyObject *args) { int mol1, frame1, mol2, frame2; PyObject *selected1, *selected2, *weightobj = NULL; if (!PyArg_ParseTuple(args, (char *)"iiO!iiO!O:atomselection.rmsd", &mol1, &frame1, &PyTuple_Type, &selected1, &mol2, &frame2, &PyTuple_Type, &selected2, &weightobj)) return NULL; VMDApp *app = get_vmdapp(); AtomSel *sel1 = sel_from_py(mol1, frame1, selected1, app); AtomSel *sel2 = sel_from_py(mol2, frame2, selected2, app); if (!sel1 || !sel2) { delete sel1; delete sel2; return NULL; } const Timestep *ts1 =app->moleculeList->mol_from_id(mol1)->get_frame(frame1); const Timestep *ts2 =app->moleculeList->mol_from_id(mol2)->get_frame(frame2); if (!ts1 || !ts2) { PyErr_SetString(PyExc_ValueError, "No coordinates in selection"); delete sel1; delete sel2; return NULL; } float *weight = parse_weight(sel1, weightobj); if (!weight) { delete sel1; delete sel2; return NULL; } float rmsd; int rc = measure_rmsd(sel1, sel2, sel1->selected, ts1->pos, ts2->pos, weight, &rmsd); delete sel1; delete sel2; delete [] weight; if (rc < 0) { PyErr_SetString(PyExc_ValueError, measure_error(rc)); return NULL; } return PyFloat_FromDouble(rmsd); }
static PyObject *minmax(PyObject *self, PyObject *args) { int molid, frame; PyObject *selected; if (!PyArg_ParseTuple(args, (char *)"iiO!", &molid, &frame, &PyTuple_Type, &selected)) return NULL; // bad args VMDApp *app = get_vmdapp(); AtomSel *sel = sel_from_py(molid, frame, selected, app); if (!sel) return NULL; const Timestep *ts = app->moleculeList->mol_from_id(molid)->get_frame(frame); if (!ts) { PyErr_SetString(PyExc_ValueError, "No coordinates in selection"); delete sel; return NULL; } float min[3], max[3]; int rc = measure_minmax(sel->num_atoms, sel->on, ts->pos, NULL, min, max); delete sel; if (rc < 0) { PyErr_SetString(PyExc_ValueError, measure_error(rc)); return NULL; } PyObject *mintuple, *maxtuple, *result; mintuple = PyTuple_New(3); maxtuple = PyTuple_New(3); result = PyTuple_New(2); for (int i=0; i<3; i++) { PyTuple_SET_ITEM(mintuple, i, PyFloat_FromDouble(min[i])); PyTuple_SET_ITEM(maxtuple, i, PyFloat_FromDouble(max[i])); } PyTuple_SET_ITEM(result, 0, mintuple); PyTuple_SET_ITEM(result, 1, maxtuple); return result; }
static PyObject *sasa(PyObject *self, PyObject *args, PyObject *keywds) { int molid = -1, frame = -1; float srad = 0; PyObject *selobj = NULL, *restrictobj = NULL; int samples = -1; const int *sampleptr = NULL; PyObject *pointsobj = NULL; static char *kwlist[] = { (char *)"srad", (char *)"molid", (char *)"frame", (char *)"selected", (char *)"samples", (char *)"points", (char *)"restrict" }; if (!PyArg_ParseTupleAndKeywords(args, keywds, (char *)"fiiO!|iO!O!:atomselection.sasa", kwlist, &srad, &molid, &frame, &PyTuple_Type, &selobj, &samples, &PyList_Type, &pointsobj, &PyTuple_Type, &restrictobj)) return NULL; // validate srad if (srad < 0) { PyErr_SetString(PyExc_ValueError, (char *)"atomselect.sasa: srad must be non-negative."); return NULL; } // validate selection VMDApp *app = get_vmdapp(); AtomSel *sel = sel_from_py(molid, frame, selobj, app); if (!sel) return NULL; // fetch the radii and coordinates const float *radii = app->moleculeList->mol_from_id(sel->molid())->extraflt.data("radius"); const float *coords = sel->coordinates(app->moleculeList); // if samples was given and is valid, use it if (samples > 1) sampleptr = &samples; // if restrict is given, validate it AtomSel *restrictsel = NULL; if (restrictobj) { if (!(restrictsel = sel_from_py(molid, frame, restrictobj, app))) { delete sel; return NULL; } } // if points are requested, fetch them ResizeArray<float> sasapts; ResizeArray<float> *sasaptsptr = pointsobj ? &sasapts : NULL; // go! float sasa = 0; int rc = measure_sasa(sel, coords, radii, srad, &sasa, sasaptsptr, restrictsel, sampleptr); delete sel; delete restrictsel; if (rc) { PyErr_SetString(PyExc_ValueError, (char *)measure_error(rc)); return NULL; } // append surface points to the provided list object. if (pointsobj) { for (int i=0; i<sasapts.num(); i++) { PyList_Append(pointsobj, PyFloat_FromDouble(sasapts[i])); } } // return the total SASA. return PyFloat_FromDouble(sasa); }
static PyObject *py_align(PyObject *self, PyObject *args) { int selmol, selframe, refmol, refframe, movemol, moveframe; PyObject *selobj, *refobj, *moveobj, *weightobj = NULL; if (!PyArg_ParseTuple(args, (char *)"iiO!iiO!iiO!O:atomselection.align", &selmol, &selframe, &PyTuple_Type, &selobj, &refmol, &refframe, &PyTuple_Type, &refobj, &movemol, &moveframe, &PyTuple_Type, &moveobj, &weightobj)) return NULL; // check if movemol is -1. If so, use the sel molecule and timestep instead if (movemol == -1) { movemol = selmol; moveobj = NULL; } VMDApp *app = get_vmdapp(); AtomSel *sel=NULL, *ref=NULL, *move=NULL; if (!(sel = sel_from_py(selmol, selframe, selobj, app)) || !(ref = sel_from_py(refmol, refframe, refobj, app)) || !(move = sel_from_py(movemol, moveframe, moveobj, app))) { delete sel; delete ref; delete move; return NULL; } const float *selts, *refts; float *movets; if (!(selts = sel->coordinates(app->moleculeList)) || !(refts = ref->coordinates(app->moleculeList)) || !(movets = move->coordinates(app->moleculeList))) { delete sel; delete ref; delete move; PyErr_SetString(PyExc_ValueError, "No coordinates in selection"); return NULL; } float *weight = parse_weight(sel, weightobj); if (!weight) { delete sel; delete ref; delete move; return NULL; } // Find the matrix that aligns sel with ref. Apply the transformation to // the atoms in move. // XXX need to add support for the "order" parameter as in Tcl. Matrix4 mat; int rc = measure_fit(sel, ref, selts, refts, weight, NULL, &mat); delete [] weight; delete sel; delete ref; if (rc < 0) { delete move; PyErr_SetString(PyExc_ValueError, (char *)measure_error(rc)); return NULL; } for (int i=0; i<move->num_atoms; i++) { if (move->on[i]) { float *pos = movets+3*i; mat.multpoint3d(pos, pos); } } Molecule *mol = app->moleculeList->mol_from_id(move->molid()); mol->force_recalc(DrawMolItem::MOL_REGEN); delete move; Py_INCREF(Py_None); return Py_None; }
int main(int argc, char *argv[]) { int num_elem, num_sides; int n_threads, n_blocks_elem, n_blocks_reduction, n_blocks_sides; int i, n, n_p, timesteps, n_quad, n_quad1d; double dt, t, endtime; double *min_radius; double min_r; double *V1x, *V1y, *V2x, *V2y, *V3x, *V3y; double *sides_x1, *sides_x2; double *sides_y1, *sides_y2; double *r1_local, *r2_local, *w_local; double *s_r, *oned_w_local; int *left_elem, *right_elem; int *elem_s1, *elem_s2, *elem_s3; int *left_side_number, *right_side_number; FILE *mesh_file, *out_file; char line[100]; char *mesh_filename; char *out_filename; char *rho_out_filename; char *u_out_filename; char *v_out_filename; char *E_out_filename; char *outfile_base; int outfile_len; double *Uu1, *Uu2, *Uu3; double *Uv1, *Uv2, *Uv3; // get input endtime = -1; if (get_input(argc, argv, &n, ×teps, &endtime, &mesh_filename, &out_filename)) { return 1; } // TODO: this should be cleaner, obviously rho_out_filename = "output/uniform_rho.out"; u_out_filename = "output/uniform_u.out"; v_out_filename = "output/uniform_v.out"; E_out_filename = "output/uniform_E.out"; // set the order of the approximation & timestep n_p = (n + 1) * (n + 2) / 2; // open the mesh to get num_elem for allocations mesh_file = fopen(mesh_filename, "r"); if (!mesh_file) { printf("\nERROR: mesh file not found.\n"); return 1; } fgets(line, 100, mesh_file); sscanf(line, "%i", &num_elem); // allocate vertex points V1x = (double *) malloc(num_elem * sizeof(double)); V1y = (double *) malloc(num_elem * sizeof(double)); V2x = (double *) malloc(num_elem * sizeof(double)); V2y = (double *) malloc(num_elem * sizeof(double)); V3x = (double *) malloc(num_elem * sizeof(double)); V3y = (double *) malloc(num_elem * sizeof(double)); elem_s1 = (int *) malloc(num_elem * sizeof(int)); elem_s2 = (int *) malloc(num_elem * sizeof(int)); elem_s3 = (int *) malloc(num_elem * sizeof(int)); // TODO: these are too big; should be a way to figure out how many we actually need left_side_number = (int *) malloc(3*num_elem * sizeof(int)); right_side_number = (int *) malloc(3*num_elem * sizeof(int)); sides_x1 = (double *) malloc(3*num_elem * sizeof(double)); sides_x2 = (double *) malloc(3*num_elem * sizeof(double)); sides_y1 = (double *) malloc(3*num_elem * sizeof(double)); sides_y2 = (double *) malloc(3*num_elem * sizeof(double)); left_elem = (int *) malloc(3*num_elem * sizeof(int)); right_elem = (int *) malloc(3*num_elem * sizeof(int)); for (i = 0; i < 3*num_elem; i++) { right_elem[i] = -1; } // read in the mesh and make all the mappings read_mesh(mesh_file, &num_sides, num_elem, V1x, V1y, V2x, V2y, V3x, V3y, left_side_number, right_side_number, sides_x1, sides_y1, sides_x2, sides_y2, elem_s1, elem_s2, elem_s3, left_elem, right_elem); // close the file fclose(mesh_file); // initialize the gpu init_gpu(num_elem, num_sides, n_p, V1x, V1y, V2x, V2y, V3x, V3y, left_side_number, right_side_number, sides_x1, sides_y1, sides_x2, sides_y2, elem_s1, elem_s2, elem_s3, left_elem, right_elem); n_threads = 256; n_blocks_elem = (num_elem / n_threads) + ((num_elem % n_threads) ? 1 : 0); n_blocks_sides = (num_sides / n_threads) + ((num_sides % n_threads) ? 1 : 0); n_blocks_reduction = (num_elem / 256) + ((num_elem % 256) ? 1 : 0); // find the min inscribed circle preval_inscribed_circles(d_J, d_V1x, d_V1y, d_V2x, d_V2y, d_V3x, d_V3y, num_elem); min_radius = (double *) malloc(num_elem * sizeof(double)); /* // find the min inscribed circle. do it on the gpu if there are at least 256 elements if (num_elem >= 256) { //min_reduction<<<n_blocks_reduction, 256>>>(d_J, d_reduction, num_elem); cudaThreadSynchronize(); checkCudaError("error after min_jacobian."); // each block finds the smallest value, so need to sort through n_blocks_reduction min_radius = (double *) malloc(n_blocks_reduction * sizeof(double)); cudaMemcpy(min_radius, d_reduction, n_blocks_reduction * sizeof(double), cudaMemcpyDeviceToHost); min_r = min_radius[0]; for (i = 1; i < n_blocks_reduction; i++) { min_r = (min_radius[i] < min_r) ? min_radius[i] : min_r; } free(min_radius); } else { */ // just grab all the radii and sort them since there are so few of them min_radius = (double *) malloc(num_elem * sizeof(double)); memcpy(min_radius, d_J, num_elem * sizeof(double)); min_r = min_radius[0]; for (i = 1; i < num_elem; i++) { min_r = (min_radius[i] < min_r) ? min_radius[i] : min_r; } free(min_radius); //} // pre computations preval_jacobian(d_J, d_V1x, d_V1y, d_V2x, d_V2y, d_V3x, d_V3y, num_elem); preval_side_length(d_s_length, d_s_V1x, d_s_V1y, d_s_V2x, d_s_V2y, num_sides); //cudaThreadSynchronize(); preval_normals(d_Nx, d_Ny, d_s_V1x, d_s_V1y, d_s_V2x, d_s_V2y, d_V1x, d_V1y, d_V2x, d_V2y, d_V3x, d_V3y, d_left_side_number, num_sides); preval_normals_direction(d_Nx, d_Ny, d_V1x, d_V1y, d_V2x, d_V2y, d_V3x, d_V3y, d_left_elem, d_left_side_number, num_sides); preval_partials(d_V1x, d_V1y, d_V2x, d_V2y, d_V3x, d_V3y, d_xr, d_yr, d_xs, d_ys, num_elem); // get the correct quadrature rules for this scheme set_quadrature(n, &r1_local, &r2_local, &w_local, &s_r, &oned_w_local, &n_quad, &n_quad1d); // evaluate the basis functions at those points and store on GPU preval_basis(r1_local, r2_local, s_r, w_local, oned_w_local, n_quad, n_quad1d, n_p); // initial conditions init_conditions(d_c, d_J, d_V1x, d_V1y, d_V2x, d_V2y, d_V3x, d_V3y, n_quad, n_p, num_elem); printf("Computing...\n"); printf(" ? %i degree polynomial interpolation (n_p = %i)\n", n, n_p); printf(" ? %i precomputed basis points\n", n_quad * n_p); printf(" ? %i elements\n", num_elem); printf(" ? %i sides\n", num_sides); printf(" ? min radius = %lf\n", min_r); printf(" ? endtime = %lf\n", endtime); time_integrate_rk4(n_quad, n_quad1d, n_p, n, num_elem, num_sides, endtime, min_r); // evaluate at the vertex points and copy over data Uu1 = (double *) malloc(num_elem * sizeof(double)); Uu2 = (double *) malloc(num_elem * sizeof(double)); Uu3 = (double *) malloc(num_elem * sizeof(double)); Uv1 = (double *) malloc(num_elem * sizeof(double)); Uv2 = (double *) malloc(num_elem * sizeof(double)); Uv3 = (double *) malloc(num_elem * sizeof(double)); // evaluate rho and write to file eval_u(d_c, d_Uv1, d_Uv2, d_Uv3, num_elem, n_p, 0); memcpy(Uv1, d_Uv1, num_elem * sizeof(double)); memcpy(Uv2, d_Uv2, num_elem * sizeof(double)); memcpy(Uv3, d_Uv3, num_elem * sizeof(double)); out_file = fopen(rho_out_filename , "w"); fprintf(out_file, "View \"Density \" {\n"); for (i = 0; i < num_elem; i++) { fprintf(out_file, "ST (%lf,%lf,0,%lf,%lf,0,%lf,%lf,0) {%lf,%lf,%lf};\n", V1x[i], V1y[i], V2x[i], V2y[i], V3x[i], V3y[i], d_Uv1[i], d_Uv2[i], d_Uv3[i]); } fprintf(out_file,"};"); fclose(out_file); // evaluate the u and v vectors and write to file eval_u_velocity(d_c, d_Uv1, d_Uv2, d_Uv3, num_elem, n_p, 1); memcpy(Uu1, d_Uv1, num_elem * sizeof(double)); memcpy(Uu2, d_Uv2, num_elem * sizeof(double)); memcpy(Uu3, d_Uv3, num_elem * sizeof(double)); eval_u_velocity(d_c, d_Uv1, d_Uv2, d_Uv3, num_elem, n_p, 2); memcpy(Uv1, d_Uv1, num_elem * sizeof(double)); memcpy(Uv2, d_Uv2, num_elem * sizeof(double)); memcpy(Uv3, d_Uv3, num_elem * sizeof(double)); out_file = fopen(u_out_filename , "w"); fprintf(out_file, "View \"u \" {\n"); for (i = 0; i < num_elem; i++) { fprintf(out_file, "VT (%lf,%lf,0,%lf,%lf,0,%lf,%lf,0) {%lf,%lf,0,%lf,%lf,0,%lf,%lf,0};\n", V1x[i], V1y[i], V2x[i], V2y[i], V3x[i], V3y[i], Uu1[i], Uv1[i], Uu2[i], Uv2[i], Uu3[i], Uv3[i]); } fprintf(out_file,"};"); fclose(out_file); // evaluate E and write to file eval_u(d_c, d_Uv1, d_Uv2, d_Uv3, num_elem, n_p, 3); memcpy(Uv1, d_Uv1, num_elem * sizeof(double)); memcpy(Uv2, d_Uv2, num_elem * sizeof(double)); memcpy(Uv3, d_Uv3, num_elem * sizeof(double)); out_file = fopen(E_out_filename , "w"); fprintf(out_file, "View \"E \" {\n"); for (i = 0; i < num_elem; i++) { fprintf(out_file, "ST (%lf,%lf,0,%lf,%lf,0,%lf,%lf,0) {%lf,%lf,%lf};\n", V1x[i], V1y[i], V2x[i], V2y[i], V3x[i], V3y[i], Uv1[i], Uv2[i], Uv3[i]); } fprintf(out_file,"};"); fclose(out_file); // plot pressure eval_p(d_c, d_Uv1, d_Uv2, d_Uv3, num_elem, n_p, 3); memcpy(Uv1, d_Uv1, num_elem * sizeof(double)); memcpy(Uv2, d_Uv2, num_elem * sizeof(double)); memcpy(Uv3, d_Uv3, num_elem * sizeof(double)); out_file = fopen("output/p.out" , "w"); fprintf(out_file, "View \"E \" {\n"); for (i = 0; i < num_elem; i++) { fprintf(out_file, "ST (%lf,%lf,0,%lf,%lf,0,%lf,%lf,0) {%lf,%lf,%lf};\n", V1x[i], V1y[i], V2x[i], V2y[i], V3x[i], V3y[i], Uv1[i], Uv2[i], Uv3[i]); } fprintf(out_file,"};"); fclose(out_file); measure_error(d_c, d_Uv1, d_Uv2, d_Uv3, d_V1x, d_V1y, d_V2x, d_V2y, d_V3x, d_V3y, num_elem, n_p); memcpy(Uv1, d_Uv1, num_elem * sizeof(double)); memcpy(Uv2, d_Uv2, num_elem * sizeof(double)); memcpy(Uv3, d_Uv3, num_elem * sizeof(double)); out_file = fopen("output/p_error.out" , "w"); fprintf(out_file, "View \"p \" {\n"); for (i = 0; i < num_elem; i++) { fprintf(out_file, "ST (%lf,%lf,0,%lf,%lf,0,%lf,%lf,0) {%lf,%lf,%lf};\n", V1x[i], V1y[i], V2x[i], V2y[i], V3x[i], V3y[i], Uv1[i], Uv2[i], Uv3[i]); } fprintf(out_file,"};"); fclose(out_file); // free variables free_gpu(); free(Uu1); free(Uu2); free(Uu3); free(Uv1); free(Uv2); free(Uv3); free(V1x); free(V1y); free(V2x); free(V2y); free(V3x); free(V3y); free(elem_s1); free(elem_s2); free(elem_s3); free(sides_x1); free(sides_x2); free(sides_y1); free(sides_y2); free(left_elem); free(right_elem); free(left_side_number); free(right_side_number); free(r1_local); free(r2_local); free(w_local); free(s_r); free(oned_w_local); return 0; }