├── LICENSE ├── README.md ├── error └── computeL2error.m ├── examples └── ex1D.m ├── mesh ├── computeE4n.m ├── generateMesh.m └── generateRectMesh.m ├── mpmtools ├── I2p.m ├── I2pIce.m ├── computeE4p.m ├── generateMp.m ├── ispine.m ├── p2I.m ├── updateE4p.m └── updatePts.m ├── plot ├── plotMesh.m ├── plotSol.m └── plotSolExact.m ├── run ├── convRate.m ├── run2DMPM.m ├── runConvect.m ├── runIceConvectRotation.m └── runIceConvergentFlow.m └── solve ├── normalBC.m ├── shape.m ├── shapeR.m ├── shapeR0.m ├── shapeR2n0.m ├── shapeRN0.m ├── shapeRg.m └── shapeRg0.m /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2016, Donsub Rim, University of Washington 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Material Point Method 2 | -------------------------------------------------------------------------------- /error/computeL2error.m: -------------------------------------------------------------------------------- 1 | function [val,totalbd] = computeL2error(uI,uexact,c4n,n4e,T) 2 | val = 0; totalbd = 0; 3 | nrElems = size(n4e,1); 4 | for elem = 1:nrElems 5 | a = c4n(n4e(elem,1),1); 6 | b = c4n(n4e(elem,2),1); 7 | c = c4n(n4e(elem,2),2); 8 | d = c4n(n4e(elem,3),2); 9 | c4nL = c4n(n4e(elem,:),:); 10 | uIL= uI(n4e(elem,:),:); 11 | [intgrl,upbd] = quad2d(@(x,y) squareerror(x,y,uIL,c4nL,uexact,T),a,b,c,d,'RelTol',1e-12); 12 | val = val + intgrl; 13 | totalbd = totalbd + upbd; 14 | 15 | end 16 | val = sqrt(val); 17 | end 18 | 19 | function val = squareerror(x,y,uIL,c4nL,uexact,T) 20 | for j = 1:size(x,1) 21 | for k = 1:size(x,2) 22 | val(j,k) = sum(abs(shapeR([x(j,k),y(j,k)],c4nL)'*uIL - uexact([x(j,k),y(j,k)],T)).^2); 23 | end 24 | end 25 | 26 | end 27 | -------------------------------------------------------------------------------- /examples/ex1D.m: -------------------------------------------------------------------------------- 1 | function ex1D 2 | 3 | E = 1; 4 | L = 1; 5 | A = 0.01; 6 | v0 = @(x) A*sin(pi*x); 7 | u0 = @(x) 0*x; 8 | rho0 = @(x) 0*x+1; 9 | b0 = @(x) 0*x; 10 | sigma0 = @(x) 0*x ; 11 | ppe = 2; 12 | nrElems = 8; 13 | nrNodes = nrElems+1; 14 | nrSteps = 20; 15 | T = 10; 16 | dt = T/nrSteps; 17 | c4n = linspace(0,L,nrNodes)'; 18 | h = L/(nrNodes-1); 19 | n4e = [1:nrElems; 2:(nrElems+1)]'; 20 | e4n = sparse(n4e(:,1),n4e(:,2),1:nrElems); 21 | bdNodes = [1 nrNodes]; 22 | inNodes = setdiff(1:nrNodes,bdNodes); 23 | nrPts = nrElems*ppe; 24 | 25 | %% Initialization 26 | xp = zeros(nrPts,nrSteps); 27 | e4xp = zeros(nrPts,nrSteps); 28 | volp = zeros(nrPts,nrSteps); 29 | rhop = zeros(nrPts,nrSteps); 30 | xp = zeros(nrPts,nrSteps); 31 | vp = zeros(nrPts,nrSteps); 32 | bp = zeros(nrPts,nrSteps); 33 | sigmap = zeros(nrPts,nrSteps); 34 | Fp = zeros(nrPts,nrSteps); 35 | Jp = zeros(nrPts,nrSteps); 36 | FI = zeros(nrNodes,nrSteps); 37 | vI = zeros(nrNodes,nrSteps); 38 | uI = zeros(nrNodes,nrSteps); 39 | xpt = zeros(ppe,nrElems); volpt = zeros(ppe,nrElems); 40 | icon = diag(ones(nrElems-1,1),-1) + diag(ones(nrElems-1,1),1); 41 | for elem = 1:nrElems 42 | a = c4n(n4e(elem,1)); b = c4n(n4e(elem,2)); 43 | pts = linspace(a,b,ppe+2); 44 | xpt(:,elem) = pts(2:(end-1))'; 45 | xp4et(elem,:) = elem; 46 | volpt(:,elem) = abs(a-b)/2; 47 | end 48 | xp(:,1) = xpt(:); 49 | xp0 = xp(:,1); 50 | xp4e(:,1) = xp4et(:); 51 | volp(:,1) = volpt(:); 52 | bp(:,1) = b0(xp(:,1)); 53 | vp(:,1) = v0(xp(:,1)); 54 | up(:,1) = u0(xp(:,1)); 55 | rhop(:,1) = rho0(xp(:,1)); 56 | rhop0 = rhop(:,1); 57 | sigmap(:,1) = sigma0(xp(:,1)); 58 | mp(:,1) = volp(:,1).*rhop(:,1); 59 | Fp(:,1) = ones(nrPts,1); 60 | Jp(:,1) = abs(Fp(:,1)); 61 | e4xp0 = gete4xp(xp0,c4n,e4n); 62 | 63 | %% MPM Algorithm 64 | 65 | 66 | for n = 1:(nrSteps-1) 67 | % Map to grid 68 | e4xp = gete4xp(xp(:,n),c4n,e4n); 69 | [mI,vI(:,n),fiI,fxI,fI,FI(:,n+1)] = p2I(xp(:,n),e4xp,c4n,n4e,mp(:,1),volp(:,n), ... 70 | vp(:,n),bp(:,n),sigmap(:,n),Fp(:,n),... 71 | nrPts,nrNodes,inNodes,h); 72 | % Solve / Timestep 73 | vI(1,n) = 0; 74 | vI(end,n) = 0; 75 | vI(inNodes,n+1) = vI(inNodes,n) + dt*fI(inNodes)./mI(inNodes); 76 | uI(inNodes,n+1) = uI(inNodes,n) + dt*vI(inNodes,n+1); 77 | 78 | % Update material points 79 | [xp(:,n+1),vp(:,n+1),Fp(:,n+1),Jp(:,n+1),... 80 | rhop(:,n+1),volp(:,n+1),sigmap(:,n+1)] = updatePts(... 81 | xp0,xp,vp(:,n),mp,mI,volp(:,n),e4xp,e4xp0,c4n,n4e,rhop0,vI(:,[n n+1]),Fp(:,n),... 82 | FI(:,n+1),nrPts,nrNodes,h,dt); 83 | xx = xp(:,n+1); 84 | % plot(xx,vp(:,n+1),xx,rhop(:,n+1),c4n,vI(:,n+1),c4n,FI(:,n+1)) 85 | figure(1); plot(c4n,uI(:,n+1)); axis([0 1 0 1]) 86 | end 87 | 88 | 89 | 90 | 91 | 92 | end 93 | 94 | function [mI,vI,fiI,fxI,fI,FI] = p2I(xp,e4xp,c4n,n4e,mp,volp,vp,... 95 | bp,sigmap,Fp,nrPts,nrNodes,inNodes,h) 96 | mI = zeros(nrNodes,1); 97 | vI = zeros(nrNodes,1); 98 | fiI = zeros(nrNodes,1); 99 | fxI = zeros(nrNodes,1); 100 | FI = zeros(nrNodes,1); 101 | for p = 1:nrPts 102 | Ns = n4e(e4xp(p),:); 103 | Nxp = shape(xp(p),Ns,c4n,h); 104 | dNxpdx = shapeg(xp(p),Ns,c4n,h); 105 | NxpAll(:,:,p) = Nxp; 106 | onecol = ones(length(Ns),1); 107 | mIloc = mp(p).*shapef(xp(p),Ns,c4n,h); 108 | mI = mI + sparse(Ns, onecol, mIloc,nrNodes,1); 109 | vIloc = vp(p).*mp(p).*Nxp; 110 | vI = vI + sparse(Ns,onecol, vIloc,nrNodes,1); 111 | fiIloc = sigmap(p).*volp(p).*dNxpdx; 112 | fiI = fiI - sparse(Ns,onecol,fiIloc,nrNodes,1); 113 | fxIloc = mp(p).*bp(p).*shapef(xp(p),Ns,c4n,h); 114 | fxI = fxI + sparse(Ns,onecol,fxIloc,nrNodes,1); 115 | % FIloc = volp(p).*Fp(p).*shapef(xp(p),Ns,c4n,h); 116 | % FI = FI + sparse(Ns,onecol,FIloc,nrNodes,1); 117 | end 118 | vI = vI./mI; 119 | % FI = FI./mI; 120 | fI = fiI + fxI; 121 | end 122 | 123 | function [xpn,vpn,Fpn,Jpn,rhopn,volpn,sigmapn] = updatePts(xp0,xp,vp,mp,mI,volp,e4xp,e4xp0,c4n,n4e,... 124 | rhop0,vI,Fp,FI,nrPts,nrNodes,h,dt) 125 | 126 | % needs work 127 | E = 1; 128 | Fpfactor = zeros(nrPts,1); 129 | xpn = zeros(nrPts,1); 130 | vpn = zeros(nrPts,1); 131 | sigmafactor = zeros(nrPts,1); 132 | for p = 1:nrPts 133 | Ns = n4e(e4xp(p),:); 134 | NIxp = shape(xp(p),Ns,c4n,h); 135 | dNIxp = shapeg(xp(p),Ns,c4n,h); 136 | Fpfactor(p) = 1 + dt*sum(vI(Ns,2).*shapegf(xp(p),Ns,c4n,h)); 137 | xpn(p) = xp(p) + dt*sum(vI(Ns,2).*NIxp); 138 | vpn(p) = vp(p) + sum((vI(Ns,2)-vI(Ns,1)).*NIxp); 139 | FIloc = volp(p).*Fp(p).*shapef(xp(p),Ns,c4n,h); 140 | FI = FI + sparse(Ns,ones(length(Ns),1),FIloc,nrNodes,1); 141 | end 142 | 143 | for p = 1:nrPts 144 | Ns0 = n4e(e4xp0(p),:); 145 | sigmafactor(p) = sum(FI(Ns0).*shapef(xp0(p),Ns0,c4n,h)); 146 | end 147 | Fpn = Fpfactor.*Fp; 148 | Jpn = abs(Fpn); 149 | rhopn = rhop0./Jpn; 150 | volpn = mp./Jpn; 151 | sigmapn = E.*sigmafactor; 152 | 153 | end 154 | 155 | function y = shape(xp, Ns, c4n, h) 156 | y = 1- abs(xp - c4n(Ns))/h; 157 | if sum(Ns == 1) 158 | y(Ns ==1 ) = 0; 159 | elseif sum(Ns == length(c4n)) 160 | y(Ns == length(c4n)) = 0; 161 | end 162 | end 163 | 164 | function y = shapef(xp, Ns, c4n, h) 165 | y = 1- abs(xp - c4n(Ns))/h; 166 | 167 | end 168 | 169 | function y = shapeg(xp, Ns, c4n, h) 170 | y = -sign(xp - c4n(Ns))/h; 171 | if sum(Ns == 1) 172 | y(Ns ==1 ) = 0; 173 | elseif sum(Ns == length(c4n)) 174 | y(Ns == length(c4n)) = 0; 175 | end 176 | end 177 | 178 | function y = shapegf(xp, Ns, c4n, h) 179 | y = -sign(xp - c4n(Ns))/h; 180 | 181 | end 182 | 183 | function val = gete4xp(xp,c4n,e4n) 184 | nrNodes = length(c4n); 185 | nrPts = length(xp); 186 | nodes1 = sum(xp*ones(1,nrNodes) - ones(nrPts,1)*c4n'>0,2); 187 | val = diag(e4n(nodes1,nodes1+1)); 188 | end 189 | -------------------------------------------------------------------------------- /mesh/computeE4n.m: -------------------------------------------------------------------------------- 1 | function e4n = computeE4n(n4e) 2 | nrElems = size(n4e,1); 3 | j = repmat(1:nrElems,1,4); 4 | e4n = logical(sparse(n4e(:),j,ones(1,4*nrElems))); 5 | end -------------------------------------------------------------------------------- /mesh/generateMesh.m: -------------------------------------------------------------------------------- 1 | function [c4n,n4e] = generateMesh(xlim,ylim,nx,ny) 2 | 3 | xx = linspace(xlim(1),xlim(2),nx+1); 4 | yy = linspace(ylim(1),ylim(2),ny+1); 5 | [X,Y] = meshgrid(xx,yy); 6 | nxy = reshape(1:((nx+1)*(ny+1)),nx+1,ny+1)'; 7 | c4n = [X(:),Y(:)]; 8 | nNodes = size(c4n,1); 9 | nxy1 = nxy(1:(end-1),1:(end-1)); 10 | nxy2 = nxy(2:end,1:(end-1)); 11 | nxy3 = nxy(2:end,2:end); 12 | nxy4 = nxy(1:(end-1),2:end); 13 | n4e = [nxy1(:),nxy2(:),nxy3(:),nxy4(:)]; 14 | 15 | end -------------------------------------------------------------------------------- /mesh/generateRectMesh.m: -------------------------------------------------------------------------------- 1 | function [c4n,n4e,inNodes,bdNodes,bdNorms,bdTans,inComps,vol4e] ... 2 | = generateRectMesh(xlim,ylim,nx,ny) 3 | % generate rectangular mesh and corresponding data structures. 4 | xx = linspace(xlim(1),xlim(2),nx+1); 5 | yy = linspace(ylim(1),ylim(2),ny+1); 6 | [X,Y] = meshgrid(xx,yy); 7 | X = X'; Y = Y'; 8 | nxy = reshape(1:((nx+1)*(ny+1)),nx+1,ny+1)'; 9 | c4n = [X(:),Y(:)]; 10 | nrNodes = size(c4n,1); 11 | nxy1 = nxy(1:(end-1),1:(end-1)); 12 | nxy2 = nxy(1:(end-1),2:end); 13 | nxy3 = nxy(2:end,2:end); 14 | nxy4 = nxy(2:end,1:(end-1)); 15 | n4e = [nxy1(:),nxy2(:),nxy3(:),nxy4(:)]; 16 | bdNodes = [nxy(1,:)'; nxy(:,end); nxy(end,:)'; nxy(:,1)]; 17 | inNodes = 1:nrNodes; inNodes(bdNodes) = []; 18 | vol4e = ones(size(n4e,1),1).*((xlim(2)-xlim(1))/nx)*((ylim(2)-ylim(1))/ny); 19 | lx = ones(nx+1,1); 20 | ly = ones(ny+1,1); 21 | bdNorms = [bdNodes, [-2*lx; 1*ly; 2*lx; -1*ly]]; 22 | bdTans = [bdNodes, [1*lx; 2*ly; -1*lx; -2*ly]]; 23 | inComps = normalBC(logical(ones(nrNodes,2)),bdNorms); 24 | end 25 | -------------------------------------------------------------------------------- /mpmtools/I2p.m: -------------------------------------------------------------------------------- 1 | function [x4pn,e4pn,v4pn,F4pn,J4p,rho4pn,vol4pn,sigma4pn] = I2p(... 2 | x4p,v4p,m4p,e4p,c4n,n4e,e4n,rhop0,... 3 | vI,vIold,F4p,nrPts,nrNodes,dt,lambda,mu) 4 | % update material pts/grid values 5 | F4pn = zeros(2,2,nrPts); 6 | J4p = zeros(nrPts,1); 7 | x4pn = zeros(nrPts,2); 8 | v4pn = zeros(nrPts,2); 9 | sigma4pn = zeros(2,2,nrPts); 10 | parfor p = 1:nrPts 11 | % fix p then find nonzero NIxp 12 | nodes = n4e(e4p(p,:),:); 13 | NIxp = shapeR(x4p(p,:),c4n(nodes,:)); 14 | dNIxp = shapeRg(x4p(p,:),c4n(nodes,:)); 15 | F4pn(:,:,p) = (eye(2,2) + dt*vI(nodes,:)'*dNIxp)*F4p(:,:,p); 16 | x4pn(p,:) = x4p(p,:) + dt*NIxp'*vI(nodes,:); 17 | v4pn(p,:) = v4p(p,:) + NIxp'*(vI(nodes,:)-vIold(nodes,:)); 18 | J4p(p) = det(F4pn(:,:,p)); 19 | sigma4pn(:,:,p) = (lambda*log(J4p(p))*eye(2) ... 20 | + mu*(F4pn(:,:,p)*F4pn(:,:,p)' - eye(2)))./J4p(p); 21 | end 22 | rho4pn = rhop0./J4p; 23 | vol4pn = m4p./rho4pn; 24 | e4pn = updateE4p(c4n,n4e,e4n,x4p,e4p); 25 | end 26 | -------------------------------------------------------------------------------- /mpmtools/I2pIce.m: -------------------------------------------------------------------------------- 1 | function [x4pn,e4pn,v4pn,F4pn,J4p,rho4pn,vol4pn,... 2 | sigma4pn,h4pn,hbar4pn,A4pn] = I2p(... 3 | x4p,v4p,m4p,e4p,c4n,n4e,e4n,rhop0,... 4 | vI,vIold,F4p,nrPts,nrNodes,dt,lambda,mu,... 5 | h4p,hbar4p,A4p) 6 | % update material pts/grid values 7 | F4pn = zeros(2,2,nrPts); 8 | J4p = zeros(nrPts,1); 9 | x4pn = zeros(nrPts,2); 10 | v4pn = zeros(nrPts,2); 11 | sigma4pn = zeros(2,2,nrPts); 12 | SA4p = 0; 13 | Sh4p = 0; 14 | parfor p = 1:nrPts 15 | % fix p then find nonzero NIxp 16 | nodes = n4e(e4p(p,:),:); 17 | NIxp = shapeR(x4p(p,:),c4n(nodes,:)); 18 | dNIxp = shapeRg(x4p(p,:),c4n(nodes,:)); 19 | F4pn(:,:,p) = (eye(2,2) + dt*vI(nodes,:)'*dNIxp)*F4p(:,:,p); 20 | x4pn(p,:) = x4p(p,:) + dt*NIxp'*vI(nodes,:); 21 | v4pn(p,:) = v4p(p,:) + NIxp'*(vI(nodes,:)-vIold(nodes,:)); 22 | J4p(p) = det(F4pn(:,:,p)); 23 | sigma4pn(:,:,p) = (lambda*log(J4p(p))*eye(2) ... 24 | + mu*(F4pn(:,:,p)*F4pn(:,:,p)' - eye(2)))./J4p(p); 25 | A4pn(p,:) = -sum(NIxp'*vI(nodes,:),2).*A4p(p,:) + SA4p; 26 | hbar4pn(p,:) = -sum(NIxp'*vI(nodes,:),2).*hbar4p(p,:) + Sh4p; 27 | end 28 | h4pn = hbar4p./A4p; 29 | rho4pn = rhop0./J4p; 30 | vol4pn = m4p./rho4pn; 31 | e4pn = updateE4p(c4n,n4e,e4n,x4p,e4p); 32 | end 33 | -------------------------------------------------------------------------------- /mpmtools/computeE4p.m: -------------------------------------------------------------------------------- 1 | function ne4p = computeE4p(c4n,n4e,e4n,xp,e4p) 2 | 3 | nrElems = size(n4e,1); 4 | i4elem = 1:nrElems; 5 | nrPts = size(xp,1); 6 | for j = 1:nrPts 7 | if ispine(xp(j,:),c4n(n4e(e4p(j,:),:),:)) 8 | ne4p(j,e4p(j,:)) = true; 9 | else 10 | c4e = []; 11 | e2search = i4elem(sum(e4n(n4e(e4p(j,:),:),:),1) > 0); 12 | for k = 1:length(e2search) 13 | c4e(:,:,k) = c4n(n4e(e2search(k),:),:); 14 | end 15 | elem = e2search(ispine(xp(j,:),c4e)); 16 | ne4p(j,elem) = true; 17 | if isempty(elem) 18 | display('empty row in e4p') 19 | end 20 | end 21 | end 22 | 23 | 24 | end -------------------------------------------------------------------------------- /mpmtools/generateMp.m: -------------------------------------------------------------------------------- 1 | function [x4p,e4p] = generateMp(c4n,n4e,isbody,nmpe) 2 | mmpe = ceil(sqrt(nmpe)); 3 | e4p = logical([]); 4 | x4p = []; 5 | nrElems = size(n4e,1); 6 | for elem = 1:nrElems 7 | mp4e = []; 8 | xlim4e = c4n(n4e(elem,[1,2]),1); 9 | ylim4e = c4n(n4e(elem,[2,3]),2); 10 | xx = linspace(xlim4e(1),xlim4e(2),mmpe+2); 11 | yy = linspace(ylim4e(1),ylim4e(2),mmpe+2); 12 | [X,Y] = meshgrid(xx(2:(end-1)),yy(2:(end-1))); 13 | [mp4e(:,1),mp4e(:,2)] = isbody(X(:),Y(:)); 14 | x4p = [x4p; mp4e]; 15 | k = size(x4p,1); 16 | npts = size(mp4e,1); 17 | e4p((k-npts+1):k,elem) = ones(npts,1); 18 | end 19 | 20 | end -------------------------------------------------------------------------------- /mpmtools/ispine.m: -------------------------------------------------------------------------------- 1 | function val = ispine(p,c4e) 2 | % check if p belongs to an element of given coordinates. 3 | e2chk = size(c4e,3); 4 | val = logical(zeros(e2chk,1)); 5 | for j = 1:e2chk 6 | vecs = c4e(:,:,j) - repmat(p,4,1); 7 | nvecs = vecs./repmat(sqrt(sum(vecs.^2,2)),1,2); 8 | angles = nvecs*nvecs'; 9 | if sum(abs(acos([diag(angles,1); angles(4,1)])),1) >= (2*pi - 1e-8) 10 | val(j) = true; 11 | break 12 | end 13 | end 14 | end -------------------------------------------------------------------------------- /mpmtools/p2I.m: -------------------------------------------------------------------------------- 1 | function [mI,mvI,fI] = p2I(x4p,e4p,c4n,n4e,m4p,vol4p,vp,... 2 | b4p,sigma4p,nrPts,nrNodes,bdNormals) 3 | % map values on material points to the grid 4 | mI = zeros(nrNodes,1); 5 | mvI = zeros(nrNodes,2); 6 | fI = zeros(nrNodes,2); 7 | parfor p = 1:nrPts 8 | % Fix p then find I to contribute to 9 | nodes = n4e(e4p(p,:),:)'; 10 | Nxp = shapeR(x4p(p,:),c4n(nodes,:)); 11 | dNxpdx = shapeRg(x4p(p,:),c4n(nodes,:)); 12 | col = ones(length(nodes),1); 13 | cols = [col; 2*col]; 14 | mI = mI + sparse(nodes, col, m4p(p)*Nxp,nrNodes,1); 15 | mvI = mvI + sparse([nodes;nodes],cols, m4p(p).*Nxp*vp(p,:),nrNodes,2); 16 | fI = fI + sparse([nodes;nodes],cols,-vol4p(p)*dNxpdx*sigma4p(:,:,p)'... 17 | +m4p(p).*Nxp*b4p(p,:),nrNodes,2); 18 | end 19 | mvI(mI < 1e-14) = 0; 20 | mvI = normalBC(mvI,bdNormals); 21 | end 22 | -------------------------------------------------------------------------------- /mpmtools/updateE4p.m: -------------------------------------------------------------------------------- 1 | function ne4p = updateE4p(c4n,n4e,e4n,x4p,e4p) 2 | % update which element each material pt belongs to. 3 | nrElems = size(n4e,1); 4 | i4elem = 1:nrElems; 5 | nrPts = size(x4p,1); 6 | for j = 1:nrPts 7 | if ispine(x4p(j,:),c4n(n4e(e4p(j,:),:),:)) 8 | ne4p(j,e4p(j,:)) = true; 9 | else 10 | c4e = []; 11 | e2search = i4elem(sum(e4n(n4e(e4p(j,:),:),:),1) > 0); 12 | for k = 1:length(e2search) 13 | c4e(:,:,k) = c4n(n4e(e2search(k),:),:); 14 | end 15 | elem = e2search(ispine(x4p(j,:),c4e)); 16 | ne4p(j,elem) = true; 17 | if isempty(elem) 18 | display('empty row in e4p') 19 | end 20 | end 21 | end 22 | end -------------------------------------------------------------------------------- /mpmtools/updatePts.m: -------------------------------------------------------------------------------- 1 | function [x4pn,e4pn,v4pn,F4pn,J4p,rho4pn,vol4pn,sigma4pn] = I2p(... 2 | x4p,v4p,m4p,mI,volp,e4p,c4n,n4e,e4n,... 3 | rhop0,vI,vIold,F4p,nrPts,nrNodes,dt,lambda,mu) 4 | % update material pts/grid values 5 | F4pn = zeros(2,2,nrPts); 6 | J4p = zeros(nrPts,1); 7 | x4pn = zeros(nrPts,2); 8 | v4pn = zeros(nrPts,2); 9 | sigma4pn = zeros(2,2,nrPts); 10 | parfor p = 1:nrPts 11 | % fix p then find nonzero NIxp 12 | nodes = n4e(e4p(p,:),:); 13 | NIxp = shapeR(x4p(p,:),c4n(nodes,:)); 14 | dNIxp = shapeRg(x4p(p,:),c4n(nodes,:)); 15 | F4pn(:,:,p) = (eye(2,2) + dt*vI(nodes,:)'*dNIxp)*F4p(:,:,p); 16 | x4pn(p,:) = x4p(p,:) + dt*NIxp'*vI(nodes,:); 17 | v4pn(p,:) = v4p(p,:) + NIxp'*(vI(nodes,:)-vIold(nodes,:)); 18 | J4p(p) = det(F4pn(:,:,p)); 19 | sigma4pn(:,:,p) = (lambda*log(J4p(p))*eye(2) ... 20 | + mu*(F4pn(:,:,p)*F4pn(:,:,p)' - eye(2)))./J4p(p); 21 | end 22 | rho4pn = rhop0./J4p; 23 | vol4pn = m4p./rho4pn; 24 | e4pn = updateE4p(c4n,n4e,e4n,x4p,e4p); 25 | end 26 | -------------------------------------------------------------------------------- /plot/plotMesh.m: -------------------------------------------------------------------------------- 1 | function plotMesh(c4n,n4e,x4p,t) 2 | 3 | nrElems = size(n4e,1); 4 | figure(1);clf; 5 | for elem = 1:nrElems 6 | plot(c4n(n4e(elem,[1:4 1]),1),c4n(n4e(elem,[1:4,1]),2)); 7 | hold on; 8 | end 9 | plot(x4p(:,1),x4p(:,2),'r.') 10 | axis equal 11 | margin = 0.01; 12 | axis([min(c4n(:,1))-margin,max(c4n(:,1))+margin,... 13 | min(c4n(:,2))-margin,max(c4n(:,2))+margin]) 14 | title({'Mesh';['t=' num2str(t)]}) 15 | 16 | end -------------------------------------------------------------------------------- /plot/plotSol.m: -------------------------------------------------------------------------------- 1 | function plotSol(c4n,n4e,x4p,t,v4p,wI) 2 | % 3 | nrElems = size(n4e,1); 4 | nrPts = size(x4p,1); 5 | f = figure('visible','off'); 6 | clf; 7 | h = max(norm(c4n(3,:) - c4n(1,:),2)); 8 | scale = 60*h; 9 | for elem = 1:nrElems 10 | plot(c4n(n4e(elem,[1:4 1]),1),c4n(n4e(elem,[1:4,1]),2)); 11 | hold on; 12 | end 13 | axis equal 14 | margin = .01; 15 | axis([min(c4n(:,1))-margin,max(c4n(:,1))+margin,min(c4n(:,2))-margin,max(c4n(:,2))+margin]) 16 | title({'MPM Solution u(X,t)'; ['t=' num2str(t,'%10.3f') ',' num2str(nrElems) ' elts,' num2str(nrPts) ' mtrl pts']}) 17 | 18 | quiver(c4n(:,1),c4n(:,2),wI(:,1),wI(:,2),h,'r'); 19 | hold off; 20 | legend('mesh','u_I','Location','NorthEastOutside'); 21 | drawnow 22 | % matlab2tikz(['../output/mpm-sol-' num2str(nrElems) '-' num2str(nrPts/nrElems) ... 23 | % '-' num2str(t,'%1.4f') '.tikz']) 24 | 25 | f = figure('visible','off'); 26 | clf; 27 | for elem = 1:nrElems 28 | plot(c4n(n4e(elem,[1:4 1]),1),c4n(n4e(elem,[1:4,1]),2)); 29 | hold on; 30 | end 31 | plot(x4p(:,1),x4p(:,2),'r.'); 32 | 33 | axis equal 34 | margin = .01; 35 | axis([min(c4n(:,1))-margin,max(c4n(:,1))+margin,... 36 | min(c4n(:,2))-margin,max(c4n(:,2))+margin]) 37 | title({'MPM Solution';['t=' num2str(t,'%10.3f')]}) 38 | quiver(x4p(:,1),x4p(:,2),v4p(:,1),v4p(:,2),'r'); 39 | 40 | title({'MPM Solution v(x_p,t)';['t=' num2str(t,'%10.3f') ',' num2str(nrElems) ' elts,'... 41 | num2str(nrPts) ' mtrl pts']}) 42 | legend('mesh','mtrl pts','v_I','Location','NorthEastOutside'); 43 | drawnow 44 | %matlab2tikz(['../output/mpm-dsoldt-' num2str(nrElems) '-' num2str(nrPts/nrElems) ... 45 | %'-' '-' num2str(t,'%1.4f') '.tikz']) 46 | saveas(f,['../output/mpm-dsoldt-' num2str(nrElems) '-' num2str(nrPts/nrElems) '-' num2str(t,'%1.4f') '.eps'], 'eps') 47 | 48 | f = figure('visible','off'); clf; 49 | h = max(norm(c4n(3,:) - c4n(1,:),2)); 50 | for elem = 1:nrElems 51 | plot(c4n(n4e(elem,[1:4 1]),1)+wI(n4e(elem,[1:4,1]),1),... 52 | c4n(n4e(elem,[1:4,1]),2)+wI(n4e(elem,[1:4,1]),2)); 53 | hold on; 54 | end 55 | axis equal 56 | margin = .01; 57 | axis([min(c4n(:,1))-margin,max(c4n(:,1))+margin,... 58 | min(c4n(:,2))-margin,max(c4n(:,2))+margin]) 59 | title({'MPM Solution u(x,t)';['t=' num2str(t,'%10.3f') ',' num2str(nrElems) ' elts,'... 60 | num2str(nrPts) ' mtrl pts']}) 61 | drawnow 62 | % matlab2tikz(['../output/mpm-grid-' num2str(nrElems) '-' num2str(nrPts/nrElems) ... 63 | % '-' '-' num2str(t,'%1.4f') '.tikz']) 64 | end 65 | -------------------------------------------------------------------------------- /plot/plotSolExact.m: -------------------------------------------------------------------------------- 1 | function plotSolExact(c4n,n4e,x4p,t,v4p,vpexact,wI,wIexact) 2 | % 3 | nrElems = size(n4e,1); 4 | nrPts = size(x4p,1); 5 | f = figure('visible','off'); 6 | clf; 7 | h = max(norm(c4n(3,:) - c4n(1,:),2)); 8 | scale = 60*h; 9 | for elem = 1:nrElems 10 | plot(c4n(n4e(elem,[1:4 1]),1),c4n(n4e(elem,[1:4,1]),2)); 11 | hold on; 12 | end 13 | axis equal 14 | margin = .01; 15 | axis([min(c4n(:,1))-margin,max(c4n(:,1))+margin,min(c4n(:,2))-margin,max(c4n(:,2))+margin]) 16 | title({'MPM Solution u(X,t)'; ['t=' num2str(t,'%10.3f') ',' num2str(nrElems) ' elts,' num2str(nrPts) ' mtrl pts']}) 17 | 18 | quiver(c4n(:,1),c4n(:,2),wIexact(:,1),wIexact(:,2),h,'--g'); 19 | hold on; 20 | quiver(c4n(:,1),c4n(:,2),wI(:,1),wI(:,2),h,'r'); 21 | hold off; 22 | legend('mesh','u_I','uexact','Location','NorthEastOutside'); 23 | drawnow 24 | matlab2tikz(['output/mpm-sol-' num2str(nrElems) '-' num2str(nrPts/nrElems) ... 25 | '-' num2str(t,'%1.4f') '.tikz']) 26 | quiver(c4n(:,1),c4n(:,2),10*(wI(:,1)-wIexact(:,1)),10*(wI(:,2)-wIexact(:,2)),'r'); 27 | 28 | f = figure('visible','off'); 29 | clf; 30 | figure(1); 31 | for elem = 1:nrElems 32 | plot(c4n(n4e(elem,[1:4 1]),1),c4n(n4e(elem,[1:4,1]),2)); 33 | hold on; 34 | end 35 | plot(x4p(:,1),x4p(:,2),'r.'); 36 | 37 | axis equal 38 | margin = .01; 39 | axis([min(c4n(:,1))-margin,max(c4n(:,1))+margin,... 40 | min(c4n(:,2))-margin,max(c4n(:,2))+margin]) 41 | title({'MPM Solution';['t=' num2str(t,'%10.3f')]}) 42 | quiver(x4p(:,1),x4p(:,2),vpexact(:,1),vpexact(:,2),'--g'); 43 | quiver(x4p(:,1),x4p(:,2),v4p(:,1),v4p(:,2),'r'); 44 | 45 | title({'MPM Solution v(x_p,t)';['t=' num2str(t,'%10.3f') ',' num2str(nrElems) ' elts,'... 46 | num2str(nrPts) ' mtrl pts']}) 47 | legend('mesh','mtrl pts','v_I','vexact','Location','NorthEastOutside'); 48 | drawnow 49 | matlab2tikz(['output/mpm-dsoldt-' num2str(nrElems) '-' num2str(nrPts/nrElems) ... 50 | '-' '-' num2str(t,'%1.4f') '.tikz']) 51 | 52 | f = figure('visible','off'); clf; 53 | h = max(norm(c4n(3,:) - c4n(1,:),2)); 54 | for elem = 1:nrElems 55 | plot(c4n(n4e(elem,[1:4 1]),1)+wI(n4e(elem,[1:4,1]),1),... 56 | c4n(n4e(elem,[1:4,1]),2)+wI(n4e(elem,[1:4,1]),2)); 57 | hold on; 58 | end 59 | axis equal 60 | margin = .01; 61 | axis([min(c4n(:,1))-margin,max(c4n(:,1))+margin,... 62 | min(c4n(:,2))-margin,max(c4n(:,2))+margin]) 63 | title({'MPM Solution u(x,t)';['t=' num2str(t,'%10.3f') ',' num2str(nrElems) ' elts,'... 64 | num2str(nrPts) ' mtrl pts']}) 65 | drawnow 66 | matlab2tikz(['output/mpm-grid-' num2str(nrElems) '-' num2str(nrPts/nrElems) ... 67 | '-' '-' num2str(t,'%1.4f') '.tikz']) 68 | end 69 | -------------------------------------------------------------------------------- /run/convRate.m: -------------------------------------------------------------------------------- 1 | function convHistory = convRate 2 | % Computes MPM solutions on a sequence of finer meshes 3 | % and outputs convergence history plot. 4 | 5 | dof = 2.^(2:6); 6 | convHistory = []; 7 | for k = 1:length(dof) 8 | convHistory(k) = run2DMPM(dof(k)); 9 | end 10 | f = figure('visible','off'); clf; 11 | h = 1./(sqrt(2)*(1:length(dof))); 12 | loglog(h,convHistory,'-bx') 13 | p = polyfit(log(h),log(convHistory),1); 14 | legend(['L^2 error (slope=' num2str(abs(p(1)),'%1.4f') ')'],... 15 | 'Location','NorthEastOutside') 16 | title('Convergence History') 17 | matlab2tikz('output/conv-rate.tikz') 18 | 19 | end 20 | -------------------------------------------------------------------------------- /run/run2DMPM.m: -------------------------------------------------------------------------------- 1 | function L2error = run2DMPM(n) 2 | % Computes Material Point Method solution and returns computed L^2 error 3 | % 4 | % L2error = run2DMPM(n) 5 | % 6 | % n: number of elements along x-direction 7 | % L2error: computed L^2 error between true and approx solution. 8 | % 9 | % Donsub Rim (drim@uw.edu) 10 | % 11 | 12 | 13 | %% Run 2D MPM code 14 | addpath(genpath('./')) 15 | xlim = [0,1]; ylim = [0,1]; 16 | nmp4e = 4; 17 | dx = (xlim(2) - xlim(1))/n; 18 | 19 | %% Initialization 20 | lambda = 0.3; % Lame const 21 | mu = 0.4; % Lame const 22 | c0 = sqrt(mu); % prob param 23 | t = 0; % init time 24 | T = 2/c0 ; % final time 25 | dt = 0.5*(dx); % time step 26 | A = 0.01; % prob param 27 | v0 = @(X) A*sin(pi*X); % initial velocity 28 | f = @(Z,t) A/c0*cos(pi*Z).*sin(c0*pi*t) + 1; % defd for convenience 29 | df = @(Z,t) -A*pi/c0*sin(pi*Z).*sin(c0*pi*t); % defd for convenience 30 | b = @(X,t) [(c0^2 - mu)*df(X(:,1),t) ... % body force 31 | + (lambda*log(abs(f(X(:,1),t).*f(X(:,2),t))) ... 32 | - (lambda + mu)).*df(X(:,1),t)./f(X(:,1),t).^2, ... 33 | (c0^2 - mu)*df(X(:,2),t) ... 34 | + (lambda*log(abs(f(X(:,1),t).*f(X(:,2),t))) ... 35 | - (lambda + mu)).*df(X(:,2),t)./f(X(:,2),t).^2]; 36 | rho0 = @(x) 0*x(:,1)+1; % init density = 1 37 | sigma0 = @(x) zeros(2,2,length(x)) ; % init stress = 0 38 | uexact = @(X,t) A/(c0*pi)*sin(pi*X)*sin(c0*pi*t); % exact displacement 39 | vexact = @(X,t) A*sin(pi*X)*cos(c0*pi*t); % exact velocity 40 | 41 | % Grid / Material Point set-up. 42 | nx = n; ny = n; % nr of elts along x,y 43 | [c4n,n4e,inNodes,bdNodes,bdNormals,bdTangents,inComps,vol4e] = ... 44 | generateRectMesh(xlim,ylim,nx,ny); 45 | e4n = computeE4n(n4e); % compute e4n 46 | [x4p,e4p] = generateMp(c4n,n4e,@isbody,nmp4e); 47 | nrNodes = size(c4n,1); 48 | nrPts = size(x4p,1); 49 | 50 | % Initialize variables. 51 | b4p = b(x4p,0); 52 | v4p = v0(x4p); 53 | vol4p = zeros(nrPts,1); % init var vol4p 54 | rho4p = zeros(nrPts,1); % init var rho4p 55 | parfor p = 1:nrPts 56 | vol4p(p) = vol4e(1)/nmp4e; % init vol 57 | F4p(:,:,p) = eye(2,2); % init deformation gradient 58 | end 59 | J4p = zeros(nrPts,1); % init var J4p 60 | rho4p(:,1) = rho0(x4p(:,1)); % init mass density 61 | sigma4p = sigma0(x4p); % init stress 62 | m4p(:,1) = vol4p(:,1).*rho4p(:,1); % init material point mass 63 | uI = zeros(nrNodes,2); % init nodal vars 64 | vIold = zeros(nrNodes,2); 65 | vI = zeros(nrNodes,2); 66 | 67 | %% MPM Loop 68 | 69 | while (t < (T - 100*eps)) 70 | 71 | if t + dt > T 72 | t = T; 73 | dt = T - t; 74 | end 75 | 76 | % Interpolate to Grid 77 | [mI,mvI,fI] = p2I(x4p,e4p,c4n,n4e,m4p,vol4p,v4p,... 78 | b4p,sigma4p,nrPts,nrNodes,bdNormals); 79 | 80 | % Solve on Grid (update momentum) 81 | posI = mI > 1e-12; 82 | vIold(posI,:) = mvI(posI,:)./repmat(mI(posI),1,2); 83 | mvI(inComps) = mvI(inComps) + dt*fI(inComps); 84 | vI(posI,:) = mvI(posI,:)./repmat(mI(posI),1,2); 85 | vI(~posI,:) = zeros(sum(~posI,1),2); % remove node values close to 0 86 | uI = uI + dt*vI; 87 | 88 | % Update Material Pts 89 | t = t + dt; % time step 90 | b4p = b(x4p,t); % update body force 91 | [x4p,e4p,v4p,F4p,J4p,rho4p,vol4p,sigma4p] = I2p(... 92 | x4p,v4p,m4p,e4p,c4n,n4e,e4n,rho4p(:,1),... 93 | vI,vIold,F4p,nrPts,nrNodes,dt,lambda,mu); 94 | 95 | display(['time = ' num2str(t,'%1.4f') '/' num2str(T,'%1.4f')]); 96 | 97 | 98 | plotSolExact(c4n,n4e,x4p,t,v4p,vexact(x4p,t),uI,uexact(c4n,t)) 99 | end 100 | 101 | 102 | plotSolExact(c4n,n4e,x4p,t,v4p,vexact(x4p,t),uI,uexact(c4n,t)) 103 | [L2error,upbd] = computeL2error(uI,uexact,c4n,n4e,T); 104 | end 105 | 106 | function [xx, yy] = isbody(xx,yy) 107 | % Given (xx,yy) returns only those points that are inside the body 108 | j = logical((xx >= 0) .* (xx <= 1) .* (yy >= 0) .* (yy <= 1)); 109 | xx = xx(j); 110 | yy = yy(j); 111 | end 112 | 113 | -------------------------------------------------------------------------------- /run/runConvect.m: -------------------------------------------------------------------------------- 1 | function runConvect(n) 2 | % Computes Material Point Method solution and returns computed L^2 error 3 | % 4 | % L2error = run2DMPM(n) 5 | % 6 | % n: number of elements along x-direction 7 | % L2error: computed L^2 error between true and approx solution. 8 | % 9 | % Donsub Rim (drim@uw.edu) 10 | % 11 | 12 | 13 | %% Run 2D MPM code 14 | addpath(genpath('../')) 15 | xlim = [0,128]; ylim = [0,128]; 16 | nmp4e = 4; 17 | dx = (xlim(2) - xlim(1))/n; 18 | 19 | %% Initialization 20 | lambda = 0.3; % Lame const 21 | mu = 0.4; % Lame const 22 | c0 = sqrt(mu); % prob param 23 | t = 0; % init time 24 | T = 72; % final time 25 | dt = 0.5*(dx); % time step 26 | A = 0.01; % prob param 27 | v0 = @(X) 0*X; % initial velocity 28 | b = @(X,t) 0*X; 29 | rho0 = @(x) 0*x(:,1)+1; % init density = 1 30 | sigma0 = @(x) zeros(2,2,length(x)) ; % init stress = 0 31 | 32 | % Grid / Material Point set-up. 33 | nx = n; ny = n; % nr of elts along x,y 34 | [c4n,n4e,inNodes,bdNodes,bdNormals,bdTangents,inComps,vol4e] = ... 35 | generateRectMesh(xlim,ylim,nx,ny); 36 | e4n = computeE4n(n4e); % compute e4n 37 | [x4p,e4p] = generateMp(c4n,n4e,@isbody,nmp4e); 38 | nrNodes = size(c4n,1); 39 | nrPts = size(x4p,1); 40 | nrElems = size(n4e,1); 41 | 42 | % Initialize variables. 43 | b4p = b(x4p,0); 44 | v4p = v0(x4p); 45 | vol4p = zeros(nrPts,1); % init var vol4p 46 | rho4p = zeros(nrPts,1); % init var rho4p 47 | parfor p = 1:nrPts 48 | vol4p(p) = vol4e(1)/nmp4e; % init vol 49 | F4p(:,:,p) = eye(2,2); % init deformation gradient 50 | end 51 | J4p = zeros(nrPts,1); % init var J4p 52 | rho4p(:,1) = rho0(x4p(:,1)); % init mass density 53 | sigma4p = sigma0(x4p); % init stress 54 | m4p(:,1) = vol4p(:,1).*rho4p(:,1); % init material point mass 55 | uI = zeros(nrNodes,2); % init nodal vars 56 | vIold = zeros(nrNodes,2); 57 | vI = zeros(nrNodes,2); 58 | 59 | %% MPM Loop 60 | 61 | plotSol(c4n,n4e,x4p,t,v4p,uI) 62 | while (t < (T - 100*eps)) 63 | 64 | if t + dt > T 65 | t = T; 66 | dt = T - t; 67 | end 68 | 69 | % Interpolate to Grid 70 | % [mI,mvI,fI] = p2I(x4p,e4p,c4n,n4e,m4p,vol4p,v4p,... 71 | % b4p,sigma4p,nrPts,nrNodes,bdNormals); 72 | 73 | % Solve on Grid (update momentum) 74 | % posI = mI > 1e-12; 75 | % vIold(posI,:) = mvI(posI,:)./repmat(mI(posI),1,2); 76 | % mvI(inComps) = mvI(inComps) + dt*fI(inComps); 77 | % vI(posI,:) = mvI(posI,:)./repmat(mI(posI),1,2); 78 | % vI(~posI,:) = zeros(sum(~posI,1),2); % remove node values close to 0 79 | vIold = vI; 80 | vI = ones(nrNodes,2); 81 | uI = uI + dt*vI; 82 | 83 | % Update Material Pts 84 | t = t + dt; % time step 85 | b4p = b(x4p,t); % update body force 86 | [x4p,e4p,v4p,F4p,J4p,rho4p,vol4p,sigma4p] = I2p(... 87 | x4p,v4p,m4p,e4p,c4n,n4e,e4n,rho4p(:,1),... 88 | vI,vIold,F4p,nrPts,nrNodes,dt,lambda,mu); 89 | 90 | display(['time = ' num2str(t,'%1.4f') '/' num2str(T,'%1.4f')]); 91 | 92 | 93 | plotSol(c4n,n4e,x4p,t,v4p,uI) 94 | end 95 | 96 | 97 | end 98 | 99 | function [xx, yy] = isbody(xx,yy) 100 | % Given (xx,yy) returns only those points that are inside the body 101 | j = logical((xx >= 20) .* (xx <= 40) .* (yy >= 20) .* (yy <= 40)); 102 | xx = xx(j); 103 | yy = yy(j); 104 | end 105 | 106 | -------------------------------------------------------------------------------- /run/runIceConvectRotation.m: -------------------------------------------------------------------------------- 1 | function runIceConvectRotation(n) 2 | % Computes Material Point Method solution and returns computed L^2 error 3 | % 4 | % L2error = run2DMPM(n) 5 | % 6 | % n: number of elements along x-direction 7 | % L2error: computed L^2 error between true and approx solution. 8 | % 9 | % Donsub Rim (drim@uw.edu) 10 | % 11 | 12 | 13 | %% Run 2D MPM code 14 | addpath(genpath('../')) 15 | xlim = [0,128]; ylim = [0,128]; 16 | nmp4e = 4; 17 | dx = (xlim(2) - xlim(1))/n; 18 | 19 | %% Initialization 20 | lambda = 0.3; % Lame const 21 | mu = 0.4; % Lame const 22 | c0 = sqrt(mu); % prob param 23 | t = 0; % init time 24 | T = 2*64*pi; % final time 25 | dt = 0.5*(dx); % time step 26 | A = 0.01; % prob param 27 | v = @(x) 1/64*[-(x(:,2)-64),(x(:,1)-64)]; 28 | % v = @(x) ones(size(x)); 29 | b = @(X,t) 0*X; 30 | rho0 = @(x) 0*x(:,1)+1; % init density = 1 31 | sigma0 = @(x) zeros(2,2,length(x)) ; % init stress = 0 32 | 33 | % Grid / Material Point set-up. 34 | nx = n; ny = n; % nr of elts along x,y 35 | [c4n,n4e,inNodes,bdNodes,bdNormals,bdTangents,inComps,vol4e] = ... 36 | generateRectMesh(xlim,ylim,nx,ny); 37 | e4n = computeE4n(n4e); % compute e4n 38 | [x4p,e4p] = generateMp(c4n,n4e,@isbody,nmp4e); 39 | nrNodes = size(c4n,1); 40 | nrPts = size(x4p,1); 41 | nrElems = size(n4e,1); 42 | 43 | % Initialize variables. 44 | b4p = b(x4p,0); 45 | v4p = v(x4p); 46 | vol4p = zeros(nrPts,1); % init var vol4p 47 | rho4p = zeros(nrPts,1); % init var rho4p 48 | parfor p = 1:nrPts 49 | vol4p(p) = vol4e(1)/nmp4e; % init vol 50 | F4p(:,:,p) = eye(2,2); % init deformation gradient 51 | end 52 | J4p = zeros(nrPts,1); % init var J4p 53 | h4p = ones(nrPts,1); 54 | A4p = ones(nrPts,1); 55 | SA4p = zeros(nrPts,1); 56 | SH4p = zeros(nrPts,1); 57 | hbar4p = ones(nrPts,1); 58 | rho4p(:,1) = rho0(x4p(:,1)); % init mass density 59 | sigma4p = sigma0(x4p); % init stress 60 | m4p(:,1) = vol4p(:,1).*rho4p(:,1); % init material point mass 61 | uI = zeros(nrNodes,2); % init nodal vars 62 | vIold = zeros(nrNodes,2); 63 | vI = v(c4n); 64 | 65 | %% MPM Loop 66 | 67 | plotSol(c4n,n4e,x4p,t,v4p,uI) 68 | while (t < (T - 100*eps)) 69 | 70 | if t + dt > T 71 | t = T; 72 | dt = T - t; 73 | end 74 | 75 | % Interpolate to Grid 76 | % [mI,mvI,fI] = p2I(x4p,e4p,c4n,n4e,m4p,vol4p,v4p,... 77 | % b4p,sigma4p,nrPts,nrNodes,bdNormals); 78 | 79 | % Solve on Grid (update momentum) 80 | % posI = mI > 1e-12; 81 | % vIold(posI,:) = mvI(posI,:)./repmat(mI(posI),1,2); 82 | % mvI(inComps) = mvI(inComps) + dt*fI(inComps); 83 | % vI(posI,:) = mvI(posI,:)./repmat(mI(posI),1,2); 84 | % vI(~posI,:) = zeros(sum(~posI,1),2); % remove node values close to 0 85 | vIold = zeros(nrNodes,2); 86 | vI = v(c4n); 87 | uI = uI + dt*vI; 88 | 89 | % Update Material Pts 90 | t = t + dt; % time step 91 | b4p = b(x4p,t); % update body force 92 | v4p = zeros(nrPts,2); 93 | [x4p,e4p,v4p,F4p,J4p,rho4p,vol4p,... 94 | sigma4p,h4p,hbar4p,A4p] = I2pIce(... 95 | x4p,v4p,m4p,e4p,c4n,n4e,e4n,rho4p(:,1),... 96 | vI,vIold,F4p,nrPts,nrNodes,dt,lambda,mu,... 97 | h4p,hbar4p,A4p); 98 | 99 | display(['time = ' num2str(t,'%1.4f') '/' num2str(T,'%1.4f')]); 100 | 101 | 102 | plotSol(c4n,n4e,x4p,t,v4p,uI) 103 | end 104 | 105 | 106 | end 107 | 108 | function [xx, yy] = isbody(xx,yy) 109 | % Given (xx,yy) returns only those points that are inside the body 110 | j = logical(((xx-106).^2 + (yy-64).^2)<=100); 111 | xx = xx(j); 112 | yy = yy(j); 113 | end 114 | 115 | -------------------------------------------------------------------------------- /run/runIceConvergentFlow.m: -------------------------------------------------------------------------------- 1 | function runIceConvergentFlow(n) 2 | % Computes Material Point Method solution and returns computed L^2 error 3 | % 4 | % L2error = run2DMPM(n) 5 | % 6 | % n: number of elements along x-direction 7 | % L2error: computed L^2 error between true and approx solution. 8 | % 9 | % Donsub Rim (drim@uw.edu) 10 | % 11 | 12 | 13 | %% Run 2D MPM code 14 | addpath(genpath('../')) 15 | xlim = [-1.6,1.6]; ylim = [0,0.5]; 16 | nmp4e = 4; 17 | dx = (xlim(2) - xlim(1))/n; 18 | 19 | %% Initialization 20 | lambda = 0.3; % Lame const 21 | mu = 0.4; % Lame const 22 | c0 = sqrt(mu); % prob param 23 | t = 0; % init time 24 | T = 2; % final time 25 | dt = 0.001*(dx); % time step 26 | A = 0.01; % prob param 27 | v = @(x) [-x(:,1),0*x(:,2)]; 28 | % v = @(x) ones(size(x)); 29 | b = @(X,t) 0*X; 30 | rho0 = @(x) 0*x(:,1)+1; % init density = 1 31 | sigma0 = @(x) zeros(2,2,length(x)) ; % init stress = 0 32 | 33 | % Grid / Material Point set-up. 34 | nx = n; ny = n; % nr of elts along x,y 35 | [c4n,n4e,inNodes,bdNodes,bdNormals,bdTangents,inComps,vol4e] = ... 36 | generateRectMesh(xlim,ylim,nx,ny); 37 | e4n = computeE4n(n4e); % compute e4n 38 | [x4p,e4p] = generateMp(c4n,n4e,@isbody,nmp4e); 39 | nrNodes = size(c4n,1); 40 | nrPts = size(x4p,1); 41 | nrElems = size(n4e,1); 42 | 43 | % Initialize variables. 44 | b4p = b(x4p,0); 45 | v4p = v(x4p); 46 | vol4p = zeros(nrPts,1); % init var vol4p 47 | rho4p = zeros(nrPts,1); % init var rho4p 48 | F4p = zeros(2,2,nrPts); 49 | parfor p = 1:nrPts 50 | vol4p(p) = vol4e(1)/nmp4e; % init vol 51 | F4p(:,:,p) = eye(2,2); % init deformation gradient 52 | end 53 | J4p = zeros(nrPts,1); % init var J4p 54 | h4p = ones(nrPts,1); 55 | A4p = ones(nrPts,1); 56 | SA4p = zeros(nrPts,1); 57 | SH4p = zeros(nrPts,1); 58 | hbar4p = ones(nrPts,1); 59 | rho4p(:,1) = rho0(x4p(:,1)); % init mass density 60 | sigma4p = sigma0(x4p); % init stress 61 | m4p(:,1) = vol4p(:,1).*rho4p(:,1); % init material point mass 62 | uI = zeros(nrNodes,2); % init nodal vars 63 | vIold = zeros(nrNodes,2); 64 | vI = v(c4n); 65 | 66 | %% MPM Loop 67 | 68 | plotSol(c4n,n4e,x4p,t,v4p,uI) 69 | while (t < (T - 100*eps)) 70 | 71 | if t + dt > T 72 | t = T; 73 | dt = T - t; 74 | end 75 | 76 | % Interpolate to Grid 77 | % [mI,mvI,fI] = p2I(x4p,e4p,c4n,n4e,m4p,vol4p,v4p,... 78 | % b4p,sigma4p,nrPts,nrNodes,bdNormals); 79 | 80 | % Solve on Grid (update momentum) 81 | % posI = mI > 1e-12; 82 | % vIold(posI,:) = mvI(posI,:)./repmat(mI(posI),1,2); 83 | % mvI(inComps) = mvI(inComps) + dt*fI(inComps); 84 | % vI(posI,:) = mvI(posI,:)./repmat(mI(posI),1,2); 85 | % vI(~posI,:) = zeros(sum(~posI,1),2); % remove node values close to 0 86 | vIold = zeros(nrNodes,2); 87 | vI = v(c4n); 88 | uI = uI + dt*vI; 89 | 90 | % Update Material Pts 91 | t = t + dt; % time step 92 | b4p = b(x4p,t); % update body force 93 | v4p = zeros(nrPts,2); 94 | [x4p,e4p,v4p,F4p,J4p,rho4p,vol4p,... 95 | sigma4p,h4p,hbar4p,A4p] = I2pIce(... 96 | x4p,v4p,m4p,e4p,c4n,n4e,e4n,rho4p(:,1),... 97 | vI,vIold,F4p,nrPts,nrNodes,dt,lambda,mu,... 98 | h4p,hbar4p,A4p); 99 | 100 | display(['time = ' num2str(t,'%1.4f') '/' num2str(T,'%1.4f')]); 101 | 102 | 103 | plotSol(c4n,n4e,x4p,t,v4p,uI) 104 | end 105 | 106 | 107 | end 108 | 109 | function [xx, yy] = isbody(xx,yy) 110 | % Given (xx,yy) returns only those points that are inside the body 111 | j = logical((xx >= -1.5).*(xx <= 1.5).*(yy >= 0).*(yy <= 0.5)); 112 | xx = xx(j); 113 | yy = yy(j); 114 | end 115 | 116 | -------------------------------------------------------------------------------- /solve/normalBC.m: -------------------------------------------------------------------------------- 1 | function vI = normalBC(vI,bdNormals) 2 | N = length(vI); 3 | vI(bdNormals(:,1) + (abs(bdNormals(:,2))-1)*N) = 0; 4 | end -------------------------------------------------------------------------------- /solve/shape.m: -------------------------------------------------------------------------------- 1 | function val = shape(xp,c4e) 2 | xi = (xp - c4e(1,:)); % needs more work! 3 | val = [(1-xi(1))*(1 - xi(2)); 4 | xi(1)*(1-xi(2)); 5 | xi(1)*xi(2); 6 | (1-xi(1))*xi(2)]; 7 | end -------------------------------------------------------------------------------- /solve/shapeR.m: -------------------------------------------------------------------------------- 1 | function val = shapeR(xp,c4n) 2 | h = [norm(c4n(2,:) - c4n(1,:)), norm(c4n(4,:) - c4n(1,:))]; 3 | xi = (xp - c4n(1,:))./h; 4 | val = [(1-xi(1))*(1 - xi(2)); 5 | xi(1)*(1-xi(2)); 6 | xi(1)*xi(2); 7 | (1-xi(1))*xi(2)]; 8 | end -------------------------------------------------------------------------------- /solve/shapeR0.m: -------------------------------------------------------------------------------- 1 | function val = shapeR0(xp,c4n,nodes,bdNodes) 2 | h = [norm(c4n(4,:) - c4n(1,:)), norm(c4n(2,:) - c4n(1,:))]; 3 | xi = (xp - c4n(1,:))./h; 4 | loop = nodes; 5 | bdpart = []; 6 | for j=1:4 7 | if ~isempty(bdpart) && sum(bdpart(j) == bdNodes) > 0 8 | bdpart = [bdpart; j]; 9 | end 10 | end 11 | val = [(1-xi(1))*(1 - xi(2)); xi(1)*(1-xi(2)); 12 | xi(1)*xi(2);(1-xi(1))*xi(2)]; 13 | val(bdpart,:) = zeros(length(bdpart),2); 14 | 15 | end -------------------------------------------------------------------------------- /solve/shapeR2n0.m: -------------------------------------------------------------------------------- 1 | function val = shapeR2n0(xp,c4nL,nodes,bdNormals) 2 | h = [norm(c4nL(4,:) - c4nL(1,:)), norm(c4nL(2,:) - c4nL(1,:))]; 3 | xi = (xp - c4nL(1,:))./h; 4 | val = [(1-xi(1))*(1 - xi(2)); 5 | xi(1)*(1-xi(2)); 6 | xi(1)*xi(2); 7 | (1-xi(1))*xi(2)]; 8 | val = repmat(val,1,2); 9 | for j = 1:4 10 | ind = (nodes(j) == bdNormals(:,1)); 11 | val(j,abs(bdNormals(ind,2))) = 0; 12 | end 13 | end -------------------------------------------------------------------------------- /solve/shapeRN0.m: -------------------------------------------------------------------------------- 1 | function val = shapeRN0(xp,c4n,nodes,bdNormal) 2 | h = [norm(c4n(4,:) - c4n(1,:)), norm(c4n(2,:) - c4n(1,:))]; 3 | xi = (xp - c4n(1,:))./h; 4 | loop = nodes; 5 | bdpart = []; 6 | for j=1:4 7 | k = (nodes(j) == bdNormal); 8 | if ~isempty(bdpart) && sum(k) > 0 9 | bdpart = [bdpart; bdNormal(k(:,1),:)]; 10 | end 11 | end 12 | val = [(1-xi(1))*(1 - xi(2)); xi(1)*(1-xi(2)); 13 | xi(1)*xi(2);(1-xi(1))*xi(2)]; 14 | for j = 1:length(bdpart) 15 | val(bdpart(j,1),bdpart(j,2)) = 0; 16 | end 17 | 18 | end -------------------------------------------------------------------------------- /solve/shapeRg.m: -------------------------------------------------------------------------------- 1 | function val = shapeRg(xp,c4n) 2 | h = [norm(c4n(2,:) - c4n(1,:)), norm(c4n(4,:) - c4n(1,:))]; 3 | xi = (xp - c4n(1,:))./h; 4 | val = [ -(1-xi(2))/h(1), -(1-xi(1))/h(2); 5 | (1-xi(2))/h(1), -xi(1)/h(2); 6 | xi(2)/h(1), xi(1)/h(2); 7 | -xi(2)/h(1), (1-xi(1))/h(2)]; 8 | end -------------------------------------------------------------------------------- /solve/shapeRg0.m: -------------------------------------------------------------------------------- 1 | function val = shapeRg0(xp,c4n,nodes,bdNodes) 2 | h = [norm(c4n(2,:) - c4n(1,:)), norm(c4n(4,:) - c4n(1,:))]; 3 | xi = (xp - c4n(1,:))./h; 4 | loop = nodes; 5 | bdpart = []; 6 | for j=1:4 7 | if ~isempty(bdpart) && sum(bdpart(j) == bdNodes) > 0 8 | bdpart = [bdpart; j]; 9 | end 10 | end 11 | val = [ -(1-xi(2))/h(1), -(1-xi(1))/h(2); 12 | (1-xi(2))/h(1), -xi(1)/h(2); 13 | xi(2)/h(1), xi(1)/h(2); 14 | -xi(2)/h(1), (1-xi(1))/h(2)]; 15 | val(bdpart,:) = zeros(length(bdpart),2); 16 | 17 | end --------------------------------------------------------------------------------