// `volumes` must be preallocated. int32 mesh_get_volumes(Mesh *mesh, float64 *volumes, int32 dim) { #define VS(ic, id) (coors[nc*entity_vertices->indices[ic] + id]) int32 ret = RET_OK; uint32 D = mesh->topology->max_dim; uint32 nc = mesh->geometry->dim; uint32 id; uint32 indx2[6]; float64 vol, aux, vv0, vv1, vv2, vv3; float64 *ptr = volumes; float64 *coors = mesh->geometry->coors; float64 v0[3], v1[3], v2[3], ndir[3]; Indices entity_vertices[1]; MeshEntityIterator it0[1]; MeshConnectivity *cd0 = 0; // d -> 0 if (!dim) { errput("vertices have no volume!\n"); ERR_CheckGo(ret); } cd0 = mesh->topology->conn[IJ(D, dim, 0)]; for (mei_init(it0, mesh, dim); mei_go(it0); mei_next(it0)) { me_get_incident2(it0->entity, entity_vertices, cd0); /* mei_print(it0, stdout); */ /* ind_print(entity_vertices, stdout); */ vol = 0; if (dim == 1) { // Edges. for (id = 0; id < nc; id++) { aux = VS(1, id) - VS(0, id); vol += aux * aux; } ptr[0] = sqrt(vol); } else if (entity_vertices->num == 3) { // Triangles. ptr[0] = _tri_area(coors, entity_vertices->indices, nc); } else if (nc == 2) { // Quadrilateral cells. ptr[0] = _tri_area(coors, entity_vertices->indices, nc); indx2[0] = entity_vertices->indices[2]; indx2[1] = entity_vertices->indices[3]; indx2[2] = entity_vertices->indices[0]; ptr[0] += _tri_area(coors, indx2, nc); } else if (nc == 3) { // 3D. if (entity_vertices->num == 4) { if (dim == 2) { // Quadrilateral faces (approximate). indx2[0] = entity_vertices->indices[0]; indx2[1] = entity_vertices->indices[1]; indx2[2] = entity_vertices->indices[2]; indx2[3] = entity_vertices->indices[3]; indx2[4] = entity_vertices->indices[0]; indx2[5] = entity_vertices->indices[1]; aux = _tri_area(coors, indx2, nc); aux += _tri_area(coors, indx2 + 1, nc); aux += _tri_area(coors, indx2 + 2, nc); aux += _tri_area(coors, indx2 + 3, nc); ptr[0] = 0.5 * aux; } else { // Tetrahedral cells. for (id = 0; id < nc; id++) { vv0 = VS(0, id); vv1 = VS(1, id); vv2 = VS(2, id); vv3 = VS(3, id); v0[id] = vv1 - vv0; v1[id] = vv2 - vv0; v2[id] = vv3 - vv2; } gtr_cross_product(ndir, v0, v1); gtr_dot_v3(ptr, v2, ndir, 3); ptr[0] /= 6.0; } } else { // Hexahedral cells with trilinear interpolation. // See https://math.stackexchange.com/questions/1628540/what-is-the-enclosed-volume-of-an-irregular-cube-given-the-x-y-z-coordinates-of // Uses 0 1 3 2 4 5 7 6 ordering w.r.t. sfepy. aux = _aux_hex(coors, entity_vertices->indices, nc, 0, 1, 3, 2); aux -= _aux_hex(coors, entity_vertices->indices, nc, 4, 5, 7, 6); aux -= _aux_hex(coors, entity_vertices->indices, nc, 0, 1, 4, 5); aux += _aux_hex(coors, entity_vertices->indices, nc, 3, 2, 7, 6); aux += _aux_hex(coors, entity_vertices->indices, nc, 0, 3, 4, 7); aux -= _aux_hex(coors, entity_vertices->indices, nc, 1, 2, 5, 6); ptr[0] = aux / 12.0; } } ptr += 1; } end_label: return(ret); #undef VS }
int32 mesh_intersect(Mesh *mesh, int32 d1, int32 d2, int32 d3) { int32 ret = RET_OK; uint32 D = mesh->topology->max_dim; uint32 n_incident, ii; uint32 *nd2 = 0; char *mask = 0; MeshEntityIterator it1[1], it2[1], it3[1]; Indices ei1[1], ei2[1]; MeshConnectivity *c12 = 0; // d1 -> d2 - to compute MeshConnectivity *c10 = 0; // d1 -> 0 - known MeshConnectivity *c20 = 0; // d2 -> 0 - known debprintf("intersect %d -> %d (%d)\n", d1, d2, d3); if (d1 < d2) { errput("d1 must be greater or equal to d2 in mesh_intersect()!\n"); ERR_CheckGo(ret); } c12 = mesh->topology->conn[IJ(D, d1, d2)]; if (d1 > d2) { c10 = mesh->topology->conn[IJ(D, d1, 0)]; c20 = mesh->topology->conn[IJ(D, d2, 0)]; } mask = alloc_mem(char, mesh->topology->num[d2]); // Count entities of d2 -> d1. conn_alloc(c12, mesh->topology->num[d1], 0); ERR_CheckGo(ret); nd2 = c12->offsets + 1; for (mei_init(it1, mesh, d1); mei_go(it1); mei_next(it1)) { // Clear mask for it1 incident entities of dimension d2. for (mei_init_conn(it3, it1->entity, d3); mei_go(it3); mei_next(it3)) { for (mei_init_conn(it2, it3->entity, d2); mei_go(it2); mei_next(it2)) { mask[it2->entity->ii] = 0; } } for (mei_init_conn(it3, it1->entity, d3); mei_go(it3); mei_next(it3)) { for (mei_init_conn(it2, it3->entity, d2); mei_go(it2); mei_next(it2)) { if (mask[it2->entity->ii]) continue; mask[it2->entity->ii] = 1; if (d1 == d2) { if (it1->entity->ii != it2->entity->ii) { nd2[it1->entity->ii]++; } } else { // Get incident vertices. me_get_incident2(it1->entity, ei1, c10); me_get_incident2(it2->entity, ei2, c20); if (contains(ei1, ei2)) { nd2[it1->entity->ii]++; } } } } } // c12->offsets now contains counts - make a cumsum to get offsets. for (ii = 1; ii < c12->num + 1; ii++) { c12->offsets[ii] += c12->offsets[ii-1]; } n_incident = c12->offsets[c12->num]; debprintf("intersect n_incident (%d -> %d): %d\n", d1, d2, n_incident); // Fill in the indices. conn_alloc(c12, 0, n_incident); ERR_CheckGo(ret); for (ii = 0; ii < c12->n_incident; ii++) { c12->indices[ii] = UINT32_None; // "not set" value. } for (mei_init(it1, mesh, d1); mei_go(it1); mei_next(it1)) { // Clear mask for it1 incident entities of dimension d2. for (mei_init_conn(it3, it1->entity, d3); mei_go(it3); mei_next(it3)) { for (mei_init_conn(it2, it3->entity, d2); mei_go(it2); mei_next(it2)) { mask[it2->entity->ii] = 0; } } for (mei_init_conn(it3, it1->entity, d3); mei_go(it3); mei_next(it3)) { for (mei_init_conn(it2, it3->entity, d2); mei_go(it2); mei_next(it2)) { if (mask[it2->entity->ii]) continue; mask[it2->entity->ii] = 1; if (d1 == d2) { if (it1->entity->ii != it2->entity->ii) { conn_set_to_free(c12, it1->entity->ii, it2->entity->ii); ERR_CheckGo(ret); } } else { // Get incident vertices. me_get_incident2(it1->entity, ei1, c10); me_get_incident2(it2->entity, ei2, c20); if (contains(ei1, ei2)) { conn_set_to_free(c12, it1->entity->ii, it2->entity->ii); ERR_CheckGo(ret); } } } } } end_label: free_mem(mask); return(ret); }
int32 mesh_build(Mesh *mesh, int32 dim) { int32 ret = RET_OK; uint32 n_incident, n_v_max, n_loc; uint32 ii, ic, id, found; uint32 D = mesh->topology->max_dim; uint32 facet[4]; // Max. space for single facet. uint32 *oris = 0; uint32 loc_oris[12]; uint32 *nDd = 0; uint32 *ptr1 = 0, *ptr2 = 0; uint32 *cell_types = mesh->topology->cell_types; Indices cell_vertices[1]; MeshEntityIterator it0[1], it1[1], it2[1]; MeshConnectivity *cD0 = 0; // D -> 0 - known MeshConnectivity *cDd = 0; // D -> d - to compute MeshConnectivity *cd0 = 0; // d -> 0 - to compute MeshConnectivity **locs = 0; MeshConnectivity *loc = 0; MeshConnectivity sloc[1]; // Local connectivity with sorted global vertices. MeshConnectivity gloc[1]; // Local connectivity with global vertices. debprintf("build %d\n", dim); if (!mesh->topology->conn[IJ(D, D, D)]->num) { mesh_setup_connectivity(mesh, D, D); } cD0 = mesh->topology->conn[IJ(D, D, 0)]; cDd = mesh->topology->conn[IJ(D, D, dim)]; cd0 = mesh->topology->conn[IJ(D, dim, 0)]; locs = (dim == 1) ? mesh->entities->edges : mesh->entities->faces; // Max. number of vertices in facets. n_v_max = (dim == 1) ? 2 : 4; // Count entities of D -> d. conn_alloc(cDd, mesh->topology->num[D], 0); ERR_CheckGo(ret); nDd = cDd->offsets + 1; for (mei_init(it0, mesh, D); mei_go(it0); mei_next(it0)) { loc = locs[cell_types[it0->it]]; nDd[it0->it] = loc->num; } // cDd->offsets now contains counts - make a cumsum to get offsets. for (ii = 1; ii < cDd->num + 1; ii++) { cDd->offsets[ii] += cDd->offsets[ii-1]; } n_incident = cDd->offsets[cDd->num]; debprintf("build n_incident (%d -> %d): %d\n", D, dim, n_incident); // Cell-local orientations w.r.t. D -> d. oris = alloc_mem(uint32, n_incident); if (dim == 2) { free_mem(mesh->topology->face_oris); mesh->topology->face_oris = oris; } else { free_mem(mesh->topology->edge_oris); mesh->topology->edge_oris = oris; } // Allocate D -> d indices. conn_alloc(cDd, 0, n_incident); ERR_CheckGo(ret); for (ii = 0; ii < cDd->n_incident; ii++) { cDd->indices[ii] = UINT32_None; // "not set" value. } // Allocate maximal buffers for d -> 0 arrays. conn_alloc(cd0, n_incident, n_incident * n_v_max); debprintf("build max. n_incident_vertex: %d\n", n_incident * n_v_max); // Allocate maximal buffers for local connectivity with sorted global // vertices. Counts have to be set to zero to avoid spurious calls to // conn_free()! sloc->num = sloc->n_incident = 0; conn_alloc(sloc, 12, n_v_max * 12); gloc->num = gloc->n_incident = 0; conn_alloc(gloc, 12, n_v_max * 12); id = 0; for (mei_init(it0, mesh, D); mei_go(it0); mei_next(it0)) { // Get vertex sets for local entities of current cell. loc = locs[cell_types[it0->it]]; me_get_incident2(it0->entity, cell_vertices, cD0); get_local_connectivity(gloc, cell_vertices, loc); conn_set_from(sloc, gloc); sort_local_connectivity(sloc, loc_oris, loc->num); // Iterate over entities in the vertex sets. for (ii = 0; ii < loc->num; ii++) { // ii points to a vertex set in sloc/gloc. n_loc = sloc->offsets[ii+1] - sloc->offsets[ii]; // Try to find entity in cells visited previously. for (mei_init_conn(it1, it0->entity, D); mei_go(it1); mei_next(it1)) { if (it1->entity->ii >= it0->entity->ii) continue; // Iterate over facets of visited cells. for (mei_init_conn(it2, it1->entity, dim); mei_go(it2); mei_next(it2)) { ptr1 = cd0->indices + cd0->offsets[it2->entity->ii]; uint32_sort234_copy(facet, ptr1, n_loc); ptr2 = sloc->indices + sloc->offsets[ii]; found = 1; for (ic = 0; ic < n_loc; ic++) { if (facet[ic] != ptr2[ic]) { found = 0; break; } } if (found) { // Assign existing entity to D -> d. conn_set_to_free(cDd, it0->entity->ii, it2->entity->ii); goto found_label; } } } // Entity not found - create new. // Add it as 'id' to D -> d. conn_set_to_free(cDd, it0->entity->ii, id); // Add vertices in gloc to d -> 0. cd0->offsets[id+1] = cd0->offsets[id] + n_loc; ptr1 = cd0->indices + cd0->offsets[id]; ptr2 = gloc->indices + gloc->offsets[ii]; for (ic = 0; ic < n_loc; ic++) { ptr1[ic] = ptr2[ic]; } // Increment entity counter. id++; found_label: // Store entity orientation key to position of the last used item in cDd. ptr1 = cDd->offsets + it0->entity->ii; ic = ptr1[1] - 1; while (ic >= ptr1[0]) { if (cDd->indices[ic] != UINT32_None) { // Not found & free slot. break; } ic--; } // printf("%d << %d, %d\n", ic, ii, loc_oris[ii]); oris[ic] = loc_oris[ii]; } } debprintf("build n_unique: %d, n_incident (%d -> 0): %d\n", id, dim, cd0->offsets[id]); // Update entity count in topology. mesh->topology->num[dim] = id; // Strip d -> 0. conn_resize(cd0, id, cd0->offsets[id]); end_label: conn_free(sloc); conn_free(gloc); return(ret); }
// `normals` must be preallocated. int32 mesh_get_facet_normals(Mesh *mesh, float64 *normals, int32 which) { #define VS(ic, id) (coors[nc*cell_vertices->indices[ik[ic]] + id]) uint32 D = mesh->topology->max_dim; uint32 nc = mesh->geometry->dim; int32 dim = D - 1; uint32 ii, id, n_loc; uint32 *ik; uint32 *cell_types = mesh->topology->cell_types; float64 *coors = mesh->geometry->coors; float64 vv0, vv1, vv2, vv3, v0[3], v1[3], v2[3], v3[3], ndir[3], ndir1[3]; Indices cell_vertices[1]; MeshEntityIterator it0[1]; MeshConnectivity *cD0 = 0; // D -> 0 MeshConnectivity *cDd = 0; // D -> d MeshConnectivity *loc = 0; MeshConnectivity **locs = 0; cD0 = mesh->topology->conn[IJ(D, D, 0)]; cDd = mesh->topology->conn[IJ(D, D, dim)]; // Local entities - reference cell edges or faces. locs = (dim == 1) ? mesh->entities->edges : mesh->entities->faces; for (mei_init(it0, mesh, D); mei_go(it0); mei_next(it0)) { me_get_incident2(it0->entity, cell_vertices, cD0); loc = locs[cell_types[it0->it]]; for (ii = 0; ii < loc->num; ii++) { ik = loc->indices + loc->offsets[ii]; // Points to local facet vertices. n_loc = loc->offsets[ii+1] - loc->offsets[ii]; if (n_loc == 2) { // Edge normals. for (id = 0; id < nc; id++) { v0[id] = VS(1, id) - VS(0, id); } ndir[0] = v0[1]; ndir[1] = -v0[0]; } else if (n_loc == 3) { // Triangular face normals. for (id = 0; id < nc; id++) { vv0 = VS(0, id); v0[id] = VS(1, id) - vv0; v1[id] = VS(2, id) - vv0; } gtr_cross_product(ndir, v0, v1); } else if (n_loc == 4) { // Quadrilateral face normals. for (id = 0; id < nc; id++) { vv0 = VS(0, id); vv1 = VS(1, id); vv2 = VS(2, id); vv3 = VS(3, id); v0[id] = vv1 - vv0; v1[id] = vv3 - vv0; v2[id] = vv3 - vv2; v3[id] = vv1 - vv2; } if (which == 0) { gtr_cross_product(ndir, v0, v1); } else if (which == 1) { gtr_cross_product(ndir, v2, v3); } else { gtr_cross_product(ndir, v0, v1); gtr_cross_product(ndir1, v2, v3); for (id = 0; id < nc; id++) { ndir[id] += ndir1[id]; } } } gtr_normalize_v3(ndir, ndir, nc, 0); for (id = 0; id < nc; id++) { normals[nc * (cDd->offsets[it0->it] + ii) + id] = ndir[id]; } } } return(RET_OK); #undef VS }
int32 refc_find_ref_coors(FMField *ref_coors, int32 *cells, int32 n_cells, int32 *status, int32 n_status, FMField *coors, Mesh *mesh, int32 *candidates, int32 n_candidates, int32 *offsets, int32 n_offsets, int32 allow_extrapolation, float64 qp_eps, float64 close_limit, void *_ctx) { BasisContext *ctx = (BasisContext *) _ctx; int32 ip, ic, ii, imin, ok, xi_ok, ret = RET_OK; int32 D = mesh->topology->max_dim; int32 nc = mesh->geometry->dim; float64 d_min, dist; float64 *mesh_coors = mesh->geometry->coors; float64 buf3[3]; FMField point[1], e_coors[1], xi[1]; Indices cell_vertices[1]; MeshEntity cell_ent[1]; MeshConnectivity *cD0 = 0; // D -> 0 mesh_setup_connectivity(mesh, D, 0); cD0 = mesh->topology->conn[IJ(D, D, 0)]; fmf_pretend_nc(point, coors->nRow, 1, 1, nc, coors->val); fmf_pretend_nc(xi, 1, 1, 1, nc, buf3); fmf_fillC(xi, 0.0); ctx->is_dx = 0; for (ip = 0; ip < coors->nRow; ip++) { FMF_SetCell(point, ip); if (offsets[ip] == offsets[ip+1]) { status[ip] = 5; cells[ip] = 0; for (ii = 0; ii < nc; ii++) { ref_coors->val[nc*ip+ii] = 0.0; } continue; } ok = xi_ok = 0; d_min = 1e10; imin = candidates[offsets[ip]]; for (ic = offsets[ip]; ic < offsets[ip+1]; ic++) { /* output("***** %d %d %d\n", ip, ic, candidates[ic]); */ ctx->iel = candidates[ic]; cell_ent->ii = candidates[ic]; me_get_incident2(cell_ent, cell_vertices, cD0); _get_cell_coors(e_coors, cell_vertices, mesh_coors, nc, ctx->e_coors_max->val); xi_ok = ctx->get_xi_dist(&dist, xi, point, e_coors, ctx); if (xi_ok) { if (dist < qp_eps) { imin = cell_ent->ii; ok = 1; break; } else if (dist < d_min) { d_min = dist; imin = cell_ent->ii; } } else if (dist < d_min) { d_min = dist; imin = cell_ent->ii; } } /* output("-> %d %d %d %.3e\n", imin, xi_ok, ok, d_min); */ cells[ip] = imin; if (ok != 1) { if (!xi_ok) { status[ip] = 4; } else if (allow_extrapolation) { if (sqrt(d_min) < close_limit) { status[ip] = 1; } else { status[ip] = 2; } } else { status[ip] = 3; } } else { status[ip] = 0; } for (ii = 0; ii < nc; ii++) { ref_coors->val[nc*ip+ii] = xi->val[ii]; } ERR_CheckGo(ret); } end_label: return(ret); }
int32 refc_find_ref_coors_convex(FMField *ref_coors, int32 *cells, int32 n_cells, int32 *status, int32 n_status, FMField *coors, Mesh *mesh, FMField *centroids, FMField *normals0, FMField *normals1, int32 *ics, int32 n_ics, int32 allow_extrapolation, float64 qp_eps, float64 close_limit, void *_ctx) { BasisContext *ctx = (BasisContext *) _ctx; int32 ip, ic, icell, icell_max = 0, ii, imin, ik, ok, ret = RET_OK; int32 xi_ok, hexa_reverse; int32 D = mesh->topology->max_dim; int32 dim = D - 1; int32 nc = mesh->geometry->dim; uint32 tri0[] = {0, 1, 3}; uint32 tri1[] = {2, 3, 1}; uint32 cell, cell0, cell00, facet; uint32 *noffs, *foffs, aux[2]; uint32 *cell_types = mesh->topology->cell_types; float64 d_min, tmin, tt, dist; float64 *mesh_coors = mesh->geometry->coors; float64 buf3[3]; float64 buf9[9]; FMField point[1], centroid[1], _normals0[1], _normals1[1], e_coors[1], xi[1]; Indices cell_vertices[1]; MeshEntity cell_ent[1]; MeshConnectivity *cD0 = 0; // D -> 0 MeshConnectivity *c0D = 0; // 0 -> D MeshConnectivity *cDd = 0; // cell -> facet MeshConnectivity *cdD = 0; // facet -> cell MeshConnectivity *loc = 0; MeshConnectivity **locs = 0; mesh_setup_connectivity(mesh, D, 0); cD0 = mesh->topology->conn[IJ(D, D, 0)]; mesh_setup_connectivity(mesh, 0, D); c0D = mesh->topology->conn[IJ(D, 0, D)]; mesh_setup_connectivity(mesh, D, dim); cDd = mesh->topology->conn[IJ(D, D, dim)]; noffs = cDd->offsets; mesh_setup_connectivity(mesh, dim, D); cdD = mesh->topology->conn[IJ(D, dim, D)]; // Local entities - reference cell edges or faces. locs = (dim == 1) ? mesh->entities->edges : mesh->entities->faces; fmf_pretend_nc(point, coors->nRow, 1, 1, nc, coors->val); fmf_pretend_nc(centroid, centroids->nRow, 1, 1, nc, centroids->val); fmf_pretend_nc(xi, 1, 1, 1, nc, buf3); fmf_fillC(xi, 0.0); ctx->is_dx = 0; for (ip = 0; ip < coors->nRow; ip++) { ic = ics[ip]; /* output("***** %d %d\n", ip, ic); */ FMF_SetCell(point, ip); /* fmf_print(point, stdout, 0); */ cell = cell0 = cell00 = c0D->indices[c0D->offsets[ic]]; ok = icell = hexa_reverse = imin = 0; d_min = 1e10; while (1) { /* output("*** %d %d %d\n", icell, cell, hexa_reverse); */ FMF_SetCell(centroid, cell); /* fmf_print(centroid, stdout, 0); */ ctx->iel = cell; cell_ent->ii = cell; me_get_incident2(cell_ent, cell_vertices, cD0); loc = locs[cell_types[cell]]; foffs = loc->offsets; if (cell_types[cell] != 4) { // No hexahedron -> planar facet. fmf_pretend_nc(_normals0, noffs[cell+1] - noffs[cell], 1, 1, nc, normals0->val + nc * noffs[cell]); tmin = 1e10; for (ii = 0; ii < loc->num; ii++) { FMF_SetCell(_normals0, ii); ik = loc->indices[foffs[ii]]; _intersect_line_plane(&tt, centroid->val, point->val, mesh_coors + nc * cell_vertices->indices[ik], _normals0->val, nc); if ((tt >= -qp_eps) && (tt < (tmin + qp_eps))) { imin = ii; tmin = tt; } } if (tmin >= (1.0 - qp_eps)) { _get_cell_coors(e_coors, cell_vertices, mesh_coors, nc, ctx->e_coors_max->val); /* fmf_print(e_coors, stdout, 0); */ xi_ok = ctx->get_xi_dist(&dist, xi, point, e_coors, ctx); d_min = Min(dist, d_min); if (xi_ok && (dist < qp_eps)) { ok = 1; } break; } } else { // Hexahedron -> non-planar facet in general. fmf_pretend_nc(_normals0, noffs[cell+1] - noffs[cell], 1, 1, nc, normals0->val + nc * noffs[cell]); fmf_pretend_nc(_normals1, noffs[cell+1] - noffs[cell], 1, 1, nc, normals1->val + nc * noffs[cell]); for (ii = 0; ii < loc->num; ii++) { FMF_SetCell(_normals0, ii); _get_tri_coors(buf9, loc->indices, foffs[ii], tri0, mesh_coors, cell_vertices->indices); _intersect_line_triangle(&tt, centroid->val, point->val, buf9, _normals0->val); if ((tt >= -qp_eps) && (tt < 1e10)) { ok = 2; imin = ii; if ((tt >= (1.0 - qp_eps)) || hexa_reverse) { _get_cell_coors(e_coors, cell_vertices, mesh_coors, nc, ctx->e_coors_max->val); xi_ok = ctx->get_xi_dist(&dist, xi, point, e_coors, ctx); d_min = Min(dist, d_min); if (xi_ok && (dist < qp_eps)) { ok = 1; } else { hexa_reverse = 1; } } break; } FMF_SetCell(_normals1, ii); _get_tri_coors(buf9, loc->indices, foffs[ii], tri1, mesh_coors, cell_vertices->indices); _intersect_line_triangle(&tt, centroid->val, point->val, buf9, _normals1->val); if ((tt >= -qp_eps) && (tt < 1e10)) { ok = 2; imin = ii; if ((tt >= (1.0 - qp_eps)) || hexa_reverse) { _get_cell_coors(e_coors, cell_vertices, mesh_coors, nc, ctx->e_coors_max->val); xi_ok = ctx->get_xi_dist(&dist, xi, point, e_coors, ctx); d_min = Min(dist, d_min); if (xi_ok && (dist < qp_eps)) { ok = 1; } else { hexa_reverse = 1; } } break; } } if (ok == 1) { break; } if (ok == 0) { errput("cannot intersect bilinear faces!\n"); ERR_CheckGo(ret); } } facet = cDd->indices[cDd->offsets[cell] + imin]; if ((cdD->offsets[facet+1] - cdD->offsets[facet]) == 2) { aux[0] = cdD->indices[cdD->offsets[facet]]; aux[1] = cdD->indices[cdD->offsets[facet]+1]; cell00 = cell0; cell0 = cell; cell = (aux[0] == cell) ? aux[1] : aux[0]; if (cell == cell00) { // Ping-pong between two cells. hexa_reverse = 1; } } else { // Boundary facet. ctx->iel = cell; cell_ent->ii = cell; me_get_incident2(cell_ent, cell_vertices, cD0); _get_cell_coors(e_coors, cell_vertices, mesh_coors, nc, ctx->e_coors_max->val); xi_ok = ctx->get_xi_dist(&dist, xi, point, e_coors, ctx); d_min = Min(dist, d_min); if (xi_ok && (dist < qp_eps)) { ok = 1; } else { ok = 0; } break; } icell++; icell_max = Max(icell, icell_max); if (icell > 10000) { errput("cannot find containing cell!\n"); ERR_CheckGo(ret); } } /* fmf_print(xi, stdout, 0); */ /* output("-> %d %d %d %.3e\n", cell, xi_ok, ok, d_min); */ cells[ip] = cell; if (ok != 1) { if (!xi_ok) { status[ip] = 4; } else if (allow_extrapolation) { // Try using minimum distance xi. if (sqrt(d_min) < close_limit) { status[ip] = 1; } else { status[ip] = 2; } } else { status[ip] = 3; } } else { status[ip] = 0; } for (ii = 0; ii < nc; ii++) { ref_coors->val[nc*ip+ii] = xi->val[ii]; } } /* output("%d\n", icell_max); */ end_label: return(ret); }