/* pick leaves overlapping the extents */ void KDT_Pick_Extents (KDT *kd, double *extents, SET **leaves) { if (kd->d < 0) /* leaf */ { SET_Insert (NULL, leaves, kd, NULL); } else if (extents [kd->d+3] <= kd->p [kd->d]) KDT_Pick_Extents (kd->l, extents, leaves); else if (extents [kd->d] > kd->p [kd->d]) KDT_Pick_Extents (kd->r, extents, leaves); else { KDT_Pick_Extents (kd->l, extents, leaves); KDT_Pick_Extents (kd->r, extents, leaves); } }
/* export data for fracture analysis in MoFEM (return number of exported analysis instances) */ int Fracture_Export_MoFEM (BODY *bod, double volume, double quality, FILE *output) { double extents [6], *q, *u, (*p) [3]; SOLFEC *sol = bod->dom->solfec; int n, elno, fano; FS *list, *it, *jt; ELEMENT *ele; FACE *fac; MESH *msh; KDT *kd; if (!(bod->flags & BODY_CHECK_FRACTURE) || sol->mode == SOLFEC_WRITE) return 0; list = fracture_state_read (bod); if (list) { MESH *copy = MESH_Copy (bod->shape->data); MESH_Update (copy, NULL, NULL, NULL); /* reference configuration */ msh = tetrahedralize1 (copy, volume, quality, -INT_MAX, -INT_MAX, NULL); /* generate tet mesh in reference configuration */ MESH_Destroy (copy); /* allocate displacements on the tet mesh */ ERRMEM (q = malloc (6 * msh->nodes_count * sizeof (double))); u = q + 3 * msh->nodes_count; /* map faces to a kd-tree for quick point queries */ kd = KDT_Create (msh->nodes_count, (double*)msh->ref_nodes, 0.0); for (ele = msh->surfeles; ele; ele = ele->next) { ELEMENT_Ref_Extents (msh, ele, extents); for (fac = ele->faces; fac; fac = fac->next) KDT_Drop (kd, extents, fac); } //______________________________________________________ // output file start for (fano = 0, fac = msh->faces; fac; fano ++, fac = fac->n) fac->index = fano; /* count and index faces */ ERRMEM (p = malloc (fano * sizeof (double [3]))); /* allocate face pressures */ elno = msh->surfeles_count + msh->bulkeles_count; fprintf (output, "mOFF %d %d %d\n", msh->nodes_count, fano, elno); // file header /* map displacements from the hex to the tet mesh */ FEM_Map_State (bod->shape->data, bod->conf, bod->velo, msh, q, u); /* only bod->disp to q mapping is used */ for (n = 0; n < msh->nodes_count; n ++) { fprintf (output, "%f %f %f %f %f %f\n", msh->ref_nodes [n][0], msh->ref_nodes [n][1], msh->ref_nodes [n][2], q[3*n], q[3*n+1], q[3*n+2]); } //______________________________________________________ /* rewind the list to the end to find the last element, which corresponds to the earliest in time fracture instance */ for (it = list; it->next; it = it->next) continue; /* for (it = list; it; it = it->next) */ /* FIXME -- FIXME -- FIXME -- FIXME */ { for (n = 0; n < fano; n ++) { SET (p [n], 0.0); /* zero face pressures */ } for (jt = it; jt; jt = jt->inext) /* for each point force in this instance */ { double (*ref) [3] = msh->ref_nodes; double a [3], b [3], c [3], area; SET *set = NULL, *item; double *qa, *qb, *qc; extents [0] = jt->point[0] - jt->radius - GEOMETRIC_EPSILON; /* set up search extents */ extents [1] = jt->point[1] - jt->radius - GEOMETRIC_EPSILON; extents [2] = jt->point[2] - jt->radius - GEOMETRIC_EPSILON; extents [3] = jt->point[0] + jt->radius + GEOMETRIC_EPSILON; extents [4] = jt->point[1] + jt->radius + GEOMETRIC_EPSILON; extents [5] = jt->point[2] + jt->radius + GEOMETRIC_EPSILON; KDT_Pick_Extents (kd, extents, &set); /* pick kd-tree leaves within the extents */ for (item = SET_First (set); item; item = SET_Next (item)) { KDT *leaf = item->data; for (n = 0; n < leaf->n; n ++) { fac = leaf->data [n]; /* face dropped into this leaf */ qa = &q[3*fac->nodes[0]]; qb = &q[3*fac->nodes[1]]; qc = &q[3*fac->nodes[2]]; ADD (ref[fac->nodes[0]], qa, a); /* current face nodes */ ADD (ref[fac->nodes[1]], qb, b); ADD (ref[fac->nodes[2]], qc, c); TRIANGLE_AREA (a, b, c, area); /* current face area */ if (area > 0.0) /* XXX */ { p [fac->index][0] += jt->force [0] / area; /* add up pressure */ p [fac->index][1] += jt->force [1] / area; /* FIXME: seems to be adding up to much pressure -> divided by area */ p [fac->index][2] += jt->force [2] / area; } } } SET_Free (NULL, &set); } for (fac = msh->faces, n=0; fac; fac = fac->n, n ++) { fprintf (output, "3 %d %d %d %g %g %g\n", fac->nodes[0], fac->nodes[1], fac->nodes[2], p[n][0], p[n][1], p[n][2]); } } //______________________________________________________ for (ele = msh->surfeles; ele; ele = ele->next) { fprintf (output, "4 %d %d %d %d\n", ele->nodes[0], ele->nodes[1], ele->nodes[2], ele->nodes[3]); } for (ele = msh->bulkeles; ele; ele = ele->next) { fprintf (output, "4 %d %d %d %d\n", ele->nodes[0], ele->nodes[1], ele->nodes[2], ele->nodes[3]); } // output file complete //______________________________________________________ fracture_state_free (list); free (q); free (p); MESH_Destroy (msh); } return 0; }
/* export data for fracture analysis in Yaffems (return number of exported analysis instances) */ int Fracture_Export_Yaffems (BODY *bod, double volume, double quality, FILE *output) { double extents [6], *q, *u, (*p) [3]; SOLFEC *sol = bod->dom->solfec; int n, m, elno, fano; FS *list, *it, *jt; ELEMENT *ele; FACE *fac; MESH *msh; KDT *kd; if (!(bod->flags & BODY_CHECK_FRACTURE) || sol->mode == SOLFEC_WRITE) return 0; list = fracture_state_read (bod); if (list) { MESH *copy = MESH_Copy (bod->shape->data); MESH_Update (copy, NULL, NULL, NULL); /* reference configuration */ msh = tetrahedralize1 (copy, volume, quality, -INT_MAX, -INT_MAX, NULL); /* generate tet mesh in reference configuration */ MESH_Destroy (copy); /* allocate displacements on the tet mesh */ ERRMEM (q = malloc (6 * msh->nodes_count * sizeof (double))); u = q + 3 * msh->nodes_count; /* map faces to a kd-tree for quick point queries */ kd = KDT_Create (msh->nodes_count, (double*)msh->ref_nodes, 0.0); for (ele = msh->surfeles; ele; ele = ele->next) { ELEMENT_Ref_Extents (msh, ele, extents); for (fac = ele->faces; fac; fac = fac->next) KDT_Drop (kd, extents, fac); } fprintf (output, "%s\n", "# vtk DataFile Version 2.0"); fprintf (output, "%s\n", "Test Title"); fprintf (output, "ASCII\n"); fprintf (output, "\n"); fprintf (output, "DATASET UNSTRUCTURED_GRID\n"); fprintf (output, "POINTS %d float\n", msh->nodes_count); for (n = 0; n < msh->nodes_count; n ++) { fprintf (output, "%f %f %f\n", msh->ref_nodes [n][0], msh->ref_nodes [n][1], msh->ref_nodes [n][2]); } for (fano = 0, fac = msh->faces; fac; fano ++, fac = fac->n) fac->index = fano; /* count and index faces */ ERRMEM (p = malloc (fano * sizeof (double [3]))); /* allocate face pressures */ elno = msh->surfeles_count + msh->bulkeles_count; fprintf (output, "\n"); fprintf (output, "CELLS %d %d\n", elno + fano, elno*5 + fano*4); for (ele = msh->surfeles; ele; ele = ele->next) { fprintf (output, "4 %d %d %d %d\n", ele->nodes[0], ele->nodes[1], ele->nodes[2], ele->nodes[3]); } for (ele = msh->bulkeles; ele; ele = ele->next) { fprintf (output, "4 %d %d %d %d\n", ele->nodes[0], ele->nodes[1], ele->nodes[2], ele->nodes[3]); } for (fac = msh->faces; fac; fac = fac->n) { fprintf (output, "3 %d %d %d\n", fac->nodes[0], fac->nodes[1], fac->nodes[2]); } fprintf (output, "\n"); fprintf (output, "CELL_TYPES %d\n", elno + fano); for (n = 0; n < elno; n++) { fprintf (output, "10\n"); } for (n = 0; n < fano; n++) { fprintf (output, "5\n"); } fprintf (output, "\n"); fprintf (output, "POINT_DATA %d\n", msh->nodes_count); for (it = list, m = 0; it; it = it->next, m ++) { /* map displacements from the hex to the tet mesh */ FEM_Map_State (bod->shape->data, it->disp, bod->velo, msh, q, u); /* only it->disp to q mapping is used */ fprintf (output, "\n"); fprintf (output, "VECTORS disp%d float\n", m+1); for (n = 0; n < msh->nodes_count; n ++) { fprintf (output, "%f %f %f\n", q[3*n], q[3*n+1], q[3*n+2]); } } fprintf (output, "\n"); fprintf (output, "CELL_DATA %d\n", elno + fano); for (it = list, m = 0; it; it = it->next, m ++) { fprintf (output, "\n"); fprintf (output, "VECTORS pres%d float\n", m); for (n = 0; n < elno; n ++) /* skip elements */ { fprintf (output, "0 0 0\n"); } for (n = 0; n < fano; n ++) { SET (p [n], 0.0); /* zero face pressures */ } for (jt = it; jt; jt = jt->inext) /* for each point force in this instance */ { double (*ref) [3] = msh->ref_nodes; double a [3], b [3], c [3], area; SET *set = NULL, *item; double *qa, *qb, *qc; extents [0] = jt->point[0] - jt->radius - GEOMETRIC_EPSILON; /* set up search extents */ extents [1] = jt->point[1] - jt->radius - GEOMETRIC_EPSILON; extents [2] = jt->point[2] - jt->radius - GEOMETRIC_EPSILON; extents [3] = jt->point[0] + jt->radius + GEOMETRIC_EPSILON; extents [4] = jt->point[1] + jt->radius + GEOMETRIC_EPSILON; extents [5] = jt->point[2] + jt->radius + GEOMETRIC_EPSILON; KDT_Pick_Extents (kd, extents, &set); /* pick kd-tree leaves within the extents */ for (item = SET_First (set); item; item = SET_Next (item)) { KDT *leaf = item->data; for (n = 0; n < leaf->n; n ++) { fac = leaf->data [n]; /* face dropped into this leaf */ qa = &q[3*fac->nodes[0]]; qb = &q[3*fac->nodes[1]]; qc = &q[3*fac->nodes[2]]; ADD (ref[fac->nodes[0]], qa, a); /* current face nodes */ ADD (ref[fac->nodes[1]], qb, b); ADD (ref[fac->nodes[2]], qc, c); TRIANGLE_AREA (a, b, c, area); /* current face area */ if (area > 0.0) /* XXX */ { p [fac->index][0] += jt->force [0] / area; /* add up pressure */ p [fac->index][1] += jt->force [1] / area; p [fac->index][2] += jt->force [2] / area; } } } SET_Free (NULL, &set); } for (n = 0; n < fano; n ++) { fprintf (output, "%g %g %g\n", p[n][0], p[n][1], p[n][2]); } } fracture_state_free (list); free (q); free (p); return m; } return 0; }