입력상수 부족문제 어떻게 해결해야하나요?
2 views (last 30 days)
Show older comments
아래 코드로 진행했을때 입력 상수 문제라고 나오는데 어떤 부분이 잘 못된건가요?
function V = Poisson_FDM_Solver_2D(V,BC,EPS,RHO,h)
% Permittivity of free-space (F/m).
EPS_0 = 8.854e-12;
% Extract simulation domain size.
[Ny,Nx] = size(V,EPS_0);
% Total number of unknowns to solve for.
L = Nx*Ny;
% Instantiate the dielectric coefficient matrices.
a0 = zeros(Ny,Nx);
a1 = zeros(Ny,Nx);
a2 = zeros(Ny,Nx);
a3 = zeros(Ny,Nx);
a4 = zeros(Ny,Nx);
% Short-hand index notation.
X1 = 2:Nx-1;
Y1 = 2:Ny-1;
X2 = 1:Nx-2;
Y2 = 1:Ny-2;
% Compute the dielectric coefficients.
a0(Y1,X1) = -( EPS(Y1,X1) + EPS(Y2,X1) + EPS(Y1,X2) + EPS(Y2,X2) );
a1(Y1,X1) = (0.5)*( EPS(Y1,X1) + EPS(Y2,X1) );
a2(Y1,X1) = (0.5)*( EPS(Y1,X2) + EPS(Y1,X1) );
a3(Y1,X1) = (0.5)*( EPS(Y2,X2) + EPS(Y1,X2) );
a4(Y1,X1) = (0.5)*( EPS(Y2,X1) + EPS(Y2,X2) );
% Separate coefficients into real and imaginary components. Matlab runs a
% lot quicker if we can limit ourselves to purely real-valued variable
% manipulation until the last moment.
a0r = real(a0); % Real
a1r = real(a1); %
a2r = real(a2); %
a3r = real(a3); %
a4r = real(a4); %
a0i = imag(a0); % Imaginary
a1i = imag(a1); %
a2i = imag(a2); %
a3i = imag(a3); %
a4i = imag(a4); %
% Check for charge densities.
if nargin == 3
b = zeros(Ny*Nx,1);
else
% Insert default h-value if not specified.
if nargin == 4
h = 1;
end
% Normalized charge matrix. This term comes from integrating the
% charge density over a square region with size h.
b = -RHO*h^2/EPS_0;
b = b(:); % Vectorize.
end
% Set the four corners to Dirichlet boundaries to avoid confusion in the
% algorithm. These points do not really matter anyway.
BC(1,1) = 1;
BC(1,Nx) = 1;
BC(Ny,Nx) = 1;
BC(Ny,1) = 1;
% Define flags for Neumann boundaries. Each case needs to be handled in
% its own unique way, so it helps to give each one a unique marker.
TOP_FLAG = -1;
BOTTOM_FLAG = -2;
LEFT_FLAG = -3;
RIGHT_FLAG = -4;
% Find the Neumann BCs on the edges.
Neumann_TOP = BC(1,:) ~= 1;
Neumann_BOTTOM = BC(Ny,:) ~= 1;
Neumann_LEFT = BC(:,1) ~= 1;
Neumann_RIGHT = BC(:,Nx) ~= 1;
% Set flags for Neumann boundaries.
BC(1,Neumann_TOP) = TOP_FLAG;
BC(Ny,Neumann_BOTTOM) = BOTTOM_FLAG;
BC(Neumann_LEFT,1) = LEFT_FLAG;
BC(Neumann_RIGHT,Nx) = RIGHT_FLAG;
% Initialize indices and values to fill the system matrix.
NZmax = 5*L; % Maximum possible number of nonzero elements.
I = zeros(NZmax,1); % i-indices.
J = zeros(NZmax,1); % j-indices.
Sr = zeros(NZmax,1); % Real Values.
Si = zeros(NZmax,1); % Imag Values.
idx = 1; % Nonzero entry index.
% Begin iterating over the unknowns and prepare to fill the system
% matrix. Filling the A-matrix is MUCH faster if you know the indices and
% values "a priori" for ALL non-zero elements. So rather than directly
% fill in the A-matrix, this loop stores all the nonzero (i,j) indices
% along with their values. The A-matrix is then instantiated directly
% from this information.
% Note that by convention, Matlab scans matrices columnwise when only
% a single element is indexed. So rather than waste time vectorizing the
% BC-matrix or initial-valued V-matrix, just use a single index to load
% and store values and remember this convention.
disp('Filling System Matrix');
for n = 1:L
% Check boundary condition.
switch BC(n)
% Dirichlet boundary.
case 1
% A(n,n) = 1.
I(idx) = n;
J(idx) = n;
Sr(idx) = 1;
idx = idx + 1;
% Specify right-hand side as the voltage at this point.
b(n) = V(n);
% Top Neumann boundary.
case TOP_FLAG
% A(n,n) = 1.
I(idx) = n;
J(idx) = n;
Sr(idx) = 1;
idx = idx + 1;
% A(n,n+1) = -1.
I(idx) = n;
J(idx) = n + 1;
Sr(idx) = -1;
idx = idx + 1;
% Bottom Neumann boundary.
case BOTTOM_FLAG
% A(n,n) = 1.
I(idx) = n;
J(idx) = n;
Sr(idx) = 1;
idx = idx + 1;
% A(n,n-1) = -1.
I(idx) = n;
J(idx) = n - 1;
Sr(idx) = -1;
idx = idx + 1;
% Left Neumann boundary.
case LEFT_FLAG
% A(n,n) = 1.
I(idx) = n;
J(idx) = n;
Sr(idx) = 1;
idx = idx + 1;
% A(n,n+Ny) = -1.
I(idx) = n;
J(idx) = n + Ny;
Sr(idx) = -1;
idx = idx + 1;
% Right Neumann boundary.
case RIGHT_FLAG
% Set A(n,n) = 1
I(idx) = n;
J(idx) = n;
Sr(idx) = 1;
idx = idx + 1;
% A(n,n-Ny) = -1.
I(idx) = n;
J(idx) = n - Ny;
Sr(idx) = -1;
idx = idx + 1;
% Regular point. Apply the 5-point star.
otherwise
% Convention for 5-point star:
%
% V2 | Indexing direction
% V3 V0 V1 |
% V4 \-/
%
% REMINDER: Single-valued indexing of a Matrix will scan
% COLUMN-WISE!
% V0 (center) term: A(n,n) = a0(n).
I(idx) = n;
J(idx) = n;
Sr(idx) = a0r(n); % Real
Si(idx) = a0i(n); % imaginary
idx = idx + 1;
% V1 (right) term: A(n,n+Ny) = a1(n)
I(idx) = n;
J(idx) = n + Ny;
Sr(idx) = a1r(n); % Real
Si(idx) = a1i(n); % imaginary
idx = idx + 1;
% V2 (top) term: A(n,n+1) = a2(n)
I(idx) = n;
J(idx) = n + 1;
Sr(idx) = a2r(n); % Real
Si(idx) = a2i(n); % imaginary
idx = idx + 1;
% V3 (left) term: A(n,n-Ny) = a3(n)
I(idx) = n;
J(idx) = n - Ny;
Sr(idx) = a3r(n); % Real
Si(idx) = a3i(n); % imaginary
idx = idx + 1;
% V4 (bottom) term: A(n,n-1) = a4(n)
I(idx) = n;
J(idx) = n - 1;
Sr(idx) = a4r(n); % Real
Si(idx) = a4i(n); % imaginary
idx = idx + 1;
end
end
% Throw out the leftover zeros.
I = I(1:idx-1);
J = J(1:idx-1);
Sr = Sr(1:idx-1);
Si = Si(1:idx-1);
% Combine real and imaginary coefficients into one vector.
S = Sr + 1j*Si;
% Fill the system matrix.
A = sparse(I,J,S,L,L,NZmax);
% Clear out memory before performing inversion. The matrix inversion
% process is HUGELY memory intensive, and will greedily hog up all the RAM
% it can get. Clearing out the major variables from the workspace will at
% least give a few extra MB of memory to this process. It won't be much,
% but every little bit helps if we're inverting a very large system.
clear I J S BC a0 a1 a2 a3 a4 a0r a0i Sr Si ;
clear a1r a1i a2r a2i a3r a3i a4r a4i Neumann_TOP Neumann_BOTTOM;
clear Neumann_LEFT Neumann_RIGHT EPS RHO;
% Invert the matrix. The slash operator is fantastic at doing this
% quickly for sparse matrices.
disp('Solving System Matrix');
V = A\b;
disp('Done!');
% Put the voltages back into a matrix.
V = reshape(V,Ny,Nx);
return;
0 Comments
Accepted Answer
lazymatlab
on 3 Apr 2023
Edited: lazymatlab
on 3 Apr 2023
function이라는 키워드로 시작하는 함수의 첫 줄은 함수에 필요한 입력인자와 함수가 반환하는 출력인자를 정의합니다.
작성하신 코드의 첫 줄을 보면
function V = Poisson_FDM_Solver_2D(V, BC, EPS, RHO, h)
라고 되어 있습니다. 이 함수를 호출하기 위해서는 V, BC, EPS, RHO, h 값을 만들어서 넘겨주여야 합니다. 즉, 함수 호출의 형태가
Poisson_FDM_Solver_2D(V, BC, EPS, RHO, h)
이어야 합니다. 각 입력인자는 괄호 안에 직접 적어도 되고, 함수 호출 전에 변수에 저장한 후 함수 호출 시 변수명만 적어도 됩니다.
0 Comments
More Answers (0)
See Also
Categories
Find more on Matrices and Arrays in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!