Пример #1
0
inline float64 _tri_area(float64 *coors, uint32 *indices, uint32 nc)
{
#define VS(ic, id) (coors[nc*indices[ic] + id])

  uint32 id;
  float64 vv0;
  float64 v0[3], v1[3], ndir[3];

  if (nc == 2) { // 2D.
    v0[2] = 0.0;
    v1[2] = 0.0;
  }

  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);
  if (nc == 2) {
    return 0.5 * fabs(ndir[2]);
  } else {
    return 0.5 * sqrt(ndir[0] * ndir[0] + ndir[1] * ndir[1]
                      + ndir[2] * ndir[2]);
  }

#undef VS
}
Пример #2
0
/*!
  For 3D and 2D.

  @par Revision history:
  - 08.06.2006, c
  - 02.08.2006
*/
int32 orient_elements( int32 *flag, int32 flag_n_row,
		      int32 *conn, int32 conn_n_row, int32 conn_n_col,
		      float64 *coors, int32 coors_n_row, int32 coors_n_col,
		      int32 *v_roots, int32 v_roots_n_row,
		      int32 *v_vecs, int32 v_vecs_n_row, int32 v_vecs_n_col,
		      int32 *swap_from, int32 swap_from_n_row, int32 swap_from_n_col,
		      int32 *swap_to, int32 swap_to_n_row, int32 swap_to_n_col )
{
#define IR( iel, ir ) (conn[conn_n_col*(iel)+v_roots[ir]])
#define IV( iel, ir, iv ) (conn[conn_n_col*(iel)+v_vecs[v_vecs_n_col*ir+iv]])
#define CONN( iel, ip ) (conn[conn_n_col*(iel)+ip])
#define SWF( ir, is ) (swap_from[swap_from_n_col*ir+is])
#define SWT( ir, is ) (swap_to[swap_to_n_col*ir+is])

  int32 ir, iel, ii, ip0, ip1, ip2, ip3, tmp, nc;
  float64 v0[3], v1[3], v2[3], v3[3], cross[3], dot[1];

  nc = coors_n_col;
  if (nc == 4) { // 3D.
    for (iel = 0; iel < conn_n_row; iel++) {
      flag[iel] = 0;

      for (ir = 0; ir < v_roots_n_row; ir++) {
	ip0 = IR( iel, ir );
	ip1 = IV( iel, ir, 0 );
	ip2 = IV( iel, ir, 1 );
	ip3 = IV( iel, ir, 2 );
	for (ii = 0; ii < 3; ii++) {
	  v0[ii] = coors[nc*ip0+ii];
	  v1[ii] = coors[nc*ip1+ii] - v0[ii];
	  v2[ii] = coors[nc*ip2+ii] - v0[ii];
	  v3[ii] = coors[nc*ip3+ii] - v0[ii];
	}
	gtr_cross_product( cross, v1, v2 );
	gtr_dot_v3( dot, v3, cross );
/*       output( "%d %d -> %d %d %d %d %e\n", iel, ir, ip0, ip1, ip2, ip3, */
/* 	      dot[0] ); */
	if (dot[0] < CONST_MachEps) {
	  flag[iel]++;
	  for (ii = 0; ii < swap_from_n_col; ii++) {
	    SwapValues( CONN( iel, SWF( ir, ii ) ),
			CONN( iel, SWT( ir, ii ) ), tmp );
/* 	  output( "%d %d\n", SWF( ir, ii ), SWT( ir, ii ) ); */
	  }
	}
      }
/*     sys_pause(); */
    }
  } else if (nc == 3) { // 2D.
    for (iel = 0; iel < conn_n_row; iel++) {
      flag[iel] = 0;

      for (ir = 0; ir < v_roots_n_row; ir++) {
	ip0 = IR( iel, ir );
	ip1 = IV( iel, ir, 0 );
	ip2 = IV( iel, ir, 1 );
	for (ii = 0; ii < 2; ii++) {
	  v0[ii] = coors[nc*ip0+ii];
	  v1[ii] = coors[nc*ip1+ii] - v0[ii];
	  v2[ii] = coors[nc*ip2+ii] - v0[ii];
	}
	v1[2] = v2[2] = 0.0;
	gtr_cross_product( cross, v1, v2 );
	if (cross[2] < CONST_MachEps) {
	  flag[iel]++;
	  for (ii = 0; ii < swap_from_n_col; ii++) {
	    SwapValues( CONN( iel, SWF( ir, ii ) ),
			CONN( iel, SWT( ir, ii ) ), tmp );
	  }
	}
      }
    }
  }
  
  return( RET_OK );

#undef IR
#undef IV
#undef CONN
#undef SWF
#undef SWT
}
Пример #3
0
// `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
}
Пример #4
0
// `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
}