From 49ecc1dda9ef67ab55fecd80451cd628dcacf852 Mon Sep 17 00:00:00 2001 From: Aneesh Srinivas Date: Sun, 2 Mar 2025 01:27:44 -0800 Subject: [PATCH] Optimized helper functions for divergence altPascal is now calculated in a single loop. Both divergence helper and extensionOperatorDivergence now create their outputs without inserting into a sparse matrix(which is slow). --- src/matlab/alt_pascal.m | 16 +++----- src/matlab/calculateInteriorRow.m | 2 +- src/matlab/divergencehelper.m | 27 +++++++++---- src/matlab/extensionOperatorDivergence.m | 48 ++++++++++++++---------- 4 files changed, 54 insertions(+), 39 deletions(-) diff --git a/src/matlab/alt_pascal.m b/src/matlab/alt_pascal.m index 9240ee8..8873b97 100644 --- a/src/matlab/alt_pascal.m +++ b/src/matlab/alt_pascal.m @@ -1,17 +1,13 @@ function [ A ] = alt_pascal( n ) -% Calculates the alternating pascal triangle. -% Will give exact values for n<56 - if(n>1030); error('Argument should be less than 1031'); end +% Calculates the alternating pascal triangle up to n rows. +% This is the change of basis matrix from the basis {i in {0,1,...,n-1}:(e^(h*D)-1)^i} to +% the standard basis. {i in {0,1,...,n-1}:(e^(i*h*D))} A=eye(n); - A(:,1)=1; + A(:,1)=2*rem(1:n,2) - 1; %Alternating vector [1,-1,1,-1,...] for i=2:n - A(i,2:end)=A(i-1,1:end-1)+A(i-1,2:end); - end - for i=1:n - for j=1:i - A(i,j)=A(i,j)*(-1)^(i+j); - end + A(i,2:end)=A(i-1,1:end-1)-A(i-1,2:end); end + end \ No newline at end of file diff --git a/src/matlab/calculateInteriorRow.m b/src/matlab/calculateInteriorRow.m index fff8e40..eca6384 100644 --- a/src/matlab/calculateInteriorRow.m +++ b/src/matlab/calculateInteriorRow.m @@ -9,7 +9,7 @@ % Our answer. r=idivide(k,int32(2)); output(r)=-1.0; - output(r+1)=1.0; + output(r+1)=1.0; %our starting value for this series is (e^(h/2*d/dx)-e^(-h/2*d/dx)) if (k>2) nextTerm=zeros([1,k]);% NextTerm in the series. %Initially set to (e^(h/2*d/dx)-e^(-h/2*d/dx))^(3) diff --git a/src/matlab/divergencehelper.m b/src/matlab/divergencehelper.m index 3cbf9a7..a4c23ec 100644 --- a/src/matlab/divergencehelper.m +++ b/src/matlab/divergencehelper.m @@ -1,14 +1,25 @@ function D=divergencehelper(k,m) %Calculates the mimetic divergence operator of order k, % barring dividing by dx. -% k=order of accuracy -% - r=calculateInteriorRow(k); - A=sparse(m+2,m+k-1); %This matrix is just using the interior scheme.Since we've extended our vector field - %beyond the boundaries it'd normally have, we don't need to use - %seperate power series expansions for the stencils near the boundary. +% k :order of accuracy. +% m :number of cells. + interior=calculateInteriorRow(k); %The interior row of our matrix + numNonZeros=m*k; % The number of nonZeroElements in the interior stencil matrix + rowList=zeros([1,numNonZeros]); + columnList=zeros([1,numNonZeros]); + valueList=zeros([1,numNonZeros]); + elementsInserted=1; for i=2:(m+1) - A(i,(i-1):(i+k-2))=r; + for j=1:(k) + rowList(elementsInserted)=i; + columnList(elementsInserted)=i+j-2; + valueList(elementsInserted)=interior(j); + elementsInserted=elementsInserted+1; + end end - D=A*extensionOperatorDivergence(k,m); + interiorScheme=sparse(rowList,columnList,valueList,m+2,m+k-1); + % This matrix is just using the interior scheme. + % Since we've extended our vector field beyond the boundaries it'd normally have, we don't need to use + % seperate power series expansions for the stencils near the boundary. + D=interiorScheme*extensionOperatorDivergence(k,m); end \ No newline at end of file diff --git a/src/matlab/extensionOperatorDivergence.m b/src/matlab/extensionOperatorDivergence.m index 324033f..77cd69e 100644 --- a/src/matlab/extensionOperatorDivergence.m +++ b/src/matlab/extensionOperatorDivergence.m @@ -1,22 +1,24 @@ function E=extensionOperatorDivergence(k,m) % Returns a m+k-1 by m+1 one matrix. Which pads an m+1` point vector field % With k/2-1 additional points on each side. These points are -% approximations of what happens if you extrapolate +% approximations of +% f(-(k/2-1)h),f(-(k/2-2)h),....,f(-h),f(1+h),f(1+2h),...,f(1+(k/2-1)h), +% with O(h^(k+1)) error on each of the approximations. % % % Parameters: % k : Order of accuracy % m : Number of cells - - E=sparse(m+k-1,m+1); + numOfRows=m+k-1; + numOfColumns=m+1; + numNonZeros=(k-2)*(k+1)+m+1;%The number of nonzero elements in E. + rowList=zeros([1,numNonZeros]);%Row indices for non zero elements + columnList=zeros([1,numNonZeros]); %Column indices for non zero elements + valueList=zeros([1,numNonZeros]); %Values of non zero elements + elementsInserted=1; %Number of elements inserted into rowList,ColumnList + %and ValueList r=idivide(k,int32(2)); - for i=r:m+r - E(i,i+1-r)=1; - end - R=zeros(r-1,k+1);%calculates the matrix R_{i,j}=binom(i-k/2,j) - %Used in the fact that e^(-jh)=∑_{i=0}^(k)binom(-j,i)(exp(h*d/dx)-I)^i+O(h^(k+1)). - % This is how you approximate f(-jh) as a linear combo of - %f(0),f(h),...,f(kh) with O(h^(k+1)). + R=zeros(r-1,k+1);% Calculates the matrix R_{i,j}=binom(i-k/2,j-1) R(:,1)=ones([r-1,1]); currentTerm=(-1); for i=2:(k+1) @@ -28,18 +30,24 @@ R(i,j)=R(i+1,j)-R(i,j-1); end end - - % A=[(-1)^(i+j)*binomial(i,j) for i=0:k,j=0:k] - R=R*alt_pascal(k+1) - for i=1:(r-1) + R=R*alt_pascal(k+1); %Converts R into the standard basis + for i=1:(r-1) % for j=1:(k+1) - E(i,j)=R(i,j); - E(m+k-i,m+2-j)=R(i,j); + rowList(elementsInserted)=i; + columnList(elementsInserted)=j; + valueList(elementsInserted)=R(i,j); + rowList(elementsInserted+1)=m+k-i; + columnList(elementsInserted+1)=m+2-j; + valueList(elementsInserted+1)=R(i,j); + elementsInserted=elementsInserted+2; end end - - - - + for i=r:m+r + rowList(elementsInserted)=i; + columnList(elementsInserted)=i+1-r; + valueList(elementsInserted)=1; + elementsInserted=elementsInserted+1; + end + E=sparse(rowList,columnList,valueList,numOfRows,numOfColumns); end \ No newline at end of file