function MyPoissonSolver() %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % Solves the pde % % div q = f, q = - d grad u, % % with boundary conditions % % n q = k (u - g) % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % defining geometry and meshing geom = geometry; [p,e,t] = initmesh(geom, 'HMax', .1); % [p,e,t] = refinemesh(geom,p,e,t); pdemesh(p, e, t); shg pause(1) % defining data functions x1 = p(1,:); x2 = p(2,:); f = 2*sin(pi*x1).*sin(pi*x2)*pi^2; nn = size(p,2); % number of nodes/degrees of freedom d = ones(1,nn); k = 100000 * ones(1,nn); % large k to force u = g g = zeros(1,nn); % initialising matrises D = sparse(zeros(nn,nn)); K = sparse(zeros(nn,nn)); F = zeros(nn,1); G = zeros(nn,1); % assembling element contributions for el = 1 : size(t,2) elNodeInd = t(1: 3, el); elCoords = p(:,elNodeInd); % element vertex coords (2 by 3 matrix) elDiff = d(elNodeInd); % element "diffusivity" (1 by 3 matrix) dD = elDiffMatrix(elCoords, elDiff); D(elNodeInd, elNodeInd) = D(elNodeInd, elNodeInd) + dD; elLoad = f(elNodeInd); dF = elLoadVector(elCoords, elLoad); F(elNodeInd) = F(elNodeInd) + dF; end % assembling boundary element conributions for bel = 1 : size(e, 2) belNodeInd = e(1: 2, bel); belCoords = p(:, belNodeInd); % bdry elem coords (2 by 2) belPerm = k(belNodeInd); % bdry elem "permeability" dK = elBdryMatrix(belCoords, belPerm); K(belNodeInd, belNodeInd) = K(belNodeInd, belNodeInd) + dK; belLoad = g(belNodeInd); dG = elBdryVector(belCoords, belPerm, belLoad); G(belNodeInd) = G(belNodeInd) + dG; end % solving U = (D + K)\(F + G); % plotting h = pdeplot(p, e, t, 'xydata', U, 'zdata', U, 'mesh', 'on'); xlabel('x_1') ylabel('x_2') zlabel('y') grid on title('solution y = u ( x_1, x_2)') % test % u = sin(pi * x1) .* sin(pi * x2); % exact sol. if domain changed to the unit square % maxerr = max( abs(U - u') ) % subroutines function dD = elDiffMatrix(coords, diffusion) % computes the local stiffness matrix on a triangle with % vertex coordinates coords (2 by 3 matrix) and % vertex diffusivity diffusion (1 by 3 matrix) dx = area(coords); x = sum(coords, 2) / 3; % element midpoint (center of gravity) Dph = Dphi(coords); d = sum(diffusion)/length(diffusion); % midpoint diffusivity dD = Dph' * (d * Dph) * dx; function dF = elLoadVector(coords, domainLoad) dx = area(coords); x = sum(coords, 2) / 3; phi = [1/3 1/3 1/3]; % element midpoint values of the three basis functions f = sum(domainLoad)/length(domainLoad); dF = phi' * f * dx; function dK = elBdryMatrix(coords, bdryPerm) % computes the local "mass" matrix of a boundary element % (line segment) with coordinates coords (2 by 2 matrix) % and "permeability" bdryPerm (1 by 2 matrix) v = coords(:, 2) - coords(:, 1); ds = sqrt(v' * v); % the (arc) length of the bdry element x = sum(coords, 2) / 2; % element midpoint phi = [1/2 1/2]; % midpoint value of the two local basis functions k = sum(bdryPerm)/length(bdryPerm); % midpoint k value dK = phi' * (k * phi) * ds; function dG = elBdryVector(coords, bdryPerm, bdryLoad) v = coords(:, 2) - coords(:, 1); ds = sqrt(v' * v); x = sum(coords, 2) / 2; phi = [1/2 1/2]; k = sum(bdryPerm)/length(bdryPerm); g = sum(bdryLoad)/length(bdryLoad); dG = phi' * k * g * ds; function dx = area(coords) % computes the area of a triangle with vertex coordinates coords % (stored in a 2 by 3 matrix) v = coords(:, 2) - coords(:, 1); w = coords(:, 3) - coords(:, 1); dx = (v(1) * w(2) - v(2) * w(1)) / 2; function Dph = Dphi(coords) % computes the gradients of the three local basis functions on a % triangle with coordinates coords v = coords(:, 2) - coords(:, 1); w = coords(:, 3) - coords(:, 1); n2v = [-v(2) v(1)]'; % normal to v n2v = n2v / sqrt(n2v' * n2v); % normalizing pw = w' * n2v; % height of triangle Dph(:, 3) = n2v / pw; n2w = [w(2) -w(1)]'; n2w = n2w / sqrt(n2w' * n2w); pv = v' * n2w; Dph(:, 2) = n2w / pv; Dph(:, 1) = - Dph(:, 2) - Dph(:, 3); % data functions function geom = geometry() % define bdry consisting of 4 line segments % (indicated by the initial numbers 2, see $>>$ help decsg), % the first of which extends from 0 to 1 in the x direction % and from 0 to -1 in the y direction, while the second % goes from 1 to 2 in the x direction, and from -1 to 1 in y, etc, % and giving number 1 to the domain to "the left" of the lines % while the last 0's means that the domain to "the right" of % the lines is the "exterior" (not part of the computational % domain). e1 = [2 0 1 0 -1 1 0]'; e2 = [2 1 2 -1 1 1 0]'; e3 = [2 2 0 1 1 1 0]'; e4 = [2 0 0 1 0 1 0]'; geom = [e1 e2 e3 e4]; % the bdry edge data stored as % columns in a geometry matrix geom