#include "fracture.h" int main(int argc, char *argv[]) { int opt; // defining variables to be (potentially) set by command line flags uint8_t filename_len; uint32_t N; uint_t L; double beta, inf, cutoff, crack_len; bool include_breaking, save_cluster_dist, use_voltage_boundaries, use_dual, save_network, save_crit_stress, save_stress_field, save_voltage_field, save_toughness, save_conductivity, save_damage, save_damage_field; bound_t boundary; // assume filenames will be less than 100 characters filename_len = 100; // set default values N = 100; L = 16; crack_len = 0.; beta = .3; inf = 1e10; cutoff = 1e-9; boundary = FREE_BOUND; include_breaking = false; save_cluster_dist = false; use_voltage_boundaries = false; use_dual = false; save_network = false; save_crit_stress = false; save_stress_field = false; save_voltage_field = false; save_damage = false; save_damage_field = false; save_conductivity = false; save_toughness = false; uint8_t bound_i; char boundc2 = 'f'; // get commandline options while ((opt = getopt(argc, argv, "n:L:b:B:dVcoNsCrtDSvel:")) != -1) { switch (opt) { case 'n': N = atoi(optarg); break; case 'L': L = atoi(optarg); break; case 'b': beta = atof(optarg); break; case 'l': crack_len = atof(optarg); break; case 'B': bound_i = atoi(optarg); switch (bound_i) { case 0: boundary = FREE_BOUND; boundc2 = 'f'; break; case 1: boundary = CYLINDER_BOUND; boundc2 = 'c'; break; case 2: boundary = TORUS_BOUND; use_voltage_boundaries = true; boundc2 = 't'; break; case 3: boundary = EMBEDDED_BOUND; boundc2 = 'e'; use_dual = true; use_voltage_boundaries = true; break; default: printf("boundary specifier must be 0 (FREE_BOUND), 1 (CYLINDER_BOUND), or 2 (TORUS_BOUND).\n"); exit(EXIT_FAILURE); } break; case 'd': save_damage = true; break; case 'e': save_damage_field = true; break; case 'V': use_voltage_boundaries = true; break; case 'D': use_dual = true; break; case 'c': save_cluster_dist = true; break; case 'o': include_breaking = true; break; case 'N': save_network = true; break; case 's': save_crit_stress = true; break; case 'S': save_stress_field = true; break; case 'v': save_voltage_field = true; break; case 'r': save_conductivity = true; //inf = 1; break; case 't': save_toughness = true; break; default: /* '?' */ exit(EXIT_FAILURE); } } char boundc; if (use_voltage_boundaries) boundc = 'v'; else boundc = 'c'; FILE *break_out; if (include_breaking) { char *break_filename = (char *)malloc(filename_len * sizeof(char)); snprintf(break_filename, filename_len, "breaks_v_%c_%c_%u_%g_%g.txt", boundc, boundc2, L, beta, crack_len); break_out = fopen(break_filename, "a"); free(break_filename); } uint_t voronoi_max_verts, c_dist_size, a_dist_size; voronoi_max_verts = 4 * pow(L, 2); c_dist_size = voronoi_max_verts; a_dist_size = voronoi_max_verts; if (voronoi_max_verts > CINT_MAX) { exit(EXIT_FAILURE); } // define arrays for saving cluster and avalanche distributions uint32_t *cluster_size_dist; uint32_t *avalanche_size_dist; char *c_filename; char *a_filename; if (save_cluster_dist) { cluster_size_dist = (uint32_t *)malloc(c_dist_size * sizeof(uint32_t)); avalanche_size_dist = (uint32_t *)malloc(a_dist_size * sizeof(uint32_t)); c_filename = (char *)malloc(filename_len * sizeof(char)); a_filename = (char *)malloc(filename_len * sizeof(char)); snprintf(c_filename, filename_len, "cstr_v_%c_%c_%d_%g_%g.dat", boundc, boundc2, L, beta, crack_len); snprintf(a_filename, filename_len, "avln_v_%c_%c_%d_%g_%g.dat", boundc, boundc2, L, beta, crack_len); FILE *cluster_out = fopen(c_filename, "rb"); FILE *avalanche_out = fopen(a_filename, "rb"); if (cluster_out != NULL) { fread(cluster_size_dist, sizeof(uint32_t), c_dist_size, cluster_out); fclose(cluster_out); } if (avalanche_out != NULL) { fread(avalanche_size_dist, sizeof(uint32_t), a_dist_size, avalanche_out); fclose(avalanche_out); } } double *crit_stress; if (save_crit_stress) { crit_stress = (double *)malloc(N * sizeof(double)); } double *stress_field; unsigned int stress_pos = 0; if (save_stress_field) { stress_field = (double *)malloc(3 * N * voronoi_max_verts * sizeof(double)); } double *voltage_field; unsigned int voltage_pos = 0; if (save_voltage_field) { voltage_field = (double *)malloc(3 * N * voronoi_max_verts * sizeof(double)); } double *damage_field; unsigned int damage_pos = 0; if (save_damage_field) { damage_field = (double *)malloc(2 * N * voronoi_max_verts * sizeof(double)); } double *conductivity; if (save_conductivity) { conductivity = (double *)malloc(N * sizeof(double)); } // define arrays for saving damage distributions uint32_t *damage; char *d_filename; if (save_damage) { damage = (uint32_t *)malloc(a_dist_size * sizeof(uint32_t)); d_filename = (char *)malloc(filename_len * sizeof(char)); snprintf(d_filename, filename_len, "damg_v_%c_%c_%d_%g_%g.dat", boundc, boundc2, L, beta, crack_len); FILE *damage_out = fopen(d_filename, "rb"); if (damage_out != NULL) { fread(damage, sizeof(uint32_t), a_dist_size, damage_out); fclose(damage_out); } } double *toughness; if (save_toughness) { toughness = (double *)malloc(N * sizeof(double)); } // start cholmod cholmod_common c; CHOL_F(start)(&c); /* if we use voltage boundary conditions, the laplacian matrix is positive * definite and we can use a supernodal LL decomposition. otherwise we need * to use the simplicial LDL decomposition */ if (use_voltage_boundaries) { //(&c)->supernodal = CHOLMOD_SUPERNODAL; (&c)->supernodal = CHOLMOD_SIMPLICIAL; } else { (&c)->supernodal = CHOLMOD_SIMPLICIAL; } printf("\n"); for (uint32_t i = 0; i < N; i++) { printf("\033[F\033[JFRACTURE: %0*d / %d\n", (uint8_t)log10(N) + 1, i + 1, N); graph_t *graph = ini_voronoi_network(L, boundary, use_dual, genfunc_hyperuniform, &c); net_t *perm_instance = create_instance(graph, inf, use_voltage_boundaries, false, &c); if (boundary == EMBEDDED_BOUND) { voronoi_bound_ini(perm_instance, L, crack_len); } gen_voro_crack(perm_instance, crack_len, &c); finish_instance(perm_instance, &c); double *fuse_thres = gen_fuse_thres(graph->ne, graph->edge_coords, beta, beta_scaling_flat); net_t *instance = copy_instance(perm_instance, &c); data_t *breaking_data = fracture_network(instance, fuse_thres, &c, cutoff); free_instance(instance, &c); free(fuse_thres); uint_t max_pos = 0; double max_val = 0; for (uint_t j = 0; j < breaking_data->num_broken; j++) { double val = breaking_data->extern_field[j]; if (val > max_val) { max_pos = j; max_val = val; } } if (save_crit_stress) crit_stress[i] = breaking_data->extern_field[max_pos]; if (save_conductivity) conductivity[i] = breaking_data->conductivity[max_pos]; if (save_damage) damage[max_pos]++; net_t *tmp_instance = copy_instance(perm_instance, &c); uint_t av_size = 0; double cur_val = 0; for (uint_t j = 0; j < max_pos; j++) { break_edge(tmp_instance, breaking_data->break_list[j], &c); double val = breaking_data->extern_field[j]; if (save_cluster_dist) { if (val < cur_val) { av_size++; } if (val > cur_val) { avalanche_size_dist[av_size]++; av_size = 0; cur_val = val; } } } if (save_stress_field || save_voltage_field) { double *tmp_voltages = get_voltage(tmp_instance, &c); if (save_voltage_field) { for (uint_t j = 0; j < tmp_instance->graph->nv; j++) { voltage_field[3 * voltage_pos] = tmp_instance->graph->vert_coords[2 * j]; voltage_field[3 * voltage_pos + 1] = tmp_instance->graph->vert_coords[2 * j + 1]; voltage_field[3 * voltage_pos + 2] = tmp_voltages[j]; voltage_pos++; } } if (save_stress_field) { double *tmp_currents = get_current_v(tmp_instance, tmp_voltages, &c); for (uint_t j = 0; j < tmp_instance->graph->ne; j++) { stress_field[3 * stress_pos] = tmp_instance->graph->edge_coords[2 * j]; stress_field[3 * stress_pos + 1] = tmp_instance->graph->edge_coords[2 * j + 1]; stress_field[3 * stress_pos + 2] = tmp_currents[j]; stress_pos++; } free(tmp_currents); } free(tmp_voltages); } if (save_damage_field) { for (uint_t j = 0; j < max_pos; j++) { damage_field[2 * damage_pos] = tmp_instance->graph->edge_coords[2 * breaking_data->break_list[j]]; damage_field[2 * damage_pos + 1] = tmp_instance->graph->edge_coords[2 * breaking_data->break_list[j] + 1]; damage_pos++; } } if (save_toughness) { double tmp_toughness = 0; if (max_pos > 0) { double sigma1 = breaking_data->extern_field[0]; double epsilon1 = sigma1 / breaking_data->conductivity[0]; for (uint_t j = 0; j < max_pos - 1; j++) { double sigma2 = breaking_data->extern_field[j+1]; double epsilon2 = sigma2 / breaking_data->conductivity[j+1]; if (epsilon2 > epsilon1) { tmp_toughness += (sigma1 + sigma2) * (epsilon2 - epsilon1) / 2; sigma1 = sigma2; epsilon1 = epsilon2; } } } toughness[i] = tmp_toughness; } if (save_cluster_dist) { uint_t *tmp_cluster_dist = get_cluster_dist(tmp_instance, &c); for (uint_t j = 0; j < tmp_instance->graph->dnv; j++) { cluster_size_dist[j] += tmp_cluster_dist[j]; } free(tmp_cluster_dist); } if (save_network) { FILE *net_out = fopen("network.txt", "w"); for (uint_t j = 0; j < graph->nv; j++) { fprintf(net_out, "%f %f ", graph->vert_coords[2 * j], tmp_instance->graph->vert_coords[2 * j + 1]); } fprintf(net_out, "\n"); for (uint_t j = 0; j < tmp_instance->graph->ne; j++) { fprintf(net_out, "%u %u ", tmp_instance->graph->ev[2 * j], tmp_instance->graph->ev[2 * j + 1]); } fprintf(net_out, "\n"); for (uint_t j = 0; j < tmp_instance->graph->dnv; j++) { fprintf(net_out, "%f %f ", tmp_instance->graph->dual_vert_coords[2 * j], tmp_instance->graph->dual_vert_coords[2 * j + 1]); } fprintf(net_out, "\n"); for (uint_t j = 0; j < tmp_instance->graph->ne; j++) { fprintf(net_out, "%u %u ", tmp_instance->graph->dev[2 * j], tmp_instance->graph->dev[2 * j + 1]); } fprintf(net_out, "\n"); for (uint_t j = 0; j < tmp_instance->graph->ne; j++) { fprintf(net_out, "%d ", tmp_instance->fuses[j]); } fclose(net_out); } free_instance(tmp_instance, &c); free_instance(perm_instance, &c); free_net(graph, &c); if (include_breaking) { for (uint_t j = 0; j < breaking_data->num_broken; j++) { fprintf(break_out, "%u %g %g ", breaking_data->break_list[j], breaking_data->extern_field[j], breaking_data->conductivity[j]); } fprintf(break_out, "\n"); } free_break_data(breaking_data); } printf("\033[F\033[JFRACTURE: COMPLETE\n"); if (save_cluster_dist) { FILE *cluster_out = fopen(c_filename, "wb"); FILE *avalanche_out = fopen(a_filename, "wb"); fwrite(cluster_size_dist, sizeof(uint32_t), c_dist_size, cluster_out); fwrite(avalanche_size_dist, sizeof(uint32_t), a_dist_size, avalanche_out); fclose(cluster_out); fclose(avalanche_out); free(c_filename); free(a_filename); free(cluster_size_dist); free(avalanche_size_dist); } if (save_voltage_field) { char *vfld_filename = (char *)malloc(filename_len * sizeof(char)); snprintf(vfld_filename, filename_len, "vfld_v_%c_%c_%d_%g_%g.dat", boundc, boundc2, L, beta, crack_len); FILE *vfld_file = fopen(vfld_filename, "ab"); fwrite(voltage_field, sizeof(double), 3 * voltage_pos, vfld_file); fclose(vfld_file); free(vfld_filename); free(voltage_field); } if (save_stress_field) { char *cfld_filename = (char *)malloc(filename_len * sizeof(char)); snprintf(cfld_filename, filename_len, "cfld_v_%c_%c_%d_%g_%g.dat", boundc, boundc2, L, beta, crack_len); FILE *cfld_file = fopen(cfld_filename, "ab"); fwrite(stress_field, sizeof(double), 3 * stress_pos, cfld_file); fclose(cfld_file); free(cfld_filename); free(stress_field); } if (save_damage_field) { char *dfld_filename = (char *)malloc(filename_len * sizeof(char)); snprintf(dfld_filename, filename_len, "dfld_v_%c_%c_%d_%g_%g.dat", boundc, boundc2, L, beta, crack_len); FILE *dfld_file = fopen(dfld_filename, "ab"); fwrite(damage_field, sizeof(double), 2 * damage_pos, dfld_file); fclose(dfld_file); free(dfld_filename); free(damage_field); } if (save_conductivity) { char *cond_filename = (char *)malloc(filename_len * sizeof(char)); snprintf(cond_filename, filename_len, "cond_v_%c_%c_%d_%g_%g.dat", boundc, boundc2, L, beta, crack_len); FILE *cond_file = fopen(cond_filename, "ab"); fwrite(conductivity, sizeof(double), N, cond_file); fclose(cond_file); free(cond_filename); free(conductivity); } if (save_toughness) { char *tough_filename = (char *)malloc(filename_len * sizeof(char)); snprintf(tough_filename, filename_len, "tuff_v_%c_%c_%d_%g_%g.dat", boundc, boundc2, L, beta, crack_len); FILE *tough_file = fopen(tough_filename, "ab"); fwrite(toughness, sizeof(double), N, tough_file); fclose(tough_file); free(tough_filename); free(toughness); } if (save_damage) { FILE *hdam_file = fopen(d_filename, "wb"); fwrite(damage, sizeof(uint32_t), a_dist_size, hdam_file); fclose(hdam_file); free(d_filename); free(damage); } if (include_breaking) { fclose(break_out); } if (save_crit_stress) { char *str_filename = (char *)malloc(filename_len * sizeof(char)); snprintf(str_filename, filename_len, "strs_v_%c_%c_%d_%g_%g.dat", boundc, boundc2, L, beta, crack_len); FILE *str_file = fopen(str_filename, "ab"); fwrite(crit_stress, sizeof(double), N, str_file); fclose(str_file); free(str_filename); free(crit_stress); } CHOL_F(finish)(&c); return 0; }