Raw File
build_mesh.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This file is part of NS2DDV.                                                      %
%                                                                                   %
% Copyright(C) 2011-2018    C. Calgaro  (caterina.calgaro@math.univ-lille1.fr)      %
%                           E. Creusé   (emmanuel.creuse@math.univ-lille1.fr)       %
%                           T. Goudon   (thierry.goudon@inria.fr)                   %
%                           A. Mouton   (alexandre.mouton@math.univ-lille1.fr)      %
%                                                                                   %
% NS2DDV is free software: you can redistribute it and/or modify it under the terms %
% of the GNU General Public License as published by the Free Software Foundation,   %
% either version 3 of the License, or (at your option) any later version.           %
%                                                                                   %
% NS2DDV is distributed in the hope that it will be useful, but WITHOUT ANY         %
% WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A   %
% PARTICULAR PURPOSE. See the GNU General Public License for more details.          %
%                                                                                   %
% You should have received a copy of the GNU General Public License along with      %
% NS2DDV. If not, see <http://www.gnu.org/licenses/>.                               %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function[MESH, RENUMBERING, DOMAIN] = build_mesh(PARAMETERS, oldp, oldt)

	% INPUT
	% PARAMETERS	List of simulation parameters
	% oldp			List of P1 nodes coming from an external source (optional)
	% oldt			List of P1 triangles coming from an external source (optional)
	%
	% OUTPUTS
	% MESH			An almost complete mesh metadata
	% RENUMBERING	Renumbering permutation matrices
	% DOMAIN		An almost complete domain metadata

	RENUMBERING = '';
	MESH = '';
	DOMAIN = '';

	if (exist('oldp') && exist('oldt'))
		useoldpt = true;
	elseif (~exist('oldp') && ~exist('oldt'))
		useoldpt = false;
	else
		error('Problem with call to build_mesh');
	end

	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	% 1 - Generate the list of nodes, triangles and edges %
	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	fprintf('Loading mesh... ');
	if ~useoldpt
		[MESH.p1, MESH.t1, MESH.hmax, MESH.hmin] = load_mesh(PARAMETERS);
	else
		MESH.p1 = oldp;
		MESH.t1 = oldt;
		% Compute hmax and hmin as the maximal and minimal length of an edge in the mesh
		MESH.hmax = 0.;
		MESH.hmin = max(max(MESH.p1))-min(min(MESH.p1));
		for i=1:size(MESH.t1,2)
			v1 = MESH.p1(:,MESH.t1(1,i));
			v2 = MESH.p1(:,MESH.t1(2,i));
			v3 = MESH.p1(:,MESH.t1(3,i));
			le1 = sqrt((v1(1)-v2(1))^2+(v1(2)-v2(2))^2);
			le2 = sqrt((v2(1)-v3(1))^2+(v2(2)-v3(2))^2);
			le3 = sqrt((v3(1)-v1(1))^2+(v3(2)-v1(2))^2);
			MESH.hmax = max([MESH.hmax,le1,le2,le3]);
			MESH.hmin = min([MESH.hmin,le1,le2,le3]);
		end
	end
	fprintf('done\n');
	fprintf('Extracting the edges... ');
	[MESH.e1full, MESH.be1, MESH.t1e] = edge_descriptor(MESH.t1, PARAMETERS);
	MESH.e2full = MESH.e1full;
	MESH.e1bfull = MESH.e1full;
	MESH.be2 = MESH.be1;
	MESH.be1b = MESH.be1;
	MESH.t2e = MESH.t1e;
	MESH.t1be = MESH.t1e;
	fprintf('done\n');

	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	% 2 - Add the number of nodes and the number of triangles %
	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	MESH.nt1 = size(MESH.t1,2);
	MESH.np1 = size(MESH.p1,2);
	MESH.ne1full = size(MESH.e1full,2);
	MESH.nbe1 = size(MESH.be1,2);
	MESH.ne2full = size(MESH.e2full,2);
	MESH.nbe2 = size(MESH.be2,2);
	MESH.ne1bfull = size(MESH.e1bfull,2);
	MESH.nbe1b = size(MESH.be1b,2);

	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	% 3- If necessary, complete the definition of the domain geometry and rescale the mesh %
	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	if ((strcmp(PARAMETERS.MESH.GENERATION, 'FROM_FILE') ...
							&& ~strcmp(PARAMETERS.DOMAIN.GEOMETRY, 'FROM_FILE')) || useoldpt)
		fprintf('Extracting the domain geometry... ');
		DOMAIN = extract_domain_geometry_from_mesh(MESH, PARAMETERS);
		fprintf('done\n');
		if (~useoldpt && strcmp(PARAMETERS.MESH.RESCALE, 'YES'))
			fprintf('Rescaling the mesh... ');
			[MESH.p1, MESH.hmax, MESH.hmin, DOMAIN] = rescale_mesh(MESH, DOMAIN, PARAMETERS);
			fprintf('done\n');
		end
	else
		DOMAIN = PARAMETERS.DOMAIN;
		%PHYSICAL = PARAMETERS.PHYSICAL;
	end

	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	% 4 - Add P1B and P2 nodes and triangles %
	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	fprintf('Computing Finite Element mesh metadata... ');
	[MESH.p2, MESH.np2, MESH.t2, MESH.nt2] = add_mdmesh_FE_P2(MESH);
	[MESH.p1b, MESH.np1b, MESH.t1b, MESH.nt1b] = add_mdmesh_FE_P1B(MESH);
	fprintf('done\n');

	%%%%%%%%%%%%%%%%%%%
	% 5 - Renumbering %
	%%%%%%%%%%%%%%%%%%%
	if strcmp(PARAMETERS.MESH.RENUMBERING, 'NONE')
		disp('No renumbering in the mesh');
		RENUMBERING.perm_p1  = 1:MESH.np1;
		RENUMBERING.perm_p1b = 1:MESH.np1b;
		RENUMBERING.perm_p2  = 1:MESH.np2;
		RENUMBERING.pinv_p1  = 1:MESH.np1;
		RENUMBERING.pinv_p1b = 1:MESH.np1b;
		RENUMBERING.pinv_p2  = 1:MESH.np2;
	else
		fprintf('Renumbering in the mesh... ');
		% Permutation of the vertices obtained using P1, P1B and P2 DOF
		%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
		RENUMBERING = renumbering_P1P1BP2(MESH, PARAMETERS);

		RENUMBERING.pinv_p1  = zeros(size(RENUMBERING.perm_p1 ));
		RENUMBERING.pinv_p1b = zeros(size(RENUMBERING.perm_p1b));
		RENUMBERING.pinv_p2  = zeros(size(RENUMBERING.perm_p2 ));

		RENUMBERING.pinv_p1 (RENUMBERING.perm_p1 ) = 1:MESH.np1;
		RENUMBERING.pinv_p1b(RENUMBERING.perm_p1b) = 1:MESH.np1b;
		RENUMBERING.pinv_p2 (RENUMBERING.perm_p2 ) = 1:MESH.np2;

		% Construction of new arrays using the permutations of the vertices
		% No permutation for the triangle's number or the edge's number
		%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

		MESH.p1 (:,RENUMBERING.perm_p1 ) = MESH.p1;
		MESH.p2 (:,RENUMBERING.perm_p2 ) = MESH.p2;
		MESH.p1b(:,RENUMBERING.perm_p1b) = MESH.p1b;

		for ke=1:MESH.nt1
			MESH.t1 (1:3,ke) = RENUMBERING.perm_p1(MESH.t1(1:3,ke));
			MESH.t2 (1:6,ke) = RENUMBERING.perm_p2(MESH.t2(1:6,ke));
			MESH.t1b(1:4,ke) = RENUMBERING.perm_p1b(MESH.t1b(1:4,ke));
		end

		for ie=1:MESH.nbe1
			MESH.be1(1:2,ie) = RENUMBERING.perm_p1(MESH.be1(1:2,ie));
			MESH.be2(1:2,ie) = RENUMBERING.perm_p2(MESH.be2(1:2,ie));
			MESH.be1b(1:2,ie) = RENUMBERING.perm_p1b(MESH.be1b(1:2,ie));
		end

		for ie =1:MESH.ne1full
			MESH.e1full(1:2,ie) = RENUMBERING.perm_p1(MESH.e1full(1:2,ie));
			MESH.e2full(1:2,ie) = RENUMBERING.perm_p2(MESH.e2full(1:2,ie));
			MESH.e1bfull(1:2,ie) = RENUMBERING.perm_p1b(MESH.e1bfull(1:2,ie));
		end
		fprintf('done\n');
    end

	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	% 6- Add Finite element specific descriptors %
	%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	fprintf('Computing Finite Element subtriangles... ');
	MESH.st1b = add_subtri_FE_P1B(MESH);
	MESH.st2 = add_subtri_FE_P2(MESH);
	fprintf('done\n');
	fprintf('Identifying the boundary nodes... ');
	[MESH.BS_top_p2, MESH.BS_bottom_p2, MESH.BS_left_p2, MESH.BS_right_p2] = ...
												identify_boundsegments_P2(MESH, DOMAIN);
	[MESH.BS_top_p1b, MESH.BS_bottom_p1b, MESH.BS_left_p1b, MESH.BS_right_p1b] = ...
												identify_boundsegments_P1B(MESH, DOMAIN);
	fprintf('done\n');

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    % 7 - Add Finite volume specific descriptors %
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	fprintf('Computing Finite Volume mesh metadata... ');
	if isfield(PARAMETERS,'FV')

		% Add metadata on triangles described by edges
		[MESH.edges_normal_sign, MESH.edges_non_unit_normals, MESH.edges_length] = normals(MESH);

		MESH.gamma_ratio = gamma_ratio(MESH, PARAMETERS);
		% The following value of tau depends on the tau-limiter. By default, we fix it to 1/gamma
		tau = 1./MESH.gamma_ratio;

		if (strcmp(PARAMETERS.DOMAIN.GEOMETRY, 'RECTANGLE') && ...
				strcmp(PARAMETERS.MESH.GENERATION, 'NS2DDV') && ...
				strcmp(PARAMETERS.FV.SCHEME, 'MUSCL') && ...
				strcmp(PARAMETERS.FV.CELLS_DESIGN, 'SQUARES'))
			[MESH.horizontal_edges, MESH.vertical_edges, MESH.volume, perimeter] = ...
				mesh_squares_fv(MESH, PARAMETERS);
			MESH.ciarlet_ratio = 2.;
			MESH.coef_CFL = 1000; %%%% used only for testing renumbering techniques
			%%%% used only for testing renumbering
			for i=1:MESH.np1
				MESH.coef_CFL = min(MESH.coef_CFL, ...
					MESH.volume(i)/(perimeter(i)*(2.0+tau*MESH.gamma_ratio*MESH.ciarlet_ratio)));
			end

			MESH.volume(RENUMBERING.perm_p1) = MESH.volume;
			MESH.volume_barycenter = MESH.p1;
		else
			[MESH.normal, MESH.volume, volume_P2, ...
				perimeter, MESH.volume_barycenter, barycenter_patchEF] = mesh_stars_fv_part1(MESH);
			% perimeter is local variable
			% volume_P2 and barycenter_patchEF are only used for testing renumbering techniques

			[MESH.boundary_edges, MESH.boundary_edges_cells, ...
				boundary_edges_length, MESH.boundary_edges_normals] = mesh_stars_fv_part2(MESH);
			% boundary_edges_length is only used for testing renumbering techniques

			[upstream_cell, downstream_cell, MESH.adjacent_cells, MESH.ciarlet_ratio] ...
				= mesh_stars_fv_part3(MESH);
			% upstream_cell and downstream_cell are only used for testing renumbering techniques

			MESH.coef_CFL = 1000; %%%% used only for testing renumbering techniques
			for i=1:MESH.np1
				%%%% used only for testing renumbering
				MESH.coef_CFL = min(MESH.coef_CFL, ...
					MESH.volume(i)/(perimeter(i)*(2.0+tau*MESH.gamma_ratio*MESH.ciarlet_ratio)));
			end
		end
        
		%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
		%%%%%   Modify the descriptor adjacent_cells : this function locates  %%%%%
		%%%%%   the upstream and downstream cells of each edge,               %%%%%
		%%%%%   only for triangles which share a boundary node                %%%%%
        
		if strcmp(PARAMETERS.FV.FLUX_LIMITER,'TAULIM')
			[MESH.adjacent_cells, MESH.flag_shadow_cells, MESH.corners] = ...
									modify_adjacent_cells_border(MESH, PARAMETERS);
		end

	else
		MESH.volume = mesh_stars_volume(MESH);
	end
	fprintf('done\n');
end
back to top