fvm_neighborhood_t * fvm_neighborhood_create(void) #endif { double w_start, w_end, cpu_start, cpu_end; fvm_neighborhood_t *n = NULL; /* Timer start */ w_start = cs_timer_wtime(); cpu_start = cs_timer_cpu_time(); /* Allocate and initialize */ BFT_MALLOC(n, 1, fvm_neighborhood_t); n->n_elts = 0; n->elt_num = NULL; n->neighbor_index = NULL; n->neighbor_num = NULL; #if defined(HAVE_MPI) n->comm = comm; #endif /* Algorithm options */ n->max_tree_depth = 30; /* defaults */ n->leaf_threshold = 30; n->max_box_ratio = 10.0; n->max_box_ratio_distrib = 6.0; _init_bt_statistics(&(n->bt_stats)); /* Timer end */ w_end = cs_timer_wtime(); cpu_end = cs_timer_cpu_time(); n->cpu_time[0] = cpu_end - cpu_start; /* build time */ n->wtime[0] = w_end - w_start; n->cpu_time[1] = 0.0; /* query */ n->wtime[1] = 0.0; /* Return structure */ return n; }
static cs_thermal_table_t * _thermal_table_create(void) { cs_thermal_table_t *tt = NULL; BFT_MALLOC(tt, 1, cs_thermal_table_t); tt->material = NULL; tt->method = NULL; tt->reference = NULL; tt->phas = NULL; tt->type = 0; tt->temp_scale = 0; tt->thermo_plane = CS_PHYS_PROP_PLANE_PH; return tt; }
void cs_user_postprocess_meshes(void) { /* Post-processing meshes may be defined using one of several functions, * whose protypes are defined in cs_post.h; these functions are: * * Functions simplest to use are cs_post_define_volume_mesh() and * cs_post_define_surface_mesh(), which allow defining volume or surface * post-processing meshes using selection criteria. * * parameters for cs_post_define_volume_mesh(): * mesh_id <-- id of mesh to define (< 0 reserved, > 0 for user) * mesh_name <-- associated mesh name * cell_criteria <-- selection criteria for cells * add_groups <-- if true, add group information if present * auto_variables <-- if true, automatic output of main variables * n_writers <-- number of associated writers * writer_ids <-- ids of associated writers * * parameters for cs_post_define_surface_mesh(): * mesh_id <-- id of mesh to define (< 0 reserved, > 0 for user) * mesh_name <-- associated mesh name * i_face_criteria <-- selection criteria for interior faces * b_face_criteria <-- selection criteria for boundary faces * add_groups <-- if true, add group information if present * auto_variables <-- if true, automatic output of main variables * n_writers <-- number of associated writers * writer_ids <-- ids of associated writers * * If no writer is associated to a mesh, it is not output, and its * construction may be avoided altogether (at least when defined * by one of the above functions). * * More advanced functions are described along with examples below. */ /*--------------------------------------------------------------------------*/ /* Reconfigure predefined meshes (mesh_id -1 for volume, -2 for boundary */ if (false) { /* De-activate boundary mesh output by redefining it with no writer association (default is: int n_writers = 1; const int writer_ids[] = {-1}); */ int n_writers = 0; const int *writer_ids = NULL; cs_post_define_surface_mesh(-2, /* mesh_id of main boundary mesh */ "Boundary", /* mesh name */ NULL, /* interior face selection criteria */ "all[]", /* boundary face selection criteria */ true, /* add_groups */ true, /* automatic variables output */ n_writers, writer_ids); } /*--------------------------------------------------------------------------*/ if (false) { /* Example: select interior faces with y = 0.5 */ const int n_writers = 2; const int writer_ids[] = {1, 4}; /* Associate to writers 1 and 4 */ const char *interior_criteria = "plane[0, -1, 0, 0.5, " "epsilon = 0.0001]"; const char *boundary_criteria = NULL; cs_post_define_surface_mesh(1, /* mesh id */ "Median plane", interior_criteria, boundary_criteria, false, /* add_groups */ false, /* auto_variables */ n_writers, writer_ids); } /*--------------------------------------------------------------------------*/ if (false) { /* Example: select all cells, and will modify the selection in 'usmpst' */ const int n_writers = 1; const int writer_ids[] = {3}; /* Associate to writer 3 */ cs_post_define_volume_mesh(2, /* mesh id */ "Volume v > 0.5", "all[]", false, /* add_groups */ true, /* auto_variables */ n_writers, writer_ids); } /*--------------------------------------------------------------------------*/ if (false) { /* Example: select all boundary faces, and will modify the selection in 'usmpst'. */ const int n_writers = 1; const int writer_ids[] = {3}; /* Associate to writer 3 */ const char *interior_criteria = NULL; const char *boundary_criteria = "all[]"; cs_post_define_surface_mesh(3, /* mesh id */ "Surface iso v", interior_criteria, boundary_criteria, false, /* add_groups */ true, /* auto_variables */ n_writers, writer_ids); } /*--------------------------------------------------------------------------*/ /* The same variables will be output through all writers associated * to a mesh. In cases where different variables of a same mesh should * be output throught different writers, the solution is to define one or * several "aliases" of that mesh, allowing to assign a different id, * writers, and variables to each secondary copy of the mesh, without the * overhead of a full copy. The cs_post_define_alias_mesh() function * may be used for such a purpose. * * parameters for cs_post_define_alias_mesh(): * mesh_id <-- id of mesh to define (< 0 reserved, > 0 for user) * aliased_mesh_id <-- id of aliased mesh * auto_variables <-- if true, automatic output of main variables * n_writers <-- number of associated writers * writer_ids <-- ids of associated writers */ if (false) { /* Example: define an alias of the main surface mesh */ const int n_writers = 1; const int writer_ids[] = {4}; /* Associate to writer 4 */ cs_post_define_alias_mesh(4, /* mesh id */ -2, /* aliased mesh id */ false, /* auto_variables */ n_writers, writer_ids); } /*--------------------------------------------------------------------------*/ /* More advanced mesh element selection is possible using * cs_post_define_volume_mesh_by_list() or * cs_post_define_surface_mesh_by_list(), which allow defining * volume or surface meshes using user-defined element lists. * * parameters for cs_post_define_volume_mesh_by_list(): * mesh_id <-- id of mesh to define (< 0 reserved, > 0 for user) * mesh_name <-- associated mesh name * n_cells <-- number of selected cells * cell_list <-> list of selected cells (1 to n numbering) * add_groups <-- if true, add group information if present * auto_variables <-- if true, automatic output of main variables * n_writers <-- number of associated writers * writer_ids <-- ids of associated writers * * parameters for cs_post_define_surface_mesh_by_list(): * mesh_id <-- id of mesh to define (< 0 reserved, > 0 for user) * mesh_name <-- associated mesh name * n_i_faces <-- number of associated interior faces * n_b_faces <-- number of associated boundary faces * i_face_list <-> list of associated interior faces (1 to n numbering) * b_face_list <-> list of associated boundary faces (1 to n numbering) * add_groups <-- if true, add group information if present * auto_variables <-- if true, automatic output of main variables * n_writers <-- number of associated writers * writer_ids <-- ids of associated writers */ if (false) { /* Advanced example: Build a surface mesh containing interior faces separating cells of group "2" from those of group "3", (assuming no cell has both colors), as well as boundary faces of group "4". */ fvm_lnum_t n_i_faces = 0, n_b_faces = 0; fvm_lnum_t *i_face_list = NULL, *b_face_list = NULL; const int n_writers = 1; const int writer_ids[] = {1}; /* Associate to writer 1 */ const cs_mesh_t *m = cs_glob_mesh; /* Allocate selection lists */ BFT_MALLOC(i_face_list, m->n_i_faces, fvm_lnum_t); BFT_MALLOC(b_face_list, m->n_b_faces, fvm_lnum_t); /* Select interior faces */ { fvm_lnum_t i, face_id; fvm_lnum_t n_families = 0; cs_int_t *family_list = NULL; int *family_mask = NULL; /* Build mask on families matching groups "2" (1), "3" (2) */ BFT_MALLOC(family_list, m->n_families, cs_int_t); BFT_MALLOC(family_mask, m->n_families, int); for (i = 0; i < m->n_families; i++) family_mask[i] = 0; cs_selector_get_family_list("2", &n_families, family_list); for (i = 0; i < n_families; i++) family_mask[family_list[i] - 1] += 1; cs_selector_get_family_list("3", &n_families, family_list); for (i = 0; i < n_families; i++) family_mask[family_list[i] - 1] += 2; BFT_FREE(family_list); /* Now that mask is built, test for adjacency */ for (face_id = 0; face_id < m->n_i_faces; face_id++) { /* Adjacent cells and flags */ fvm_lnum_t c1 = m->i_face_cells[face_id*2] - 1; fvm_lnum_t c2 = m->i_face_cells[face_id*2 + 1] - 1; int iflag1 = family_mask[m->cell_family[c1]]; int iflag2 = family_mask[m->cell_family[c2]]; /* Should the face belong to the extracted mesh ? */ if ((iflag1 == 1 && iflag2 == 2) || (iflag1 == 2 && iflag2 == 1)) { i_face_list[n_i_faces] = face_id + 1; n_i_faces += 1; } } BFT_FREE(family_mask); } /* Select boundary faces */ cs_selector_get_b_face_list("4", &n_b_faces, b_face_list); /* Define postprocessing mesh */ cs_post_define_surface_mesh_by_list(5, /* mesh id */ "Mixed surface", n_i_faces, n_b_faces, i_face_list, b_face_list, false, /* add_groups */ false, /* auto_variables */ n_writers, writer_ids); /* Free selection lists */ BFT_FREE(i_face_list); BFT_FREE(b_face_list); }
void fvm_neighborhood_by_boxes(fvm_neighborhood_t *n, int dim, cs_lnum_t n_boxes, const cs_gnum_t *box_gnum, const cs_coord_t *extents, cs_gnum_t **box_gnum_assigned, cs_coord_t **extents_assigned) { double clock_start, clock_end, cpu_start, cpu_end; fvm_box_tree_t *bt = NULL; fvm_box_set_t *boxes = NULL; const cs_gnum_t *_box_gnum = box_gnum; const cs_coord_t *_extents = extents; int n_ranks = 1; clock_start = cs_timer_wtime(); cpu_start = cs_timer_cpu_time(); /* Transfer data if necessary */ if (box_gnum_assigned != NULL) _box_gnum = *box_gnum_assigned; if (extents_assigned != NULL) _extents = *extents_assigned; /* Reset structure if necessary */ n->n_elts = 0; if (n->elt_num != NULL) BFT_FREE(n->elt_num); if (n->neighbor_index != NULL) BFT_FREE(n->neighbor_index); if (n->neighbor_num != NULL) BFT_FREE(n->neighbor_num); /* Allocate fvm_box_set_t structure and initialize it */ #if defined(HAVE_MPI) if (n->comm != MPI_COMM_NULL) MPI_Comm_size(n->comm, &n_ranks); boxes = fvm_box_set_create(dim, 1, /* normalize */ 1, /* allow_projection */ n_boxes, _box_gnum, _extents, n->comm); if (n_ranks > 1) _redistribute_boxes(n, boxes); #else boxes = fvm_box_set_create(dim, 1, /* normalize */ 1, /* allow_projection */ n_boxes, _box_gnum, _extents); #endif /* Free transferred data if applicable */ if (box_gnum_assigned != NULL) { _box_gnum = NULL; BFT_FREE(*box_gnum_assigned); } if (extents_assigned != NULL) { _extents = NULL; BFT_FREE(*extents_assigned); } /* Build a tree structure and use it to order bounding boxes */ /* Create and initialize a box tree structure */ bt = fvm_box_tree_create(n->max_tree_depth, n->leaf_threshold, n->max_box_ratio); /* Build a tree and put bounding boxes */ fvm_box_tree_set_boxes(bt, boxes, FVM_BOX_TREE_ASYNC_LEVEL); _update_bt_statistics((&n->bt_stats), bt); /* Update construction times. */ clock_end = cs_timer_wtime(); cpu_end = cs_timer_cpu_time(); n->cpu_time[0] = cpu_end - cpu_start; n->wtime[0] = clock_end - clock_start; clock_start = clock_end; cpu_start = cpu_end; /* Allocate structure to store intersections between boxes */ n->n_elts = fvm_box_set_get_size(boxes); BFT_MALLOC(n->elt_num, n->n_elts, cs_gnum_t); memcpy(n->elt_num, fvm_box_set_get_g_num(boxes), n->n_elts*sizeof(cs_gnum_t)); fvm_box_tree_get_intersects(bt, boxes, &(n->neighbor_index), &(n->neighbor_num)); #if 0 && defined(DEBUG) && !defined(NDEBUG) fvm_box_tree_dump(bt); fvm_box_set_dump(boxes, 1); #endif /* Destroy the associated box tree */ fvm_box_tree_destroy(&bt); /* Compact intersections list, delete redundancies and order intersections */ _order_neighborhood(n); #if defined(HAVE_MPI) /* Synchronize list of intersections for each element of the list and distribute it by block over the ranks */ if (n_ranks > 1) _sync_by_block(n, fvm_box_set_get_global_size(boxes)); #endif /* HAVE_MPI */ /* Destroy the box set structures */ fvm_box_set_destroy(&boxes); _clean_neighbor_nums(n); /* Update query times. */ clock_end = cs_timer_wtime(); cpu_end = cs_timer_cpu_time(); n->cpu_time[1] = cpu_end - cpu_start; n->wtime[1] = clock_end - clock_start; }
static void _sync_by_block(fvm_neighborhood_t *n, cs_gnum_t n_g_elts) { cs_lnum_t i, j; int rank_id, n_ranks, n_recv_elts, n_sub_elts, shift; int *send_count = NULL, *recv_count = NULL; int *send_shift = NULL, *recv_shift = NULL; cs_lnum_t *counter = NULL; cs_gnum_t *send_buf = NULL, *recv_buf = NULL; assert(n != NULL); if (n_g_elts == 0 || n->comm == MPI_COMM_NULL) return; /* Initialization */ MPI_Comm_rank(n->comm, &rank_id); MPI_Comm_size(n->comm, &n_ranks); cs_block_dist_info_t bi = cs_block_dist_compute_sizes(rank_id, n_ranks, 0, 0, n_g_elts); /* Allocate buffers */ BFT_MALLOC(send_count, n_ranks, int); BFT_MALLOC(recv_count, n_ranks, int); BFT_MALLOC(send_shift, n_ranks + 1, int); BFT_MALLOC(recv_shift, n_ranks + 1, int); for (i = 0; i < n_ranks; i++) send_count[i] = 0; /* Synchronize definition for each global element */ for (i = 0; i < n->n_elts; i++) { long int g_ent_id = n->elt_num[i] -1; int send_rank = (g_ent_id/bi.block_size)*bi.rank_step; n_sub_elts = n->neighbor_index[i+1] - n->neighbor_index[i]; send_count[send_rank] += 2 + n_sub_elts; } MPI_Alltoall(send_count, 1, MPI_INT, recv_count, 1, MPI_INT, n->comm); send_shift[0] = 0; recv_shift[0] = 0; for (i = 0; i < n_ranks; i++) { send_shift[i + 1] = send_shift[i] + send_count[i]; recv_shift[i + 1] = recv_shift[i] + recv_count[i]; } /* Fill send_buf: global number and number of elements in index */ BFT_MALLOC(send_buf, send_shift[n_ranks], cs_gnum_t); BFT_MALLOC(recv_buf, recv_shift[n_ranks], cs_gnum_t); for (i = 0; i < n_ranks; i++) send_count[i] = 0; for (i = 0; i < n->n_elts; i++) { long int g_ent_num = n->elt_num[i]; int send_rank = ((g_ent_num - 1)/bi.block_size)*bi.rank_step; shift = send_shift[send_rank] + send_count[send_rank]; n_sub_elts = n->neighbor_index[i+1] - n->neighbor_index[i]; send_buf[shift++] = g_ent_num; send_buf[shift++] = n_sub_elts; for (j = 0; j < n_sub_elts; j++) send_buf[shift + j] = n->neighbor_num[n->neighbor_index[i] + j]; send_count[send_rank] += 2 + n_sub_elts; } MPI_Alltoallv(send_buf, send_count, send_shift, CS_MPI_GNUM, recv_buf, recv_count, recv_shift, CS_MPI_GNUM, n->comm); n_recv_elts = recv_shift[n_ranks]; /* Free what we may */ BFT_FREE(send_buf); BFT_FREE(send_count); BFT_FREE(send_shift); BFT_FREE(recv_count); BFT_FREE(recv_shift); /* Build arrays corresponding to block distribution of neighborhood */ n->n_elts = bi.gnum_range[1] - bi.gnum_range[0]; BFT_FREE(n->elt_num); BFT_FREE(n->neighbor_index); BFT_FREE(n->neighbor_num); BFT_MALLOC(n->elt_num, n->n_elts, cs_gnum_t); BFT_MALLOC(n->neighbor_index, n->n_elts + 1, cs_lnum_t); for (i = 0; i < n->n_elts; i++) { n->elt_num[i] = bi.gnum_range[0] + i; n->neighbor_index[i] = 0; } n->neighbor_index[n->n_elts] = 0; /* Count element neighbors in block distribution */ i = 0; /* start position in recv_buf */ while (i < n_recv_elts) { cs_lnum_t elt_id = recv_buf[i++] - bi.gnum_range[0]; assert(n->elt_num[elt_id] == recv_buf[i-1]); n_sub_elts = recv_buf[i++]; n->neighbor_index[elt_id + 1] += n_sub_elts; i += n_sub_elts; } /* Transform element neighbor count to index */ n->neighbor_index[0] = 0; for (i = 0; i < n->n_elts; i++) n->neighbor_index[i+1] += n->neighbor_index[i]; BFT_MALLOC(n->neighbor_num, n->neighbor_index[n->n_elts], cs_gnum_t); /* Fill element neighbors in block distribution */ BFT_MALLOC(counter, n->n_elts, cs_lnum_t); for (i = 0; i < n->n_elts; i++) counter[i] = 0; i = 0; /* start position in recv_buf */ while (i < n_recv_elts) { cs_lnum_t elt_id = recv_buf[i++] - bi.gnum_range[0]; n_sub_elts = recv_buf[i++]; shift = n->neighbor_index[elt_id] + counter[elt_id]; for (j = 0; j < n_sub_elts; j++) n->neighbor_num[j + shift] = recv_buf[i++]; counter[elt_id] += n_sub_elts; } /* End of loop on ranks */ BFT_FREE(recv_buf); BFT_FREE(counter); /* Remove redundant data */ _clean_neighbor_nums(n); }
static void _order_neighborhood(fvm_neighborhood_t *n) { cs_lnum_t i, j, k, order_id, shift, e_count; cs_lnum_t n_elts, n_neighbors, n_elt_neighbors; cs_gnum_t prev_num, cur_num; cs_lnum_t *order = NULL, *old_index = NULL; cs_gnum_t *old_e_num = NULL, *old_n_num = NULL; assert(n != NULL); if (n->n_elts == 0) return; n_elts = n->n_elts; n_neighbors = n->neighbor_index[n_elts]; BFT_MALLOC(order, n_elts, cs_lnum_t); BFT_MALLOC(old_e_num, n_elts, cs_gnum_t); BFT_MALLOC(old_index, n_elts + 1, cs_lnum_t); BFT_MALLOC(old_n_num, n_neighbors, cs_gnum_t); memcpy(old_e_num, n->elt_num, n_elts*sizeof(cs_gnum_t)); memcpy(old_index, n->neighbor_index, (n_elts + 1)*sizeof(cs_lnum_t)); memcpy(old_n_num, n->neighbor_num, n_neighbors*sizeof(cs_gnum_t)); /* Order elt_num */ cs_order_gnum_allocated(NULL, old_e_num, order, n_elts); /* Reshape according to the new ordering */ /* Add first element */ order_id = order[0]; shift = 0; n->elt_num[0] = old_e_num[order_id]; prev_num = n->elt_num[0]; n->neighbor_index[0] = 0; n->neighbor_index[1] = old_index[order_id+1] - old_index[order_id]; /* Loop on second-to last elements, merging data if an element has already appeared */ for (i = 1, e_count = 1; i < n_elts; i++) { order_id = order[i]; n_elt_neighbors = old_index[order_id+1] - old_index[order_id]; shift = n->neighbor_index[i]; cur_num = old_e_num[order_id]; if (cur_num != prev_num) { n->elt_num[e_count] = cur_num; n->neighbor_index[e_count+1] = ( n->neighbor_index[e_count] + n_elt_neighbors); e_count += 1; prev_num = cur_num; } else n->neighbor_index[e_count] += n_elt_neighbors; for (j = old_index[order_id], k = 0; k < n_elt_neighbors; j++, k++) n->neighbor_num[shift + k] = old_n_num[j]; } /* End of loop on elements */ assert(n->neighbor_index[e_count] == n_neighbors); /* Free temporary memory */ BFT_FREE(order); BFT_FREE(old_e_num); BFT_FREE(old_index); BFT_FREE(old_n_num); }
void cs_mesh_smoother_unwarp(cs_mesh_t *mesh, const int vtx_is_fixed[]) { int face; cs_real_t maxwarp, minhist_i, minhist_b, maxhist_i, maxhist_b; cs_real_t rnorm_b, rnorm_i; bool conv = false; int iter = 0; int max_iter = UNWARPING_MAX_LOOPS; double frac = 0.1; double eps = 1.e-4; cs_real_t maxwarp_p = 90; cs_real_t *vtx_tolerance = NULL; cs_real_t *loc_vtx_mvt = NULL; cs_real_t *i_face_norm = NULL; cs_real_t *i_face_cog = NULL; cs_real_t *b_face_norm = NULL; cs_real_t *b_face_cog = NULL; cs_real_t *b_face_warp = NULL; cs_real_t *i_face_warp = NULL; if (mesh->have_rotation_perio) bft_error(__FILE__, __LINE__, 0, "Smoothing in case of periodicity of rotation not yet handled."); bft_printf(_("\n Start unwarping algorithm\n\n")); BFT_MALLOC(b_face_warp, mesh->n_b_faces, cs_real_t); BFT_MALLOC(i_face_warp, mesh->n_i_faces, cs_real_t); BFT_MALLOC(vtx_tolerance, mesh->n_vertices, cs_real_t); BFT_MALLOC(loc_vtx_mvt, 3*(mesh->n_vertices), cs_real_t); while (!conv) { cs_mesh_quantities_i_faces(mesh, &(i_face_cog), &(i_face_norm)); cs_mesh_quantities_b_faces(mesh, &(b_face_cog), &(b_face_norm)); cs_mesh_quality_compute_warping(mesh, i_face_norm, b_face_norm, i_face_warp, b_face_warp); _get_tolerance(mesh, vtx_tolerance, frac); for (face = 0; face < mesh->n_i_faces; face++) { rnorm_i = sqrt ( i_face_norm[3*face]*i_face_norm[3*face] + i_face_norm[3*face + 1]*i_face_norm[3*face + 1] + i_face_norm[3*face + 2]*i_face_norm[3*face + 2]); i_face_norm[3*face ] /= rnorm_i; i_face_norm[3*face +1] /= rnorm_i; i_face_norm[3*face +2] /= rnorm_i; } for (face = 0; face < mesh->n_b_faces; face++) { rnorm_b = sqrt( b_face_norm[3*face]*b_face_norm[3*face] + b_face_norm[3*face + 1]*b_face_norm[3*face + 1] + b_face_norm[3*face + 2]*b_face_norm[3*face + 2]); b_face_norm[3*face ] /= rnorm_b; b_face_norm[3*face +1] /= rnorm_b; b_face_norm[3*face +2] /= rnorm_b; } maxwarp = _unwarping_mvt(mesh, i_face_norm, b_face_norm, i_face_cog, b_face_cog, loc_vtx_mvt, i_face_warp, b_face_warp, vtx_tolerance, frac); if (iter == 0) { _compute_minmax(mesh->n_i_faces, i_face_warp, &minhist_i, &maxhist_i); _compute_minmax(mesh->n_b_faces, b_face_warp, &minhist_b, &maxhist_b); bft_printf(_("\n Histogram of the boundary faces warping" " before unwarping algorithm:\n\n")); _histogram(mesh->n_b_faces, b_face_warp, minhist_b, maxhist_b, minhist_b, maxhist_b); bft_printf(_("\n Histogram of the interior faces warping" " before unwarping algorithm:\n\n")); _int_face_histogram(mesh, i_face_warp, minhist_i, maxhist_i, minhist_i, maxhist_i); } if (maxwarp/maxwarp_p > 1.005) { if (iter <= 1) bft_error(__FILE__, __LINE__, 0, _("\nUnwarping algorithm failed.")); else { cs_base_warn(__FILE__, __LINE__); bft_printf(_("\nUnwarping algorithm stopped at iteration %d" " because it starting to diverge.\n"), iter); iter = max_iter +100; conv = true; } } if ( ((1 - maxwarp/maxwarp_p) > 0 && (1 - maxwarp/maxwarp_p) < eps) || iter == max_iter) { conv = true; bft_printf(_("\nUnwarping algorithm converged at iteration %d \n"), iter +1); } maxwarp_p = maxwarp; if (iter <= max_iter) _move_vertices(mesh, loc_vtx_mvt, vtx_is_fixed); BFT_FREE(i_face_norm); BFT_FREE(b_face_norm); BFT_FREE(i_face_cog); BFT_FREE(b_face_cog); iter++; } /* Output quality histograms */ { cs_real_t min_b, max_b, max_i, min_i; _compute_minmax(mesh->n_i_faces, i_face_warp, &min_i, &max_i); _compute_minmax(mesh->n_b_faces, b_face_warp, &min_b, &max_b); bft_printf(_("\n Histogram of the boundary faces warping" " after unwarping algorithm:\n\n")); _histogram(mesh->n_b_faces, b_face_warp, minhist_b, maxhist_b, min_b, max_b); bft_printf(_("\n Histogram of the interior faces warping" " after unwarping algorithm:\n\n")); _int_face_histogram(mesh, i_face_warp, minhist_i, maxhist_i, min_i, max_i); } BFT_FREE(vtx_tolerance); BFT_FREE(loc_vtx_mvt); BFT_FREE(i_face_warp); BFT_FREE(b_face_warp); bft_printf(_("\n End unwarping algorithm\n\n")); }
void cs_mesh_smoother_fix_by_feature(cs_mesh_t *mesh, cs_real_t feature_angle, int vtx_is_fixed[]) { cs_lnum_t face, j; cs_real_t rnorm_b; cs_real_t *face_norm, *vtx_norm; cs_real_t *b_face_norm = NULL; cs_real_t *b_face_cog = NULL; cs_real_t *b_vtx_norm = NULL; cs_real_t *_vtx_is_fixed = NULL; BFT_MALLOC(_vtx_is_fixed, mesh->n_vertices, cs_real_t); BFT_MALLOC(b_vtx_norm, 3*(mesh->n_vertices), cs_real_t); cs_mesh_quantities_b_faces(mesh, &(b_face_cog), &(b_face_norm)); BFT_FREE(b_face_cog); for (face = 0; face < mesh->n_b_faces; face++) { rnorm_b = sqrt( b_face_norm[3*face ]*b_face_norm[3*face ] + b_face_norm[3*face + 1]*b_face_norm[3*face + 1] + b_face_norm[3*face + 2]*b_face_norm[3*face + 2]); b_face_norm[3*face ] /= rnorm_b; b_face_norm[3*face + 1] /= rnorm_b; b_face_norm[3*face + 2] /= rnorm_b; } _compute_vtx_normals(mesh, b_face_norm, b_vtx_norm); for (j = 0; j < mesh->n_vertices; j++) _vtx_is_fixed[j] = 0; for (face = 0; face < mesh->n_b_faces; face++) { for (j = mesh->b_face_vtx_idx[face]; j < mesh->b_face_vtx_idx[face +1]; j++) { face_norm = &b_face_norm[face*3]; vtx_norm = &b_vtx_norm[(mesh->b_face_vtx_lst[j])*3]; if (_DOT_PRODUCT_3D(face_norm, vtx_norm) < cos(feature_angle*_PI_/180.0) || feature_angle < DBL_MIN) _vtx_is_fixed[mesh->b_face_vtx_lst[j]] += 1; } } if (mesh->vtx_interfaces != NULL) { cs_interface_set_sum(mesh->vtx_interfaces, mesh->n_vertices, 1, true, CS_REAL_TYPE, _vtx_is_fixed); } for (j = 0; j < mesh->n_vertices; j++) { if (_vtx_is_fixed[j] > 0.1) vtx_is_fixed[j] = 1; else vtx_is_fixed[j] = 0; } BFT_FREE(b_face_norm); BFT_FREE(b_vtx_norm); BFT_FREE(_vtx_is_fixed); }
static void _get_global_tolerance(cs_mesh_t *mesh, cs_real_t *vtx_tolerance) { cs_int_t i, rank, vtx_id, block_size, shift; cs_gnum_t first_vtx_gnum; cs_lnum_t n_vertices = mesh->n_vertices; double *g_vtx_tolerance = NULL, *send_list = NULL, *recv_list = NULL; cs_int_t *send_count = NULL, *recv_count = NULL; cs_int_t *send_shift = NULL, *recv_shift = NULL; cs_gnum_t *send_glist = NULL, *recv_glist = NULL; cs_gnum_t n_g_vertices = mesh->n_g_vertices; const cs_gnum_t *io_gnum = mesh->global_vtx_num; MPI_Comm mpi_comm = cs_glob_mpi_comm; const int local_rank = CS_MAX(cs_glob_rank_id, 0); const int n_ranks = cs_glob_n_ranks; /* Define a fvm_io_num_t structure on vertices */ block_size = n_g_vertices / n_ranks; if (n_g_vertices % n_ranks > 0) block_size += 1; /* Count the number of vertices to send to each rank */ /* ------------------------------------------------- */ BFT_MALLOC(send_count, n_ranks, int); BFT_MALLOC(recv_count, n_ranks, int); BFT_MALLOC(send_shift, n_ranks + 1, int); BFT_MALLOC(recv_shift, n_ranks + 1, int); send_shift[0] = 0; recv_shift[0] = 0; for (rank = 0; rank < n_ranks; rank++) send_count[rank] = 0; for (i = 0; i < n_vertices; i++) { rank = (io_gnum[i] - 1)/block_size; send_count[rank] += 1; } MPI_Alltoall(send_count, 1, MPI_INT, recv_count, 1, MPI_INT, mpi_comm); for (rank = 0; rank < n_ranks; rank++) { send_shift[rank + 1] = send_shift[rank] + send_count[rank]; recv_shift[rank + 1] = recv_shift[rank] + recv_count[rank]; } assert(send_shift[n_ranks] == n_vertices); /* Send the global numbering for each vertex */ /* ----------------------------------------- */ BFT_MALLOC(send_glist, n_vertices, cs_gnum_t); BFT_MALLOC(recv_glist, recv_shift[n_ranks], cs_gnum_t); for (rank = 0; rank < n_ranks; rank++) send_count[rank] = 0; for (i = 0; i < n_vertices; i++) { rank = (io_gnum[i] - 1)/block_size; shift = send_shift[rank] + send_count[rank]; send_count[rank] += 1; send_glist[shift] = io_gnum[i]; } MPI_Alltoallv(send_glist, send_count, send_shift, CS_MPI_GNUM, recv_glist, recv_count, recv_shift, CS_MPI_GNUM, mpi_comm); /* Send the vertex tolerance for each vertex */ /* ----------------------------------------- */ BFT_MALLOC(send_list, n_vertices, double); BFT_MALLOC(recv_list, recv_shift[n_ranks], double); for (rank = 0; rank < n_ranks; rank++) send_count[rank] = 0; for (i = 0; i < n_vertices; i++) { rank = (io_gnum[i] - 1)/block_size; shift = send_shift[rank] + send_count[rank]; send_count[rank] += 1; send_list[shift] = vtx_tolerance[i]; } MPI_Alltoallv(send_list, send_count, send_shift, MPI_DOUBLE, recv_list, recv_count, recv_shift, MPI_DOUBLE, mpi_comm); /* Define the global tolerance array */ BFT_MALLOC(g_vtx_tolerance, block_size, double); for (i = 0; i < block_size; i++) g_vtx_tolerance[i] = DBL_MAX; first_vtx_gnum = block_size * local_rank + 1; for (i = 0; i < recv_shift[n_ranks]; i++) { vtx_id = recv_glist[i] - first_vtx_gnum; g_vtx_tolerance[vtx_id] = CS_MIN(g_vtx_tolerance[vtx_id], recv_list[i]); } /* Replace local vertex tolerance by the new computed global tolerance */ for (i = 0; i < recv_shift[n_ranks]; i++) { vtx_id = recv_glist[i] - first_vtx_gnum; recv_list[i] = g_vtx_tolerance[vtx_id]; } MPI_Alltoallv(recv_list, recv_count, recv_shift, MPI_DOUBLE, send_list, send_count, send_shift, MPI_DOUBLE, mpi_comm); for (rank = 0; rank < n_ranks; rank++) send_count[rank] = 0; for (i = 0; i < n_vertices; i++) { rank = (io_gnum[i] - 1)/block_size; shift = send_shift[rank] + send_count[rank]; send_count[rank] += 1; vtx_tolerance[i] = send_list[shift]; } /* Free memory */ BFT_FREE(recv_glist); BFT_FREE(send_glist); BFT_FREE(send_list); BFT_FREE(recv_list); BFT_FREE(recv_count); BFT_FREE(send_count); BFT_FREE(recv_shift); BFT_FREE(send_shift); BFT_FREE(g_vtx_tolerance); }
void cs_join_post_after_split(cs_lnum_t n_old_i_faces, cs_lnum_t n_old_b_faces, cs_gnum_t n_g_new_b_faces, cs_lnum_t n_select_faces, const cs_mesh_t *mesh, cs_join_param_t join_param) { if (join_param.visualization < 1 || _cs_join_post_initialized == false) return; cs_lnum_t i, j; int writer_ids[] = {_cs_join_post_param.writer_num}; char *mesh_name = NULL; cs_lnum_t *post_i_faces = NULL, *post_b_faces = NULL; fvm_nodal_t *post_i_mesh = NULL; int post_i_mesh_id = cs_post_get_free_mesh_id(); int post_b_mesh_id = 0; const int n_new_i_faces = mesh->n_i_faces - n_old_i_faces; const int n_new_b_faces = mesh->n_b_faces - n_old_b_faces + n_select_faces; /* Define list of faces to post-treat */ BFT_MALLOC(post_i_faces, n_new_i_faces, cs_lnum_t); BFT_MALLOC(post_b_faces, n_new_b_faces, cs_lnum_t); for (i = n_old_i_faces, j = 0; i < mesh->n_i_faces; i++, j++) post_i_faces[j] = i + 1; for (i = n_old_b_faces-n_select_faces, j = 0; i < mesh->n_b_faces; i++, j++) post_b_faces[j] = i + 1; BFT_MALLOC(mesh_name, strlen("InteriorJoinedFaces_j") + 2 + 1, char); sprintf(mesh_name,"%s%02d", "InteriorJoinedFaces_j", join_param.num); post_i_mesh = cs_mesh_connect_faces_to_nodal(cs_glob_mesh, mesh_name, false, /* include families */ n_new_i_faces, 0, post_i_faces, NULL); cs_post_define_existing_mesh(post_i_mesh_id, post_i_mesh, 0, /* dim_shift */ true, /* transfer ownership */ false, 1, writer_ids); if (join_param.visualization > 1 && n_g_new_b_faces > 0) { fvm_nodal_t *post_b_mesh = NULL; post_b_mesh_id = cs_post_get_free_mesh_id(); BFT_REALLOC(mesh_name, strlen("BoundaryJoinedFaces_j") + 2 + 1, char); sprintf(mesh_name,"%s%02d", "BoundaryJoinedFaces_j", join_param.num); post_b_mesh = cs_mesh_connect_faces_to_nodal(cs_glob_mesh, mesh_name, false, /* include families */ 0, n_new_b_faces, NULL, post_b_faces); cs_post_define_existing_mesh(post_b_mesh_id, post_b_mesh, 0, /* dim_shift */ true, /* transfer ownership */ false, 1, writer_ids); }
void cs_join_post_mesh(const char *mesh_name, const cs_join_mesh_t *join_mesh) { if (_cs_join_post_initialized == true) return; int i, j; cs_lnum_t n_vertices; const char *name = NULL; int *ifield = NULL; double *dfield = NULL; cs_gnum_t *vertex_gnum = NULL; cs_real_t *vertex_coord = NULL; cs_lnum_t *parent_vtx_num = NULL; fvm_nodal_t *post_mesh = NULL; fvm_writer_t *writer = _cs_join_post_param.writer; const int local_rank = CS_MAX(cs_glob_rank_id, 0); const cs_lnum_t face_list_shift[2] = {0, join_mesh->n_faces}; const cs_lnum_t *face_vertex_idx[1] = {join_mesh->face_vtx_idx}; const cs_lnum_t *face_vertex_lst[1] = {join_mesh->face_vtx_lst}; /* Define an fvm_nodal_mesh_t structure from a cs_join_mesh_t structure */ /* Create an empty fvm_nodal_t structure. */ if (mesh_name == NULL) name = join_mesh->name; else name = mesh_name; post_mesh = fvm_nodal_create(name, 3); /* Define fvm_nodal_t structure */ fvm_nodal_from_desc_add_faces(post_mesh, join_mesh->n_faces, NULL, 1, face_list_shift, face_vertex_idx, face_vertex_lst, NULL, NULL); /* Define vertex_coord for fvm_nodal_set_shared_vertices() */ BFT_MALLOC(vertex_coord, 3*join_mesh->n_vertices, cs_real_t); for (i = 0; i < join_mesh->n_vertices; i++) for (j = 0; j < 3; j++) vertex_coord[3*i+j] = (join_mesh->vertices[i]).coord[j]; fvm_nodal_set_shared_vertices(post_mesh, vertex_coord); /* Order faces by increasing global number */ fvm_nodal_order_faces(post_mesh, join_mesh->face_gnum); fvm_nodal_init_io_num(post_mesh, join_mesh->face_gnum, 2); /* Order vertices by increasing global number */ BFT_MALLOC(vertex_gnum, join_mesh->n_vertices, cs_gnum_t); for (i = 0; i < join_mesh->n_vertices; i++) vertex_gnum[i] = (join_mesh->vertices[i]).gnum; fvm_nodal_order_vertices(post_mesh, vertex_gnum); fvm_nodal_init_io_num(post_mesh, vertex_gnum, 0); /* Write current mesh */ fvm_writer_export_nodal(writer, post_mesh); BFT_FREE(vertex_gnum); BFT_FREE(vertex_coord); /* Write rank associated to each face */ BFT_MALLOC(ifield, join_mesh->n_faces, int); for (i = 0; i < join_mesh->n_faces; i++) ifield[i] = local_rank; _post_elt_ifield(post_mesh, _("Rank"), 1, ifield); BFT_FREE(ifield); /* Write vertex tolerance */ n_vertices = fvm_nodal_get_n_entities(post_mesh, 0); BFT_MALLOC(parent_vtx_num, n_vertices, cs_lnum_t); BFT_MALLOC(dfield, n_vertices, double); fvm_nodal_get_parent_num(post_mesh, 0, parent_vtx_num); for (i = 0; i < n_vertices; i++) { cs_join_vertex_t data = join_mesh->vertices[parent_vtx_num[i]-1]; dfield[i] = data.tolerance; } _post_vtx_dfield(post_mesh, _("VtxTolerance"), 1, dfield); BFT_FREE(parent_vtx_num); BFT_FREE(dfield); post_mesh = fvm_nodal_destroy(post_mesh); }
void cs_user_solver(const cs_mesh_t *mesh, const cs_mesh_quantities_t *mesh_quantities) { return; /* REMOVE_LINE_FOR_USE_OF_SUBROUTINE */ cs_int_t i, iter, n_iter; cs_real_t x0, xL, t0, tL, L; cs_real_t r; cs_real_t *t = NULL, *t_old = NULL, *t_sol = NULL; cs_restart_t *restart, *checkpoint; cs_time_plot_t *time_plot; const cs_int_t n = mesh->n_cells; const cs_real_t pi = 4.*atan(1.); const char var_name[] = "temperature"; /* Initialization */ BFT_MALLOC(t, n, cs_real_t); BFT_MALLOC(t_old, n, cs_real_t); BFT_MALLOC(t_sol, n, cs_real_t); x0 = 1.e30; xL = -1.e30; for (i = 0; i < mesh->n_b_faces; i++) { cs_real_t x_face = mesh_quantities->b_face_cog[3*i]; if (x_face < x0) x0 = x_face; if (x_face > xL) xL = x_face; } L = xL - x0; /* it is assumed that dx is constant and x0 = 0, XL =1 */ t0 = 0.; tL = 0.; r = 0.2; /* Fourier number */ n_iter = 100000; for (i = 0; i < n; i++) t_old[i] = sin(pi*(0.5+i)/n); /* ------- */ /* Restart */ /* ------- */ if (1 == 0) { restart = cs_restart_create("main", /* file name */ NULL, /* force directory */ CS_RESTART_MODE_READ); /* read mode */ cs_restart_read_section(restart, /* restart file */ var_name, /* buffer name */ 1, /* location id */ 1, /* number of values per location */ 2, /* value type */ t_old); /* buffer */ cs_restart_destroy(&restart); } /* --------------- */ /* Time monitoring */ /* --------------- */ time_plot = cs_time_plot_init_probe(var_name, /* variable name */ "probes_", /* file prefix */ CS_TIME_PLOT_DAT, /* file format */ true, /* use iter. numbers */ -1., /* force flush */ 0, /* buffer size */ 1, /* number of probes */ NULL, /* probes list */ NULL); /* probes coord. */ /* ----------- */ /* Calculation */ /* ----------- */ /* Heat equation resolution by Finite Volume method */ for (iter = 0; iter < n_iter; iter++) { /* 1D Finite Volume scheme, with constant dx */ t[0] = t_old[0] + r*(t_old[1] - 3.*t_old[0] + 2.*t0); for (i = 1; i < n-1; i++) t[i] = t_old[i] + r*(t_old[i+1] - 2.*t_old[i] + t_old[i-1]); t[n-1] = t_old[n-1] + r*(2.*tL - 3.*t_old[n-1] + t_old[n-2]); /* Update previous value of the temperature */ for (i = 0; i < n; i++) t_old[i] = t[i]; /* Analytical solution at the current time */ for (i = 0; i < n; i++) t_sol[i] = sin(pi*(0.5+i)/n)*exp(-r*pi*pi*(iter+1)/(n*n)); /* Plot maximum temperature value (center-value) */ cs_time_plot_vals_write(time_plot, /* time plot structure */ iter, /* current iteration number */ -1., /* current time */ 1, /* number of values */ &(t[n/2])); /* values */ } /* --------- */ /* Chekpoint */ /* --------- */ checkpoint = cs_restart_create("main", /* file name */ NULL, /* force directory */ CS_RESTART_MODE_WRITE); /* write mode */ cs_restart_write_section(checkpoint, /* restart file */ var_name, /* buffer name */ 1, /* location id */ 1, /* number of values per location */ 2, /* value type */ t); /* buffer */ cs_restart_destroy(&checkpoint); /* --------------- */ /* Post-processing */ /* --------------- */ cs_post_activate_writer(-1, /* default writer */ true); /* activate if 1 */ cs_post_write_var(-1, /* default mesh */ var_name, /* variable name */ 1, /* variable dimension */ false, /* interleave if true */ true, /* define on parents */ CS_POST_TYPE_cs_real_t, /* type */ t, /* value on cells */ NULL, /* value on interior faces */ NULL, /* value on boundary faces */ NULL); /* time-independent output */ cs_post_write_var(-1, /* default mesh */ "solution", /* variable name */ 1, /* variable dimension */ false, /* interleave if true */ true, /* define on parents */ CS_POST_TYPE_cs_real_t, /* type */ t_sol, /* value on cells */ NULL, /* value on interior faces */ NULL, /* value on boundary faces */ NULL); /* time-independent output */ /* Finalization */ BFT_FREE(t); BFT_FREE(t_old); BFT_FREE(t_sol); cs_time_plot_finalize(&time_plot); return; }