void amr_grid_add_local_patch(amr_grid_t* grid, int i, int j, int k) { ASSERT(!grid->finalized); DECLARE_3D_ARRAY(patch_type_t, patch_types, grid->patch_types, grid->nx, grid->ny, grid->nz); patch_type_t patch_type = patch_types[i][j][k]; ASSERT(patch_type == NO_PATCH); patch_types[i][j][k] = LOCAL_SAME_LEVEL; ++(grid->num_local_patches); }
void amr_grid_add_remote_patch(amr_grid_t* grid, int i, int j, int k, int remote_owner) { ASSERT(!grid->finalized); DECLARE_3D_ARRAY(patch_type_t, patch_types, grid->patch_types, grid->nx, grid->ny, grid->nz); patch_type_t patch_type = patch_types[i][j][k]; ASSERT(patch_type == NO_PATCH); patch_types[i][j][k] = REMOTE_SAME_LEVEL; DECLARE_3D_ARRAY(int, remote_owners, grid->remote_owners, grid->nx, grid->ny, grid->nz); remote_owners[i][j][k] = remote_owner; }
static void compute_integral(gmls_functional_t* functional, real_t t, multicomp_poly_basis_t* poly_basis, real_t* solution, point_t* quad_points, real_t* quad_weights, vector_t* quad_normals, int num_quad_points, real_t* lambdas) { START_FUNCTION_TIMER(); bool on_boundary = (quad_normals != NULL); // Loop through the points and compute the lambda matrix of functional // approximants. int num_comp = functional->num_comp; int basis_dim = multicomp_poly_basis_dim(poly_basis); memset(lambdas, 0, sizeof(real_t) * num_comp * basis_dim * num_comp); DECLARE_3D_ARRAY(real_t, lam, lambdas, num_comp, basis_dim, num_comp); for (int q = 0; q < num_quad_points; ++q) { point_t* xq = &quad_points[q]; real_t wq = quad_weights[q]; vector_t* nq = (on_boundary) ? &quad_normals[q] : NULL; // Now compute the (multi-component) integrands for the functional at // this point. real_t integrands[num_comp*basis_dim*num_comp]; functional->vtable.eval_integrands(functional->context, t, poly_basis, xq, nq, solution, integrands); // Integrate. DECLARE_3D_ARRAY(real_t, I, integrands, num_comp, num_comp, basis_dim); for (int i = 0; i < num_comp; ++i) for (int j = 0; j < basis_dim; ++j) for (int k = 0; k < num_comp; ++k) lam[i][j][k] += wq * I[i][k][j]; } STOP_FUNCTION_TIMER(); }
void amr_grid_finalize(amr_grid_t* grid) { ASSERT(!grid->finalized); // Make sure that we have accounted for all patches in our construction // process. DECLARE_3D_ARRAY(patch_type_t, patch_types, grid->patch_types, grid->nx, grid->ny, grid->nz); if (grid->num_local_patches < (grid->nx * grid->ny * grid->nz)) { for (int i = 0; i < grid->nx; ++i) { for (int j = 0; j < grid->ny; ++j) { for (int k = 0; k < grid->nz; ++k) { if (patch_types[i][j][k] == NO_PATCH) polymec_error("amr_grid_finalize: no local or remote patch at (%d, %d, %d).", i, j, k); } } } } // Make an array of indices for locally-present patches. grid->local_patch_indices = polymec_malloc(sizeof(int) * 3 * grid->num_local_patches); int l = 0; for (int i = 0; i < grid->nx; ++i) { for (int j = 0; j < grid->ny; ++j) { for (int k = 0; k < grid->nz; ++k, ++l) { grid->local_patch_indices[3*l] = i; grid->local_patch_indices[3*l+1] = j; grid->local_patch_indices[3*l+2] = k; } } } // Establish our remote copying pattern. grid->cell_ex = grid_cell_exchanger_new(grid); grid->x_face_ex = grid_x_face_exchanger_new(grid); grid->y_face_ex = grid_y_face_exchanger_new(grid); grid->z_face_ex = grid_z_face_exchanger_new(grid); grid->x_edge_ex = grid_x_edge_exchanger_new(grid); grid->y_edge_ex = grid_y_edge_exchanger_new(grid); grid->z_edge_ex = grid_z_edge_exchanger_new(grid); grid->node_ex = grid_node_exchanger_new(grid); grid->finalized = true; }
static void elastic_eval_integrands(void* context, real_t t, multicomp_poly_basis_t* basis, point_t* x, vector_t* n, real_t* solution, real_t* integrands) { elastic_t* elastic = context; int dim = multicomp_poly_basis_dim(basis); // Evaluate the polynomial derivatives. All the components use the // same basis, so we don't have to distinguish between them real_t dpdx[dim], dpdy[dim], dpdz[dim]; multicomp_poly_basis_compute(basis, 0, 1, 0, 0, x, dpdx); multicomp_poly_basis_compute(basis, 0, 0, 1, 0, x, dpdy); multicomp_poly_basis_compute(basis, 0, 0, 0, 1, x, dpdz); // Evaluate the D and N matrices. real_t D[6*6], N[3*6]; eval_stress_strain_matrix(elastic->E, elastic->nu, D); eval_normal_vector_matrix(n, N); memset(integrands, 0, sizeof(int) * dim); DECLARE_3D_ARRAY(real_t, I, integrands, 3, 3, dim); for (int k = 0; k < dim; ++k) { // Evaluate the P matrix for the kth vector. real_t P[6*3]; eval_basis_matrix(dpdx[k], dpdy[k], dpdz[k], P); // Compute N * D * P (a 3x3 matrix) for the kth vector. real_t DP[6*3]; real_t alpha = 1.0, beta = 0.0; char no_trans = 'N'; int six = 6, three = 3; rgemm(&no_trans, &no_trans, &six, &three, &six, &alpha, D, &six, P, &six, &beta, DP, &six); real_t NDP[6*3]; rgemm(&no_trans, &no_trans, &three, &three, &six, &alpha, N, &three, DP, &six, &beta, NDP, &three); I[0][0][k] = NDP[0]; I[0][1][k] = NDP[3]; I[0][2][k] = NDP[6]; I[1][0][k] = NDP[1]; I[1][1][k] = NDP[4]; I[1][2][k] = NDP[7]; I[2][0][k] = NDP[2]; I[2][1][k] = NDP[5]; I[2][2][k] = NDP[8]; } }
void test_real_array3(void** state) { void* storage = polymec_malloc(sizeof(real_t)*10*10*10); DECLARE_3D_ARRAY(real_t, a, storage, 10, 10, 10); for (int i = 0; i < 10; ++i) for (int j = 0; j < 10; ++j) for (int k = 0; k < 10; ++k) a[i][j][k] = 100*i + 10*j + k; for (int i = 0; i < 10; ++i) { for (int j = 0; j < 10; ++j) { for (int k = 0; k < 10; ++k) { assert_real_equal(100*i + 10*j + k, a[i][j][k]); } } } polymec_free(storage); }
// Returns the number of values that patch (i, j, k) transmits to patch (i1, j1, k1). // The patch mask identifies those kinds of patches included in the total. static int num_transmitted_patch_values(amr_grid_t* grid, amr_grid_data_centering_t centering, int patch_mask, int i, int j, int k, int i1, int j1, int k1) { // Make sure the patches abut one another in index space. if ((ABS(i - i1) + ABS(j - j1) + ABS(k - k1)) > 1) return 0; // Figure out how many values are on a side. int x_padding, y_padding, z_padding; switch(centering) { case AMR_GRID_CELL: x_padding = y_padding = z_padding = 0; break; case AMR_GRID_X_FACE: x_padding = 1; y_padding = z_padding = 0; break; case AMR_GRID_Y_FACE: y_padding = 1; x_padding = z_padding = 0; break; case AMR_GRID_Z_FACE: z_padding = 1; x_padding = y_padding = 0; break; case AMR_GRID_X_EDGE: x_padding = 0; y_padding = z_padding = 1; break; case AMR_GRID_Y_EDGE: y_padding = 0; x_padding = z_padding = 1; break; case AMR_GRID_Z_EDGE: z_padding = 0; x_padding = y_padding = 1; break; case AMR_GRID_NODE: x_padding = y_padding = z_padding = 1; } int px, py, pz; amr_grid_get_patch_size(grid, &px, &py, &pz); int x_size = px + x_padding, y_size = py + y_padding, z_size = pz + z_padding; // Handle neighbor grid cases, if any. amr_grid_t* grid1 = grid; int cross_section_size = 0; if (i1 == -1) { grid1 = (grid->neighbors[0] != NULL) ? grid->neighbors[0] : NULL; i1 = grid1->nx - 1; cross_section_size = y_size * z_size; } else if (i1 == grid->px) { grid1 = (grid->neighbors[1] != NULL) ? grid->neighbors[1] : NULL; i1 = 0; cross_section_size = y_size * z_size; } else if (j1 == -1) { grid1 = (grid->neighbors[2] != NULL) ? grid->neighbors[2] : NULL; j1 = grid1->ny - 1; cross_section_size = x_size * z_size; } else if (j1 == grid->py) { grid1 = (grid->neighbors[3] != NULL) ? grid->neighbors[3] : NULL; j1 = 0; cross_section_size = x_size * z_size; } else if (k1 == -1) { grid1 = (grid->neighbors[4] != NULL) ? grid->neighbors[4] : NULL; k1 = grid1->nz - 1; cross_section_size = x_size * y_size; } else if (k1 == grid->px) { grid1 = (grid->neighbors[5] != NULL) ? grid->neighbors[5] : NULL; k1 = 0; cross_section_size = x_size * y_size; } if (grid1 == NULL) return 0; DECLARE_3D_ARRAY(patch_type_t, patch_types, grid1->patch_types, grid1->nx, grid1->ny, grid1->nz); patch_type_t patch_type = patch_types[i1][j1][k1]; if ((patch_mask | patch_type) == 0) return 0; return cross_section_size; }
bool amr_grid_has_local_patch(amr_grid_t* grid, int i, int j, int k) { DECLARE_3D_ARRAY(patch_type_t, patch_types, grid->patch_types, grid->nx, grid->ny, grid->nz); return (patch_types[i][j][k] == LOCAL_SAME_LEVEL); }
// Copies data from the patch buffer to the patches in the given grid. static void patch_buffer_copy_out(patch_buffer_t* buffer, amr_grid_data_t* grid_data) { amr_grid_t* grid = amr_grid_data_grid(grid_data); amr_grid_data_centering_t centering = amr_grid_data_centering(grid_data); int num_components = amr_grid_data_num_components(grid_data); int num_ghosts = amr_grid_data_num_ghosts(grid_data); // Now count up the sent data for each patch. int local_mask = LOCAL_SAME_LEVEL | LOCAL_FINER_LEVEL | LOCAL_COARSER_LEVEL; int pos = 0, i, j, k, p = 0; amr_patch_t* patch; DECLARE_3D_ARRAY(patch_type_t, patch_types, grid->patch_types, grid->nx, grid->ny, grid->nz); while (amr_grid_data_next_local_patch(grid_data, &pos, &i, &j, &k, &patch)) { patch_type_t patch_type = patch_types[i][j][k]; if (patch_type == LOCAL_SAME_LEVEL) polymec_error("patch_buffer_copy_out: adaptive mesh refinement is not yet supported!"); DECLARE_AMR_PATCH_ARRAY(array, patch); int offset = buffer->patch_receive_offsets[p]; // Copy out -x values. int num_values = num_transmitted_patch_values(grid, centering, local_mask, i, j, k, i-1, j, k); for (int j = patch->j1; j < patch->j2; ++j) for (int k = patch->k1; k < patch->k2; ++k) for (int g = 0; g < num_ghosts; ++g) for (int c = 0; c < num_components; ++c, ++offset) array[g][j][k][c] = buffer->data[offset]; // Copy out +x values. num_values = num_transmitted_patch_values(grid, centering, local_mask, i, j, k, i+1, j, k); for (int j = patch->j1; j < patch->j2; ++j) for (int k = patch->k1; k < patch->k2; ++k) for (int g = 0; g < num_ghosts; ++g) for (int c = 0; c < num_components; ++c, ++offset) array[patch->i2+num_ghosts-g-1][j][k][c] = buffer->data[offset]; // Copy out -y values. num_values = num_transmitted_patch_values(grid, centering, local_mask, i, j, k, i, j-1, k); for (int i = patch->i1; i < patch->i2; ++i) for (int k = patch->k1; k < patch->k2; ++k) for (int g = 0; g < num_ghosts; ++g) for (int c = 0; c < num_components; ++c, ++offset) array[i][g][k][c] = buffer->data[offset]; // Copy out +y values. num_values = num_transmitted_patch_values(grid, centering, local_mask, i, j, k, i, j+1, k); for (int i = patch->i1; i < patch->i2; ++i) for (int k = patch->k1; k < patch->k2; ++k) for (int g = 0; g < num_ghosts; ++g) for (int c = 0; c < num_components; ++c, ++offset) array[i][patch->j2+num_ghosts-g-1][k][c] = buffer->data[offset]; // Copy out -z values. num_values = num_transmitted_patch_values(grid, centering, local_mask, i, j, k, i, j, k-1); for (int i = patch->i1; i < patch->i2; ++i) for (int j = patch->j1; j < patch->j2; ++j) for (int g = 0; g < num_ghosts; ++g) for (int c = 0; c < num_components; ++c, ++offset) array[i][j][g][c] = buffer->data[offset]; // Copy out +z values. num_values = num_transmitted_patch_values(grid, centering, local_mask, i, j, k, i, j, k+1); for (int i = patch->i1; i < patch->i2; ++i) for (int j = patch->j1; j < patch->j2; ++j) for (int g = 0; g < num_ghosts; ++g) for (int c = 0; c < num_components; ++c, ++offset) array[i][j][patch->k2+num_ghosts-g-1][c] = buffer->data[offset]; ASSERT(offset == buffer->patch_receive_offsets[p+1]); ++p; } }