fe_mesh_t* fe_mesh_new(MPI_Comm comm, int num_nodes) { ASSERT(num_nodes >= 4); fe_mesh_t* mesh = polymec_malloc(sizeof(fe_mesh_t)); mesh->comm = comm; mesh->num_nodes = num_nodes; mesh->blocks = ptr_array_new(); mesh->block_names = string_array_new(); mesh->block_elem_offsets = int_array_new(); int_array_append(mesh->block_elem_offsets, 0); mesh->node_coords = polymec_malloc(sizeof(point_t) * mesh->num_nodes); memset(mesh->node_coords, 0, sizeof(point_t) * mesh->num_nodes); mesh->num_faces = 0; mesh->face_node_offsets = NULL; mesh->face_nodes = NULL; mesh->face_edge_offsets = NULL; mesh->face_edges = NULL; mesh->num_edges = 0; mesh->edge_node_offsets = NULL; mesh->edge_nodes = NULL; mesh->elem_sets = tagger_new(); mesh->face_sets = tagger_new(); mesh->edge_sets = tagger_new(); mesh->node_sets = tagger_new(); mesh->side_sets = tagger_new(); return mesh; }
/* assumes static lock is held */ static inline bool quark_init_if_needed() { if (quark_string_hash == NULL) { quark_string_hash = create_hashtable(31, string_hash, string_eq); quark_string_index = ptr_array_new(10); ptr_array_append(quark_string_index, NULL); return true; } return false; }
static ptr_array _gather_roots(STATE, cpu c) { ptr_array roots; roots = ptr_array_new(NUM_OF_GLOBALS + 100); memcpy(roots->array, state->global, sizeof(struct rubinius_globals)); roots->length = NUM_OF_GLOBALS; cpu_add_roots(state, c, roots); /* truncate the free_context list since we don't care about them after we've collected anyway */ return roots; }
ode_integrator_t* functional_euler_ode_integrator_new(real_t theta, MPI_Comm comm, int num_local_values, int num_remote_values, void* context, int (*rhs)(void* context, real_t t, real_t* x, real_t* xdot), void (*dtor)(void* context)) { ASSERT(theta >= 0.0); ASSERT(theta <= 1.0); ASSERT(num_local_values > 0); ASSERT(num_remote_values >= 0); ASSERT(rhs != NULL); euler_ode_t* integ = polymec_malloc(sizeof(euler_ode_t)); integ->theta = theta; integ->comm = comm; integ->num_local_values = num_local_values; integ->num_remote_values = num_remote_values; integ->context = context; integ->rhs = rhs; integ->dtor = dtor; integ->newton = NULL; integ->observers = ptr_array_new(); integ->x_old = polymec_malloc(sizeof(real_t) * (num_local_values + num_remote_values)); integ->x_new = polymec_malloc(sizeof(real_t) * (num_local_values + num_remote_values)); integ->f1 = polymec_malloc(sizeof(real_t) * num_local_values); // no ghosts here! integ->f2 = polymec_malloc(sizeof(real_t) * num_local_values); // no ghosts here! ode_integrator_vtable vtable = {.step = euler_step, .advance = euler_advance, .dtor = euler_dtor}; int order = 1; if (theta == 0.5) order = 2; char name[1024]; snprintf(name, 1024, "Functional Euler integrator(theta = %g)", theta); ode_integrator_t* I = ode_integrator_new(name, integ, vtable, order); // Set default iteration criteria. euler_ode_integrator_set_max_iterations(I, 100); euler_ode_integrator_set_tolerances(I, 1e-4, 1.0); euler_ode_integrator_set_lp_convergence_norm(I, 0); return I; }
ode_integrator_t* newton_euler_ode_integrator_new(MPI_Comm comm, int num_local_values, int num_remote_values, void* context, int (*rhs)(void* context, real_t t, real_t* x, real_t* xdot), void (*dtor)(void* context), newton_pc_t* precond, newton_krylov_t solver_type, int max_krylov_dim) { ASSERT(num_local_values > 0); ASSERT(num_remote_values >= 0); ASSERT(max_krylov_dim > 3); ASSERT(rhs != NULL); euler_ode_t* integ = polymec_malloc(sizeof(euler_ode_t)); integ->theta = -FLT_MAX; integ->comm = comm; integ->num_local_values = num_local_values; integ->num_remote_values = num_remote_values; integ->context = context; integ->rhs = rhs; integ->dtor = dtor; // Set up the Newton solver. newton_solver_vtable newton_vtable = {.eval = evaluate_residual}; integ->newton = newton_solver_new(comm, num_local_values, num_remote_values, integ, newton_vtable, precond, solver_type, max_krylov_dim, 5); integ->observers = ptr_array_new(); integ->x_old = polymec_malloc(sizeof(real_t) * (num_local_values + num_remote_values)); integ->x_new = polymec_malloc(sizeof(real_t) * (num_local_values + num_remote_values)); integ->f1 = integ->f2 = NULL; ode_integrator_vtable vtable = {.step = newton_euler_step, .advance = euler_advance, .dtor = euler_dtor}; int order = 1; ode_integrator_t* I = ode_integrator_new("Backward Euler Newton integrator", integ, vtable, order); // Set default iteration criteria. euler_ode_integrator_set_max_iterations(I, 100); return I; }
void str_grid_cell_filler_insert(str_grid_cell_filler_t* cell_filler, int i, int j, int k, str_grid_patch_filler_t* patch_filler) { int index = patch_index(cell_filler, i, j, k); ASSERT(str_grid_has_patch(cell_filler->grid, i, j, k)); ptr_array_t** fillers_p = (ptr_array_t**)int_ptr_unordered_map_get(cell_filler->patch_fillers, index); ptr_array_t* fillers; if (fillers_p != NULL) fillers = *fillers_p; else { fillers = ptr_array_new(); int_ptr_unordered_map_insert_with_v_dtor(cell_filler->patch_fillers, index, fillers, DTOR(ptr_array_free)); } ptr_array_append(fillers, patch_filler); }
fe_mesh_t* fe_mesh_clone(fe_mesh_t* mesh) { fe_mesh_t* copy = polymec_malloc(sizeof(fe_mesh_t)); copy->comm = mesh->comm; copy->num_nodes = mesh->num_nodes; copy->blocks = ptr_array_new(); for (int i = 0; i < mesh->blocks->size; ++i) copy->blocks->data[i] = fe_block_clone(mesh->blocks->data[i]); copy->block_names = string_array_new(); for (int i = 0; i < mesh->block_names->size; ++i) copy->block_names->data[i] = string_dup(mesh->block_names->data[i]); copy->block_elem_offsets = int_array_new(); for (int i = 0; i < mesh->block_elem_offsets->size; ++i) int_array_append(copy->block_elem_offsets, mesh->block_elem_offsets->data[i]); copy->node_coords = polymec_malloc(sizeof(point_t) * copy->num_nodes); memcpy(copy->node_coords, mesh->node_coords, sizeof(point_t) * copy->num_nodes); return copy; }
amr_data_hierarchy_t* amr_data_hierarchy_new(amr_grid_hierarchy_t* grids, int num_components, int num_ghosts) { ASSERT(num_components > 0); amr_data_hierarchy_t* data = polymec_malloc(sizeof(amr_data_hierarchy_t)); data->grids = grids; data->num_components = num_components; data->num_ghosts = num_ghosts; data->grid_data = ptr_array_new(); int pos = 0; amr_grid_t* level; while (amr_grid_hierarchy_next_coarsest(grids, &pos, &level)) { amr_grid_data_t* grid_data = amr_grid_data_new(level, AMR_GRID_CELL, data->num_components, data->num_ghosts); ptr_array_append_with_dtor(data->grid_data, grid_data, DTOR(amr_grid_data_free)); } return data; }
void create_boundary_generators(ptr_array_t* surface_points, ptr_array_t* surface_normals, ptr_array_t* surface_tags, point_t** boundary_generators, int* num_boundary_generators, char*** tag_names, int_array_t*** tags, int* num_tags) { ASSERT(surface_points->size >= 4); // surface must be closed! ASSERT(surface_points->size == surface_normals->size); ASSERT(surface_points->size == surface_tags->size); int num_surface_points = surface_points->size; // Compute the minimum distance from each surface point to its neighbors. real_t* h_min = polymec_malloc(sizeof(real_t) * num_surface_points); { // Dump the surface points into a kd-tree. point_t* surf_points = polymec_malloc(sizeof(point_t) * num_surface_points); for (int i = 0; i < num_surface_points; ++i) surf_points[i] = *((point_t*)surface_points->data[i]); kd_tree_t* tree = kd_tree_new(surf_points, num_surface_points); int neighbors[2]; for (int i = 0; i < num_surface_points; ++i) { // Find the "nearest 2" points to the ith surface point--the first is // the point itself, and the second is its nearest neighbor. // FIXME: Serious memory error within here. We work around it for // FIXME: the moment by freshing the tree pointer, which is // FIXME: corrupted. ICK! kd_tree_t* tree_p = tree; kd_tree_nearest_n(tree, &surf_points[i], 2, neighbors); tree = tree_p; ASSERT(neighbors[0] == i); ASSERT(neighbors[1] >= 0); ASSERT(neighbors[1] < num_surface_points); h_min[i] = point_distance(&surf_points[i], &surf_points[neighbors[1]]); } // Clean up. kd_tree_free(tree); polymec_free(surf_points); } // Generate boundary points for each surface point based on how many // surfaces it belongs to. ptr_array_t* boundary_points = ptr_array_new(); string_int_unordered_map_t* tag_indices = string_int_unordered_map_new(); ptr_array_t* boundary_tags = ptr_array_new(); for (int i = 0; i < num_surface_points; ++i) { // Add any tags from this point to the set of existing boundary tags. string_slist_t* tags = surface_tags->data[i]; for (string_slist_node_t* t_iter = tags->front; t_iter != NULL; t_iter = t_iter->next) string_int_unordered_map_insert(tag_indices, t_iter->value, tag_indices->size); // Retrieve the surface point. point_t* x_surf = surface_points->data[i]; // Retrieve the list of normal vectors for this surface point. ptr_slist_t* normal_list = surface_normals->data[i]; int num_normals = normal_list->size; vector_t normals[num_normals]; int n_offset = 0; for (ptr_slist_node_t* n_iter = normal_list->front; n_iter != NULL; n_iter = n_iter->next) normals[n_offset++] = *((vector_t*)n_iter->value); // For now, let's keep things relatively simple. if (num_normals > 2) { polymec_error("create_boundary_generators: Too many normal vectors (%d) for surface point %d at (%g, %g, %g)", num_normals, i, x_surf->x, x_surf->y, x_surf->z); } // Create boundary points based on this list of normals. if (num_normals == 1) { // This point only belongs to one surface, so we create boundary points // on either side of it. point_t* x_out = polymec_malloc(sizeof(point_t)); x_out->x = x_surf->x + h_min[i]*normals[0].x; x_out->y = x_surf->y + h_min[i]*normals[0].y; x_out->z = x_surf->z + h_min[i]*normals[0].z; ptr_array_append_with_dtor(boundary_points, x_out, polymec_free); point_t* x_in = polymec_malloc(sizeof(point_t)); x_in->x = x_surf->x - h_min[i]*normals[0].x; x_in->y = x_surf->y - h_min[i]*normals[0].y; x_in->z = x_surf->z - h_min[i]*normals[0].z; ptr_array_append_with_dtor(boundary_points, x_in, polymec_free); } else if (num_normals == 2) { // This point appears at the interface between two surfaces. // (Or so it seems.) ASSERT(vector_dot(&normals[0], &normals[1]) < 0.0); point_t* x1 = polymec_malloc(sizeof(point_t)); x1->x = x_surf->x + h_min[i]*normals[0].x; x1->y = x_surf->y + h_min[i]*normals[0].y; x1->z = x_surf->z + h_min[i]*normals[0].z; ptr_array_append_with_dtor(boundary_points, x1, polymec_free); point_t* x2 = polymec_malloc(sizeof(point_t)); x2->x = x_surf->x - h_min[i]*normals[1].x; x2->y = x_surf->y - h_min[i]*normals[1].y; x2->z = x_surf->z - h_min[i]*normals[1].z; ptr_array_append_with_dtor(boundary_points, x2, polymec_free); } // Tag the boundary point appropriately. ptr_array_append(boundary_tags, tags); // Borrowed ref to tags. } // Move the surface points into a contiguous array. *boundary_generators = polymec_malloc(sizeof(point_t) * boundary_points->size); *num_boundary_generators = boundary_points->size; for (int i = 0; i < boundary_points->size; ++i) { (*boundary_generators)[i] = *((point_t*)boundary_points->data[i]); } // Transcribe the tags. *tag_names = polymec_malloc(sizeof(char*) * tag_indices->size); *tags = polymec_malloc(sizeof(int_array_t*) * tag_indices->size); *num_tags = tag_indices->size; char* tag_name; int pos = 0, tag_index; while (string_int_unordered_map_next(tag_indices, &pos, &tag_name, &tag_index)) { (*tag_names)[tag_index] = string_dup(tag_name); (*tags)[tag_index] = int_array_new(); for (int j = 0; j < *num_boundary_generators; ++j) int_array_append((*tags)[tag_index], tag_index); } // Clean up. string_int_unordered_map_free(tag_indices); polymec_free(h_min); }
amr_grid_t* amr_grid_new(MPI_Comm comm, int nx, int ny, int nz, int px, int py, int pz, bool periodic_in_x, bool periodic_in_y, bool periodic_in_z) { ASSERT(nx > 0); ASSERT(ny > 0); ASSERT(nz > 0); ASSERT(px > 0); ASSERT(py > 0); ASSERT(pz > 0); amr_grid_t* grid = polymec_malloc(sizeof(amr_grid_t)); grid->nx = nx; grid->ny = ny; grid->nz = nz; grid->px = px; grid->py = py; grid->pz = pz; grid->x_periodic = periodic_in_x; grid->y_periodic = periodic_in_y; grid->z_periodic = periodic_in_z; grid->num_local_patches = 0; grid->local_patch_indices = NULL; grid->patch_types = polymec_malloc(sizeof(patch_type_t) * nx * ny * nz); grid->remote_owners = polymec_malloc(sizeof(int) * nx * ny * nz); grid->comm = comm; for (int i = 0; i < nx * ny * nz; ++i) { grid->patch_types[i] = NO_PATCH; grid->remote_owners[i] = -1; } grid->ref_ratio = 0; grid->coarser = NULL; grid->coarse_interpolator = NULL; grid->finer = NULL; grid->fine_interpolator = NULL; for (int n = 0; n < 6; ++n) { grid->neighbors[n] = NULL; grid->neighbor_interpolators[n] = NULL; } grid->finalized = false; grid->cell_ex = NULL; grid->x_face_ex = NULL; grid->y_face_ex = NULL; grid->z_face_ex = NULL; grid->x_edge_ex = NULL; grid->y_edge_ex = NULL; grid->z_edge_ex = NULL; grid->node_ex = NULL; for (int centering = 0; centering < 8; ++centering) grid->local_buffers[centering] = ptr_array_new(); grid->pending_data = int_ptr_unordered_map_new(); return grid; }