Raw File
mesh_stars_fv_part3.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[upstream_cell,downstream_cell,adjacent_cells,ciarlet_ratio] = mesh_stars_fv_part3(MESH)

	% INPUT
	% MESH					An incomplete mesh metadata
	%
	% OUTPUT
	% upstream_cell			Locates the downstream cells of each edge
	% downstream_cell		Locates the downstream cells of each edge
	% adjacent_cells		An other way to describe upstream and downstream cells of each edge
	% ciarlet_ratio			Ciarlet_ratio number as defined in Calgaro-Chane-Kane-Creuse-Goudon JCP2010

	%% Compute the number of triangles which share a fixed node

	% This function locates the upstream and downstream cells of each edge
	% An other way to describe upstream and downstream cells of each edge
	% Compute the ciarlet_ratio number

	triangles_node = zeros(1,MESH.np1);
	for ke = 1:MESH.nt1
		for j=1:3
			js = MESH.t1(j,ke);
			triangles_node(js) = triangles_node(js)+1;
		end
	end
	max_triangles_node = max(triangles_node);

	%% Take note of the number of triangles which share a fixed node

	num_triangles_node = zeros(max_triangles_node,MESH.np1);
	for ke = 1:MESH.nt1
		for j=1:3
			js = MESH.t1(j,ke);
			ind = 1;
			while (num_triangles_node(ind,js) > 0)
				ind = ind+1;
			end
			num_triangles_node(ind,js) = ke;
		end
	end

	%% Compute the upstream_cell and downstream_cell of each edge

	upstream_cell = zeros(1,MESH.ne1full);
	downstream_cell = zeros(1,MESH.ne1full);

	for ie=1:MESH.ne1full
		node1 = MESH.e1full(1,ie);
		node2 = MESH.e1full(2,ie);

		% (xe,ye) is the normal vector of the edge
		xe = MESH.p1(1,node2)-MESH.p1(1,node1);
	    ye = MESH.p1(2,node2)-MESH.p1(2,node1);
		nor = sqrt(xe^2+ye^2);
		xe = xe/nor;
		ye = ye/nor;

		pdscalmin = 2;
		ind_triangle = 0;
		for it=1:triangles_node(node1)
			nloc = 1;
			nb_triangle = num_triangles_node(it,node1);
			while (MESH.t1(nloc,nb_triangle) ~=node1)
				nloc = nloc+1;
			end
			node_face1 = MESH.t2(nloc+3,nb_triangle);
			xv = MESH.p2(1,node_face1)-MESH.p1(1,node1); % the renumbering is not the same for p1 and p2
			yv = MESH.p2(2,node_face1)-MESH.p1(2,node1);
			nor = sqrt(xv^2+yv^2);
			xv = xv/nor;
			yv = yv/nor;
			pdscal = xe*xv+ye*yv;
			if (pdscal < pdscalmin)
				pdscalmin = pdscal;
				ind_triangle = nb_triangle;
			end
		end
		upstream_cell(1,ie) = ind_triangle;

		pdscalmax = -2;
		ind_triangle = 0;
		for it=1:triangles_node(node2)
			nloc = 1;
			nb_triangle = num_triangles_node(it,node2);
			while (MESH.t1(nloc,nb_triangle) ~=node2)
				nloc = nloc+1;
			end
			node_face2 = MESH.t2(nloc+3,nb_triangle);
			xv = MESH.p2(1,node_face2)-MESH.p1(1,node2); % the renumbering is not the same for p1 and p2
			yv = MESH.p2(2,node_face2)-MESH.p1(2,node2);
			nor = sqrt(xv^2+yv^2);
			xv = xv/nor;
			yv = yv/nor;
			pdscal = xe*xv+ye*yv;
			if (pdscal > pdscalmax)
				pdscalmax = pdscal;
				ind_triangle = nb_triangle;
			end
		end
		downstream_cell(1,ie) = ind_triangle;
	end

	%% A second way in order to compute the upstream and downstream cells for each edge of each triangle

	adjacent_cells = zeros(MESH.nt1,3,2);
	for ke=1:MESH.nt1
		for j=1:3
			xgj = (sum(MESH.p2(1,MESH.t2(1:3,ke)))/3 + MESH.p2(1,MESH.t2(j+3,ke)))/2;
			ygj = (sum(MESH.p2(2,MESH.t2(1:3,ke)))/3 + MESH.p2(2,MESH.t2(j+3,ke)))/2;

			jp1 = mod(j  ,3)+1;
			jm1 = mod(jp1,3)+1;
			neup = MESH.t1(jp1,ke);
			neum = MESH.t1(jm1,ke);

			ddx = xgj-MESH.p1(1,neup);
			ddy = ygj-MESH.p1(2,neup);
			nor = sqrt(ddx^2+ddy^2);
			ddx = ddx/nor;
			ddy = ddy/nor;

			pdscalmin = 2;
			ind_triangle = 0;
			for it=1:triangles_node(neup)
				nloc = 1;
				nb_triangle = num_triangles_node(it,neup);
				while (MESH.t1(nloc,nb_triangle) ~= neup)
					nloc = nloc+1;
				end
				node_face1 = MESH.t2(nloc+3,nb_triangle);
				xv = MESH.p2(1,node_face1)-MESH.p1(1,neup); % the renumbering is not the same for p1 and p2
				yv = MESH.p2(2,node_face1)-MESH.p1(2,neup);
				nor = sqrt(xv^2+yv^2);
				xv = xv/nor;
				yv = yv/nor;
				pdscal = ddx*xv+ddy*yv;
				if (pdscal < pdscalmin)
					pdscalmin = pdscal;
					ind_triangle = nb_triangle;
				end
			end
			adjacent_cells(ke,j,1) = ind_triangle;

			ddx = xgj-MESH.p1(1,neum);
			ddy = ygj-MESH.p1(2,neum);
			nor = sqrt(ddx^2+ddy^2);
			ddx = ddx/nor;
			ddy = ddy/nor;

			pdscalmin = 2;
			ind_triangle = 0;
			for it=1:triangles_node(neum)
				nloc = 1;
				nb_triangle = num_triangles_node(it,neum);
				while (MESH.t1(nloc,nb_triangle) ~= neum)
					nloc = nloc+1;
				end
				node_face2 = MESH.t2(nloc+3,nb_triangle);
				xv = MESH.p2(1,node_face2)-MESH.p1(1,neum); % the renumbering is not the same for p1 and p2
				yv = MESH.p2(2,node_face2)-MESH.p1(2,neum);
				nor = sqrt(xv^2+yv^2);
				xv = xv/nor;
				yv = yv/nor;
				pdscal = ddx*xv+ddy*yv;
				if (pdscal < pdscalmin)
					pdscalmin = pdscal;
					ind_triangle = nb_triangle;
				end
			end
			adjacent_cells(ke,j,2) = ind_triangle;
		end
	end

	%% Compute the ciarlet_ratio number
	% ciarlet_ratio = max_{j \in triangles} max_{k \in triangles sharing a node with j} r_j/h_k
	% r_j being the radius of the circombscribed circle in triangle j
	% h_k being the smallest height of the triangle k

	radius = zeros(1,MESH.nt1);
	min_height = zeros(1,MESH.nt1);

	for ke=1:MESH.nt1
	    De = [MESH.p1(2,MESH.t1(3,ke))-MESH.p1(2,MESH.t1(1,ke)), ...
						MESH.p1(2,MESH.t1(1,ke))-MESH.p1(2,MESH.t1(2,ke)); ...
				MESH.p1(1,MESH.t1(1,ke))-MESH.p1(1,MESH.t1(3,ke)), ...
						MESH.p1(1,MESH.t1(2,ke))-MESH.p1(1,MESH.t1(1,ke))];
		Je = abs(det(De));

		radius(ke) = 1.0/(2*Je);
		min_height(ke) = 1.e+10;

		for j=1:3
			ia = abs(MESH.t1e(j,ke));
			radius(ke)  = radius(ke)*MESH.edges_length(ia);
			min_height(ke) = min(min_height(ke), Je/MESH.edges_length(ia));
		end
	end

	ciarlet_ratio=0.0;
	ratio_rj_hk=0.0;

	for ke=1:MESH.nt1
		for j=1:3
			js = MESH.t1(j,ke);
			for it=1:triangles_node(js)
				nb_triangle = num_triangles_node(it,js);
				ratio_rj_hk = max(ratio_rj_hk, radius(ke) / min_height(nb_triangle));
			end
		end
		ciarlet_ratio = max(ciarlet_ratio,ratio_rj_hk);  
	end

end
back to top