function fem_basis_t6_display ( node_file, element_file ) %*****************************************************************************80 % %% FEM_BASIS_T6_DISPLAY displays a finite element T6 basis. % % Discussion: % % This program reads a data file defining a set of nodes, and a % data file defining the triangulation of those nodes using 6 node triangles. % % It is assumed that the 6 node triangles have straight sides, that is, % that each midside node lies on the line segment connecting the % corresponding vertices. % % The program then asks the user interactively to select one of the % nodes. It computes the basis function associated with that node % and displays it over the entire mesh. Of course, the basis function % will only be nonzero over a small number of the elements, but it % is instructive to see the entire mesh. % % The display is initially "flat", but by using the manipulator % on the graphics menu, the user can easily get some dramatic images % of the basis function. % % Usage: % % fem_basis_t6_display ( 'node_file.txt', 'element_file.txt' ) % % Licensing: % % This code is distributed under the GNU LGPL license. % % Modified: % % 13 March 2009 % % Author: % % John Burkardt % timestamp ( ); fprintf ( 1, '\n' ); fprintf ( 1, 'FEM_BASIS_T6_DISPLAY:\n' ); fprintf ( 1, ' MATLAB version\n' ); fprintf ( 1, ' Display basis functions associated with \n' ); fprintf ( 1, ' a finite element grid of quadratic triangles ("T6").\n' ); fprintf ( 1, '\n' ); fprintf ( 1, ' This program reads two files:\n' ); fprintf ( 1, '\n' ); fprintf ( 1, ' * node_file, the node file,\n' ); fprintf ( 1, ' * element_file, the element file,\n' ); fprintf ( 1, '\n' ); fprintf ( 1, ' The user specifies a basis function by node index,\n' ); fprintf ( 1, ' and the program displays a surface plot of that basis function.\n' ); fprintf ( 1, ' (Use the 3D ROTATE option to see the full picture!\n' ); % % Read the data. % node_xy = load ( node_file )'; [ dim_num, node_num ] = size ( node_xy ); element_node = load ( element_file )'; [ element_order, element_num ] = size ( element_node ); if ( element_order ~= 6 ) fprintf ( 1, '\n' ); fprintf ( 1, 'FEM_BASIS_T6_DISPLAY\n' ); fprintf ( 1, ' This program requires that the elements have order 6.\n' ); fprintf ( 1, ' Your elements have order %d\n', element_order ); error ( 'FEM_BASIS_T6_DISPLAY - Fatal error!' ); end x_min = min ( node_xy(1,:) ); x_max = max ( node_xy(1,:) ); y_min = min ( node_xy(2,:) ); y_max = max ( node_xy(2,:) ); node_min = min ( min ( element_node ) ); node_max = max ( max ( element_node ) ); fprintf ( 1, '\n' ); fprintf ( 1, ' Every basis function is associated with a node.\n' ); fprintf ( 1, ' To chooose a basis function, you specify a node.\n' ); fprintf ( 1, ' Nodes range in value from %d to %d.\n', node_min, node_max ); while ( 1 ) fprintf ( 1, '\n' ); prompt = sprintf ( 'Enter a node between %d and %d: ', node_min, node_max ); node_index = input ( prompt ); if ( node_index < node_min | node_max < node_index ) break end % % Clear the graphics page. % clf fprintf ( 1, '\n' ); z_min = 0.0; z_max = 0.0; for element = 1 : element_num pt(1,1:6) = node_xy(1,element_node(1:6,element)); pt(2,1:6) = node_xy(2,element_node(1:6,element)); local = 0; for j = 1 : element_order if ( element_node(j,element) == node_index ) local = j; fprintf ( 1, ' Node %d occurs as local node %d in element %d.\n', ... node_index, j, element ); end end % % If the node is not part of this element, we can draw the zero patch easily. % if ( local == 0 ) x = zeros(2,2); y = zeros(2,2); z = zeros(2,2); x(1,1) = pt(1,1); y(1,1) = pt(2,1); x(2,1) = pt(1,1); y(2,1) = pt(2,1); x(1,2) = pt(1,2); y(1,2) = pt(2,2); x(2,2) = pt(1,3); y(2,2) = pt(2,3); % % If the node is part of this element, then we want to use an 11x11 grid of points % to sample the (reference) element and generate data for a smooth surface. % else x = zeros(11,11); y = zeros(11,11); z = zeros(11,11); for i = 0 : 10 % % To use SURFACE, we need to define a logical rectangular grid of points. % But our region is a triangle, so the easiest thing to do is to identify % two corners of the grid. % We try to do this in such a way that the same thing happens in each % element, and the resulting grid looks less haphazard. % if ( local == 1 | local == 5 ) xlo = ( ( 10 - i ) * pt(1,1) + i * pt(1,2) ) / 10; ylo = ( ( 10 - i ) * pt(2,1) + i * pt(2,2) ) / 10; xhi = ( ( 10 - i ) * pt(1,1) + i * pt(1,3) ) / 10; yhi = ( ( 10 - i ) * pt(2,1) + i * pt(2,3) ) / 10; elseif ( local == 2 | local == 6 ) xlo = ( ( 10 - i ) * pt(1,2) + i * pt(1,1) ) / 10; ylo = ( ( 10 - i ) * pt(2,2) + i * pt(2,1) ) / 10; xhi = ( ( 10 - i ) * pt(1,2) + i * pt(1,3) ) / 10; yhi = ( ( 10 - i ) * pt(2,2) + i * pt(2,3) ) / 10; elseif ( local == 3 | local == 4 ) xlo = ( ( 10 - i ) * pt(1,3) + i * pt(1,2) ) / 10; ylo = ( ( 10 - i ) * pt(2,3) + i * pt(2,2) ) / 10; xhi = ( ( 10 - i ) * pt(1,3) + i * pt(1,1) ) / 10; yhi = ( ( 10 - i ) * pt(2,3) + i * pt(2,1) ) / 10; end for j = 0 : 10 pp(1) = ( ( 10 - j ) * xlo + j * xhi ) / 10; pp(2) = ( ( 10 - j ) * ylo + j * yhi ) / 10; zz = basis_11_t6 ( pt, local, pp ); z_min = min ( z_min, zz ); z_max = max ( z_max, zz ); x(i+1,j+1) = pp(1); y(i+1,j+1) = pp(2); z(i+1,j+1) = zz; end end end caxis ( 'auto' ) surface ( x, y, z, 'FaceColor', 'interp' ) end % % Using SHADING FACETED draws nice little boundary lines between each patch. % However, the way we draw the basis function means that that surface is simply % covered in black lines, losing all the color information. % % SHADING INTERP loses the little boundary lines, but allows the color information % to be seen. % % You have your clumsy choice of ONE or THE OTHER. % % shading faceted; shading interp; axis ( [ x_min, x_max, y_min, y_max, z_min, z_max ] ); axis equal xlabel ( '--X axis--' ) ylabel ( '--Y axis--' ) zlabel ( '--Z axis--' ) title_string = sprintf ( 'T6 basis function for node %d', node_index ); title ( title_string ); fprintf ( 1, '\n' ); fprintf ( 1, ' %f <= Z <= %f\n', z_min, z_max ); fprintf ( 1, 'Press return...\n' ); pause end fprintf ( 1, '\n' ); fprintf ( 1, 'FEM_BASIS_T6_DISPLAY:\n' ); fprintf ( 1, ' Normal end of execution.\n' ); fprintf ( 1, '\n' ); timestamp ( ); return end