This commit is contained in:
xinxiao
2026-03-13 11:24:41 +08:00
commit 04e2bb29c7
238 changed files with 29102 additions and 0 deletions
+324
View File
@@ -0,0 +1,324 @@
classdef ADI
% ADI class: simple implementation of automatic differentiation for easy construction of jacobian matrices.
%
% SYNOPSIS:
% x = ADI(value, jacobian)
%
% PARAMETERS:
% value - The numerical value of the object
%
% jacobian - The Jacobian of the object.
%
% RETURNS:
% ADI object.
%
% COMMENTS:
% This class is typically instansiated for a set of different variables
% using initVariablesADI. The file contains a worked example demonstrating
% the usage for several variables.
%
% SEE ALSO:
% initVariablesADI
%{
Copyright 2009-2014 SINTEF ICT, Applied Mathematics.
This file is part of The MATLAB Reservoir Simulation Toolbox (MRST).
MRST 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.
MRST 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 MRST. If not, see <http://www.gnu.org/licenses/>.
%}
properties
val %function value
jac %list of sparse jacobian matrices
end
methods
function obj = ADI(a,b)
%ADI class constructor
if nargin == 0 % empty constructor
obj.val = [];
obj.jac = {};
elseif nargin == 1 %
if isa(a, 'ADI')
obj = a;
else
error('Contructor requires 2 inputs')
end
elseif nargin == 2 % values + jacobians
obj.val = a; % value
if ~iscell(b)
b = {b};
end
obj.jac = b; % jacobian or list of jacobians
else
error('Input to constructor not valid')
end
end
%--------------------------------------------------------------------
function h = numval(u)
h = numel(u.val);
end
%--------------------------------------------------------------------
function h = double(u)
h = u.val;
end
%--------------------------------------------------------------------
function h = ge(u, v)
h = ge(double(u), double(v));
end
%--------------------------------------------------------------------
function h = gt(u, v)
h = gt(double(u), double(v));
end
%--------------------------------------------------------------------
function h = le(u, v)
h = le(double(u), double(v));
end
%--------------------------------------------------------------------
function h = lt(u, v)
h = lt(double(u), double(v));
end
%--------------------------------------------------------------------
function h = uplus(u)
h = u;
end
%--------------------------------------------------------------------
function h = uminus(u)
h = ADI(-u.val, uminusJac(u.jac));
end
%--------------------------------------------------------------------
% function h = plus(u,v)
% if ~isa(u,'ADI') %u is a vector/scalar
% h = ADI(u+v.val, v.jac);
% elseif ~isa(v,'ADI') %v is a vector/scalar
% h = ADI(u.val + v, u.jac);
% else
% h = ADI(u.val+v.val, plusJac(u.jac, v.jac) );
% end
% end
function h = plus(u,v)
if ~isa(u,'ADI') %u is a vector/scalar
if numel(u) <= numel(v.val)
h = ADI(u+v.val, v.jac);
elseif numel(v.val) == 1
h = plus(u, repmat(v,[numel(u), 1]));
else
error('Vectors have different lengths')
end
elseif ~isa(v,'ADI') %v is a vector/scalar
if numel(v) <= numel(u.val)
h = ADI(u.val + v, u.jac);
elseif numel(u.val) == 1
h = plus(repmat(u,[numel(v), 1]), v);
else
error('Vectors have different lengths')
end
else
if numel(u.val) == numel(v.val)
h = ADI(u.val+v.val, plusJac(u.jac, v.jac) );
elseif numel(u.val) == 1
h = plus(repmat(u, [numel(v.val), 1]), v);
elseif numel(v.val) == 1
h = plus(u, repmat(v, [numel(u.val), 1]));
else
error('Vectors have different lengths')
end
end
end
%--------------------------------------------------------------------
function h = minus(u,v)
h = plus(u, uminus(v));
end
%--------------------------------------------------------------------
function h = mtimes(u,v)% '*'
if ~isa(u,'ADI') %u is a scalar/matrix
h = ADI(u*v.val, mtimesJac(u, v.jac));
elseif ~isa(v,'ADI') %v is a scalar
h = mtimes(v,u);
else % special case where either u or v has single value
if numel(u.val) == 1
h = times(repmat(u, [numel(v.val), 1]), v);
elseif numel(v.val) == 1
h = times(u, repmat(v, [numel(u.val), 1]));
else
error('Operation not supported');
end
end
end
%--------------------------------------------------------------------
function h = times(u,v)% '.*'
if ~isa(u,'ADI') %u is a scalar/vector
if numel(u)==numel(v.val)
h = ADI(u.*v.val, lMultDiag(u, v.jac));
else
h = mtimes(u,v);
end
elseif ~isa(v,'ADI') %v is a scalar/vector
h = times(v,u);
else
if numel(u.val)==numel(v.val)
h = ADI(u.val.*v.val, timesJac(u.val, v.val, u.jac, v.jac));
elseif numel(v.val)==1||numel(u.val)==1
h = mtimes(u,v);
else
error('Operation not supported');
end
end
end
%--------------------------------------------------------------------
function h = mrdivide(u,v)% '/'
if ~isa(v,'ADI') %v is a scalar
h = mtimes(u, 1/v);
else
error('Operation not supported');
end
end
%--------------------------------------------------------------------
function h = subsref(u,s)
switch s(1).type
case '.'
h = builtin('subsref',u,s);
case '()'
assert(numel(s(1).subs) == 1, ...
'Expected single index, got %d', numel(s(1).subs))
subs = s(1).subs{1};
if ischar(s) && strcmp(subs, ':'),
h = u;
else
if islogical(subs), subs = find(subs); end
h = ADI(u.val(subs), subsrefJac(u.jac, subs));
end
if numel(s) > 1
% Recursively handle next operation
h = subsref(h, s(2:end));
end
case '{}'
error('Operation not supported');
end
end
%--------------------------------------------------------------------
function h = power(u,v)% '.^'
h = ADI(u.val.^v, lMultDiag(v.*u.val.^(v-1), u.jac));
end
%--------------------------------------------------------------------
function h = rdivide(u,v)% './'
h = times(u, power(v, -1));
end
%--------------------------------------------------------------------
function h = exp(u)
eu = exp(u.val);
h = ADI(eu, lMultDiag(eu, u.jac));
end
%--------------------------------------------------------------------
function h = log(u)
logu = log(u.val);
h = ADI(logu, lMultDiag(1./u.val, u.jac));
end
%--------------------------------------------------------------------
function h = interptable(X, Y, u)
y = interptable(X, Y, u.val);
dydx = dinterptable(X, Y, u.val);
h = ADI(y,lMultDiag(dydx, u.jac));
end
%--------------------------------------------------------------------
end
end
%**************************************************************************
%-------- Helper functions involving Jacobians ---------------------------
%**************************************************************************
function J = uminusJac(J1)
J = cellfun(@uminus, J1, 'UniformOutput', false);
end
function J = plusJac(J1, J2)
J = cellfun(@plus, J1, J2, 'UniformOutput', false);
end
function J = mtimesJac(M, J1)
J = cell(1, numel(J1));
for k = 1:numel(J)
J{k} = M*J1{k};
end
end
function J = lMultDiag(d, J1)
n = numel(d);
D = sparse((1:n)', (1:n)', d, n, n);
J = cell(1, numel(J1));
for k = 1:numel(J)
J{k} = D*J1{k};
end
end
function J = timesJac(v1, v2, J1, J2)
n = numel(v1);
D1 = sparse((1:n)', (1:n)', v1, n, n);
D2 = sparse((1:n)', (1:n)', v2, n, n);
J = cell(1, numel(J1));
for k = 1:numel(J)
J{k} = D1*J2{k} + D2*J1{k};
end
end
function J = subsrefJac(J1, subs)
J = cell(1, numel(J1));
for k = 1:numel(J)
J{k} = J1{k}(subs,:);
end
end
%--------------------------------------------------------------------------
%--------------------------------------------------------------------------
%--------------------------------------------------------------------------
@@ -0,0 +1,6 @@
function tm = ADtimestep(yitap, yitas, omega, dp, ds)
dp = abs(dp);
ds = abs(ds);
tm1 = (1 + omega) * yitap ./ (dp + omega * yitap);
tm2 = (1 + omega) * yitas ./ (ds + omega * yitas);
tm = min(min(tm1),min(tm2));
@@ -0,0 +1,24 @@
function os = OperatorRS(N, nex, nc)
%
%nex是网格之间具有流体交换的总数
%nc
%N
% Avg of face property
M = sparse((1 : nex)' * [1 1], N, 0.5 * ones(nex, 2), nex, nc);
os.faceAvg = @(x) M * x;
% Harm of face property
M = sparse((1 : nex)' * [1 1], N, ones(nex, 2), nex, nc);
os.faceHarm = @(x) 1./ (M * (1 ./ x));
% Div and grad
C = sparse((1 : nex)' * [1 1], N, ones(nex, 1) * [-1 1], nex, nc);
os.grad = @(x) C * x;
os.div = @(x) -C' * x;
% Upstream weighting
os.faceUpstr = @(flag, x) faceUpstr(flag, x, N, [nex, nc]);
function xu = faceUpstr(flag, x, N, sz)
flag = logical(flag);
upcell = N(:, 2);
upcell(flag) = N(flag, 1);
xu = sparse((1 : sz(1))', upcell, 1, sz(1), sz(2)) * x;
@@ -0,0 +1,13 @@
function h = dinterptable(X, Y, u)
% n = length(X);
% DYDX = diff(Y) ./ diff(X);
% DYDX = DYDX([1, 1:end, end]);
% [~, b] = histc(u, [-inf;X;inf]);
% b = b - 1;
% b(b == 0) = 1;
% b(b == n) = n - 1;
% h = DYDX(b);
DYDX = diff(Y) ./ diff(X);
DYDX = DYDX([1, 1:end, end]);
[~, b] = histc(u, [-inf;X;inf]);
h = reshape(DYDX(b), [], 1);
+17
View File
@@ -0,0 +1,17 @@
function f = fluidPVT(Bopb, pb, co, Bwi, prw, cw, vwi, cvw, visopb, cvo, SW, KRO, KRW, PCOW, ifpcow, SWF, KROF, KRWF, PCOWF, rpt,Dosi, Dwsi, cs_data, csa_data, cb_data, cba_data)
f.Bw = @(p) Bw(p, Bwi, prw, cw);
f.Bo = @(p) Bo(p, Bopb, pb, co);
f.muw = @(p) muw(p, vwi, prw, cvw);
f.muo = @(p) muo(p, visopb, pb, cvo);
f.kro = @(sw) kro(sw, SW, KRO, SWF, KROF, rpt);
f.krw = @(sw) krw(sw, SW, KRW, SWF, KRWF, rpt);
f.pcow = @(sw) pcow(sw, SW, PCOW, SWF, PCOWF, rpt);
f.krow = @(sw) kro(sw, SWF, KROF);
f.krww = @(sw) krw(sw, SWF, KRWF);
f.pcoww = @(sw) pcow(sw, SWF, PCOWF);
f.cs_absorb = @(sw) cs_absorb_f(cs, cs_data, csa_data);
f.cb_absorb = @(sw) cb_absorb_f(cb, cb_data, cba_data);
f.ifpcow = ifpcow;
f.Dosi = Dosi;
f.Dwsi = Dwsi;
@@ -0,0 +1,5 @@
function state = initialRS(P, Sw, Cs, Cb)
state.p = P;
state.sw = Sw;
state.cs = Cs;
state.cb = Cb;
+31
View File
@@ -0,0 +1,31 @@
function [P, Sw, Cs, Cb] = intADI(p, sw, cs, cb)
n = length(p);
Jp = cell(1,4);
Jsw = cell(1,4);
Jcs = cell(1,4);
Jcb = cell(1,4);
Jp{1} = sparse(1:n, 1:n, ones(n,1), n, n);
Jp{2} = sparse(n,n);
Jp{3} = sparse(n,n);
Jp{4} = sparse(n,n);
Jsw{1} = sparse(n,n);
Jsw{2} = sparse(1:n, 1:n, ones(n,1), n, n);
Jsw{3} = sparse(n,n);
Jsw{4} = sparse(n,n);
Jcs{1} = sparse(n,n);
Jcs{2} = sparse(n,n);
Jcs{3} = sparse(1:n, 1:n, ones(n,1), n, n);
Jcs{4} = sparse(n,n);
Jcb{1} = sparse(n,n);
Jcb{2} = sparse(n,n);
Jcb{3} = sparse(n,n);
Jcb{4} = sparse(1:n, 1:n, ones(n,1), n, n);
P = ADI(p, Jp);
Sw = ADI(sw, Jsw);
Cs = ADI(cs, Jcs);
Cb = ADI(cb, Jcb);
+44
View File
@@ -0,0 +1,44 @@
function [P, Sw, Cs, Cb, Pwf] = intADI2(p, sw, cs, cb, pwf)
n = length(p);
npwf = length(pwf);
Jp = cell(1,5);
Jsw = cell(1,5);
Jcs = cell(1,5);
Jcb = cell(1,5);
Jpwf = cell(1,5);
Jp{1} = sparse(1:n, 1:n, ones(n,1), n, n);
Jp{2} = sparse(n,n);
Jp{3} = sparse(n,n);
Jp{4} = sparse(n,n);
Jp{5} = sparse(n,npwf);
Jsw{1} = sparse(n,n);
Jsw{2} = sparse(1:n, 1:n, ones(n,1), n, n);
Jsw{3} = sparse(n,n);
Jsw{4} = sparse(n,n);
Jsw{5} = sparse(n,npwf);
Jcs{1} = sparse(n,n);
Jcs{2} = sparse(n,n);
Jcs{3} = sparse(1:n, 1:n, ones(n,1), n, n);
Jcs{4} = sparse(n,n);
Jcs{5} = sparse(n,npwf);
Jcb{1} = sparse(n,n);
Jcb{2} = sparse(n,n);
Jcb{3} = sparse(n,n);
Jcb{4} = sparse(1:n, 1:n, ones(n,1), n, n);
Jcb{5} = sparse(n,npwf);
Jpwf{1} = sparse(npwf,n);
Jpwf{2} = sparse(npwf,n);
Jpwf{3} = sparse(npwf,n);
Jpwf{4} = sparse(npwf,n);
Jpwf{5} = sparse(1:npwf, 1:npwf, ones(npwf,1), npwf, npwf);
P = ADI(p, Jp);
Sw = ADI(sw, Jsw);
Cs = ADI(cs, Jcs);
Cb = ADI(cb, Jcb);
Pwf = ADI(pwf, Jpwf);
+6
View File
@@ -0,0 +1,6 @@
function [z] = intADIz(z)
n = length(z);
Jz = cell(1,2);
Jz{1} = sparse( n, n);%
Jz{2} = sparse(n,n);%
z = ADI(z, Jz);
@@ -0,0 +1,2 @@
function h = interptable(X, Y, u)
h = interp1(X, Y, u, 'linear', 'extrap');