static Element * mesh_find_large_element( const Mesh *mesh, gdouble max_element_area ) { GList *elements_iter; for ( elements_iter = mesh->elements; elements_iter != NULL; elements_iter = g_list_next( elements_iter ) ) { if ( element_area( ELEMENT( elements_iter->data ) ) > max_element_area ) return ELEMENT( elements_iter->data ); } return NULL; }
/* This function evaluates the quality of an element, based on the 2D quality * functional proposed by Lipnikov et. al.. The description for the functional * is taken from: Yu. V. Vasileskii and K. N. Lipnikov, An Adaptive Algorithm * for Quasioptimal Mesh Generation, Computational Mathematics and Mathematical * Physics, Vol. 39, No. 9, 1999, pp. 1468 - 1486. */ double Mesh::element_quality(size_t eid) const{ const size_t *n = &ENList[3*eid]; // Pointers to the coordinates of each vertex const double *c0 = &coords[2*n[0]]; const double *c1 = &coords[2*n[1]]; const double *c2 = &coords[2*n[2]]; // Pointers to the metric tensor at each vertex const double *m0 = &metric[3*n[0]]; //const const double *m1 = &metric[3*n[1]]; //const const double *m2 = &metric[3*n[2]]; //const // Metric tensor averaged over the element const double m00 = (m0[0] + m1[0] + m2[0])/3; //const const double m01 = (m0[1] + m1[1] + m2[1])/3; //const const double m11 = (m0[2] + m1[2] + m2[2])/3; //const // l is the length of the perimeter, measured in metric space const double c0010 = c0[0] - c1[0]; const double c0111 = c0[1] - c1[1]; const double c0020 = c0[0] - c2[0]; const double c0121 = c0[1] - c2[1]; const double c2010 = c2[0] - c1[0]; const double c2111 = c2[1] - c1[1]; const double l = sqrt(c0111*(c0111*m11 + 2*c0010*m01) + c0010*c0010*m00)+ sqrt(c0121*(c0121*m11 + 2*c0020*m01) + c0020*c0020*m00)+ sqrt(c2111*(c2111*m11 + 2*c2010*m01) + c2010*c2010*m00); // Area in physical space const double a = element_area(eid); // Area in metric space const double a_m = a * sqrt(m00*m11 - m01*m01); //const // Function const double f = std::min(l/3.0, 3.0/l); const double F = pow(f * (2.0 - f), 3.0); // This is the 2D Lipnikov functional. double quality = 12.0 * sqrt(3.0) * a_m * F / (l*l); return quality; }
/* This function evaluates the quality of an element, based on the 2D quality * functional proposed by Lipnikov et. al.. The description for the functional * is taken from: Yu. V. Vasileskii and K. N. Lipnikov, An Adaptive Algorithm * for Quasioptimal Mesh Generation, Computational Mathematics and Mathematical * Physics, Vol. 39, No. 9, 1999, pp. 1468 - 1486. */ float Mesh::element_quality(size_t eid) const{ const size_t *n = &ENList[3*eid]; // Pointers to the coordinates of each vertex const float *c0 = &coords[2*n[0]]; const float *c1 = &coords[2*n[1]]; const float *c2 = &coords[2*n[2]]; // Pointers to the metric tensor at each vertex const float *m0 = &metric[3*n[0]]; const float *m1 = &metric[3*n[1]]; const float *m2 = &metric[3*n[2]]; // Metric tensor averaged over the element float m00 = (m0[0] + m1[0] + m2[0])/3; float m01 = (m0[1] + m1[1] + m2[1])/3; float m11 = (m0[2] + m1[2] + m2[2])/3; // l is the length of the perimeter, measured in metric space float l = sqrt((c0[1] - c1[1])*((c0[1] - c1[1])*m11 + (c0[0] - c1[0])*m01) + (c0[0] - c1[0])*((c0[1] - c1[1])*m01 + (c0[0] - c1[0])*m00))+ sqrt((c0[1] - c2[1])*((c0[1] - c2[1])*m11 + (c0[0] - c2[0])*m01) + (c0[0] - c2[0])*((c0[1] - c2[1])*m01 + (c0[0] - c2[0])*m00))+ sqrt((c2[1] - c1[1])*((c2[1] - c1[1])*m11 + (c2[0] - c1[0])*m01) + (c2[0] - c1[0])*((c2[1] - c1[1])*m01 + (c2[0] - c1[0])*m00)); // Area in physical space float a = element_area(eid); // Area in metric space float a_m = a*sqrt(m00*m11 - m01*m01); // Function float f = std::min(l/3.0, 3.0/l); float F = pow(f * (2.0 - f), 3.0); // This is the 2D Lipnikov functional. float quality = 12.0 * sqrt(3.0) * a_m * F / (l*l); return quality; }
int test_element( int argc, char *argv[] ) { Element *e = element_new(); g_return_val_if_fail( e->adjacent_halfedge == NULL , 1 ); element_free( e ); Point2 p1, p2, p3; point2_set( &p1, 0.0, 1.0 ); point2_set( &p2, 0.0, 0.0 ); point2_set( &p3, sqrt( 3.0 ), 0.0 ); gdouble a1, a2, a3; triangle_angles( &p1, &p2, &p3, &a1, &a2, &a3 ); g_return_val_if_fail( fabs( a1 - G_PI/3.0) < SMALL_NUMBER, 1 ); g_return_val_if_fail( fabs( a2 - G_PI/2.0) < SMALL_NUMBER, 1 ); g_return_val_if_fail( fabs( a3 - G_PI/6.0) < SMALL_NUMBER, 1 ); a1 = triangle_circumcircle_radius( &p1, &p2, &p3 ); g_return_val_if_fail( fabs( a1 - 1.0 ) < SMALL_NUMBER, 1 ); a1 = triangle_circumcircle_radius_edge_length( 1.0, sqrt( 3.0 ), 2.0 ); g_return_val_if_fail( fabs( a1 - 1.0 ) < SMALL_NUMBER, 1 ); Point2 p; triangle_circumcenter_coordinates( &p1, &p2, &p3, &p ); g_return_val_if_fail( fabs( p.x - sqrt( 3.0 )/2.0 ) < SMALL_NUMBER, 1 ); g_return_val_if_fail( fabs( p.y - 1.0/2.0 ) < SMALL_NUMBER, 1 ); a1 = triangle_area( &p1, &p2, &p3 ); g_return_val_if_fail( fabs( a1 - sqrt( 3.0 )/2.0 ) < SMALL_NUMBER, 1 ); Mesh *mesh = mesh_new(); Node *n1 = mesh_add_node( mesh, 0.0, 1.0 ); Node *n2 = mesh_add_node( mesh, 0.0, 0.0 ); Node *n3 = mesh_add_node( mesh, sqrt(3.0), 0.0 ); Edge *e1 = mesh_add_edge( mesh, n1, n2 ); Edge *e2 = mesh_add_edge( mesh, n2, n3 ); Edge *e3 = mesh_add_edge( mesh, n3, n1 ); Element *el = mesh_add_element( mesh, &e1->he[0], &e2->he[0], &e3->he[0] ); gdouble l1, l2, l3; element_edge_lengths( el, &l1, &l2, &l3 ); g_return_val_if_fail( fabs( l1 - 1.0) < SMALL_NUMBER, 1); g_return_val_if_fail( fabs( l2 - sqrt(3.0)) < SMALL_NUMBER, 1); g_return_val_if_fail( fabs( l3 - 2.0) < SMALL_NUMBER, 1); HalfEdge *he = element_min_edge( el, &l1 ); g_return_val_if_fail( he->edge == e1, 1 ); g_return_val_if_fail( fabs( l1 - 1.0) < SMALL_NUMBER, 1); l1 = element_min_edge_length( el ); g_return_val_if_fail( fabs( l1 - 1.0) < SMALL_NUMBER, 1); he = element_max_edge( el, &l1 ); g_return_val_if_fail( he->edge == e3, 1 ); g_return_val_if_fail( fabs( l1 - 2.0) < SMALL_NUMBER, 1); l1 = element_max_edge_length( el ); g_return_val_if_fail( fabs( l1 - 2.0) < SMALL_NUMBER, 1); element_angles( el, &a1, &a2, &a3 ); g_return_val_if_fail( fabs( a1 - G_PI/3.0) < SMALL_NUMBER, 1); g_return_val_if_fail( fabs( a2 - G_PI/2.0) < SMALL_NUMBER, 1); g_return_val_if_fail( fabs( a3 - G_PI/6.0) < SMALL_NUMBER, 1); a1 = element_maximum_angle( el ); g_return_val_if_fail( fabs( a1 - G_PI/2.0) < SMALL_NUMBER, 1); a1 = element_minimum_angle( el ); g_return_val_if_fail( fabs( a1 - G_PI/6.0) < SMALL_NUMBER, 1); element_circumcenter_coordinates( el, &p ); g_return_val_if_fail( fabs( p.x - sqrt( 3.0 )/2.0 ) < SMALL_NUMBER, 1); g_return_val_if_fail( fabs( p.y - 1.0/2.0 ) < SMALL_NUMBER, 1); point2_set( NODE_POSITION( n3 ), 3.0, 0.0 ); a1 = element_area( el ); g_return_val_if_fail( fabs( a1 - 3.0/2.0) < SMALL_NUMBER, 1); return 0; }