Raw File
func_base.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[base] = func_base(FE_approx, deriv_ordermax, int_points)

	% INPUTS
	% FE_approx			Finite element method for which we want to compute the reference DOF
	% deriv_ordermax	Maximal order for the derivatives of the DOF to be computed
	% int_points		List of points where the DOF and their derivatives will be evaluated
	% 
	% OUTPUT
	% base				The list of basis functions and their derivatives evaluated at points in int_points

	% Allowed values for FE_approx : 'P1', 'P1B', 'P2'

	d = (deriv_ordermax+1)*(deriv_ordermax+2)/2;
	np = size(int_points,1);

	switch FE_approx
		case {'P1'}
			% 3 DOF on the triangle
			base = zeros(np, 3, d);

			% Evaluate the DOF
			if (deriv_ordermax >= 0)
				base(:,1,1) =  1.0 - int_points(:,1) - int_points(:,2);
				base(:,2,1) =  int_points(:,1);
				base(:,3,1) =  int_points(:,2);
			end

			% Evaluate the first order derivatives of the DOF
			if (deriv_ordermax >= 1)
				% Apply d/dx
				base(:,1,2) = -1.0;
				base(:,2,2) =  1.0;
				base(:,3,2) =  0.0;

				% Apply d/dy
				base(:,1,3) = -1.0;
				base(:,2,3) =  0.0;
				base(:,3,3) =  1.0;
			end

			% Higher order derivatives are equal to 0
			if (deriv_ordermax >= 2)
				base(:,:,4:d) = 0.;
			end

		case {'P1B'}
			% 4 DOF on the triangle
			base = zeros(np, 4, d);

			% Evaluate the DOF
			if (deriv_ordermax >= 0)
				base(:,4,1) =  27.*(1. - int_points(:,1) - int_points(:,2)).*int_points(:,1).*int_points(:,2);
				base(:,1,1) =  1. - int_points(:,1) - int_points(:,2) - base(:,4,1)/3.;
				base(:,2,1) =  int_points(:,1) - base(:,4,1)/3.;
				base(:,3,1) =  int_points(:,2) - base(:,4,1)/3.;
			end

			% Evaluate the first order derivatives of the DOF
			if (deriv_ordermax >= 1)
				% Apply d/dx
				base(:,4,2) = -54.*int_points(:,1).*int_points(:,2) + 27.*int_points(:,2) - 27.*int_points(:,2).^2;
				base(:,1,2) = -1. - base(:,4,2)/3.;
				base(:,2,2) =  1. - base(:,4,2)/3.;
				base(:,3,2) =  -base(:,4,2)/3.;

				% Apply d/dy
				base(:,4,3) = -54.*int_points(:,2).*int_points(:,1) + 27.*int_points(:,1) - 27.*int_points(:,1).^2;
				base(:,1,3) = -1. - base(:,4,3)/3.;
				base(:,2,3) =  -base(:,4,3)/3.;
				base(:,3,3) =  1. - base(:,4,3)/3.;
			end

			% Evaluate the second order derivatives of the DOF
			if (deriv_ordermax >= 2)
				% Apply d^2/dx^2
				base(:,4,4) = - 54.*int_points(:,2);
				base(:,1,4) = - base(:,4,4)/3.;
				base(:,2,4) = - base(:,4,4)/3.;
				base(:,3,4) = - base(:,4,4)/3.;
         
				% Apply d^2/dy^2
				base(:,4,5) = - 54.*int_points(:,1);
				base(:,1,5) = - base(:,4,5)/3.;
				base(:,2,5) = - base(:,4,5)/3.;
				base(:,3,5) = - base(:,4,5)/3.; 

				% Apply d^2/dxdy
				base(:,4,6) = -54.*int_points(:,1) + 27. - 54.*int_points(:,2);
				base(:,1,6) = - base(:,4,6)/3.; 
				base(:,2,6) = - base(:,4,6)/3.;
				base(:,3,6) = - base(:,4,6)/3.;
			end

			% Evaluate the second order derivatives of the DOF
			if (deriv_ordermax >= 3)
				% Apply d^3/dx^3
				base(:,4,7) = 0.;
				base(:,1,7) = -base(:,4,7)/3.;
				base(:,2,7) = -base(:,4,7)/3.;
				base(:,3,7) = -base(:,4,7)/3.;

				% Apply d^3/dy^3
				base(:,4,8) = 0.;
				base(:,1,8) = -base(:,4,8)/3.;
				base(:,2,8) = -base(:,4,8)/3.;
				base(:,3,8) = -base(:,4,8)/3.;

				% Apply d^3/dx^2dy
				base(:,4,9) = -54.;
				base(:,1,9) = -base(:,4,9);
				base(:,2,9) = -base(:,4,9);
				base(:,3,9) = -base(:,4,9);

				% Apply d^3/dxdy^2
				base(:,4,10) = -54.;
				base(:,1,10) = -base(:,4,10);
				base(:,2,10) = -base(:,4,10);
				base(:,3,10) = -base(:,4,10);
			end

			% Higher order derivatives are equal to 0
			if (deriv_ordermax >= 4)
				base(:,:,11:d) = 0.0;
			end

		case {'P2'}
			base = zeros(np, 6, d);

			% Evaluate the DOF
			if (deriv_ordermax >= 0)
				base(:,1,1) = 1. - 3.*int_points(:,1) - 3.*int_points(:,2) + 4.*int_points(:,1).*int_points(:,2) ...
								+ 2.*int_points(:,1).^2 + 2.*int_points(:,2).^2;
				base(:,2,1) = - int_points(:,1) + 2.*int_points(:,1).^2;
				base(:,3,1) = - int_points(:,2) + 2.*int_points(:,2).^2;
				base(:,4,1) = 4.*int_points(:,1).*int_points(:,2);
				base(:,5,1) = 4.*int_points(:,2) - 4.*int_points(:,1).*int_points(:,2) - 4.*int_points(:,2).^2;
				base(:,6,1) = 4.*int_points(:,1) - 4.*int_points(:,1).*int_points(:,2) - 4.*int_points(:,1).^2;
			end

			% Evaluate the first order derivatives of the DOF
			if (deriv_ordermax >= 1)
				% Apply d/dx
				base(:,1,2) = -3. + 4.*int_points(:,2) + 4.*int_points(:,1);
				base(:,2,2) = -1. + 4.*int_points(:,1);
				base(:,3,2) = 0.;
				base(:,4,2) = 4.*int_points(:,2);
				base(:,5,2) = -4.*int_points(:,2);
				base(:,6,2) = 4. - 4.*int_points(:,2) - 8.*int_points(:,1);

				% Apply d/dy
				base(:,1,3) = -3. + 4.*int_points(:,1) + 4.*int_points(:,2);
				base(:,2,3) = 0.;
				base(:,3,3) = -1. + 4.*int_points(:,2);
				base(:,4,3) = 4.*int_points(:,1);
				base(:,5,3) = 4. - 4.*int_points(:,1) - 8.*int_points(:,2);
				base(:,6,3) = -4.*int_points(:,1);
			end

			% Evaluate the second order derivatives of the DOF
			if (deriv_ordermax >= 2)
				% Apply d^2/dx^2
				base(:,1,4) = 4.;
				base(:,2,4) = 4.;
				base(:,3,4) = 0.;
				base(:,4,4) = 0.;
				base(:,5,4) = 0.;
				base(:,6,4) = -8.;

				% Apply d^2/dy^2
				base(:,1,5) = 4.;
				base(:,2,5) = 0.;
				base(:,3,5) = 4.;
				base(:,4,5) = 0.;
				base(:,5,5) = -8.;
				base(:,6,5) = 0.;

				% Apply d^2/dxdy
				base(:,1,6) = 4.;
				base(:,2,6) = 0.;
				base(:,3,6) = 0.;
				base(:,4,6) = 4.;
				base(:,5,6) = -4.;
				base(:,6,6) = -4.;
			end

			% Higher order derivatives are equal to 0
			if (deriv_ordermax >= 3)
				base(:,:,7:d) = 0.0;
			end

		otherwise
			error(sprintf('Degrees of freedom are implemented only for P1, P2, and P1B finite element methods.\n'));
	end
end
back to top