⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fjcst.m

📁 matlab中常用电法各种装置的电磁正演计算
💻 M
字号:
function [CCONV, NOUT, ROUT] = FJCST(FTYPE, RLO, RHI, IKEEP, IPOW, EPS, FUNC, varargin);

% [CCONV, NOUT, ROUT] = FJCST(FTYPE, RLO, RHI, IKEEP, IPOW, EPS, FUNC, varargin);
%
% FCST.m is part of the CR1Dmod forward modeling package. It is a function used
% to calculate a J0, J1, COS, or SIN transform of a complex or real function.
% The integral is computed as a convolution between sampled values of the 
% kernel function and Fast Hankel Transform filter coefficients.
%
%  What is calculated is the integral:
%  
%  G(r)=integral of [ FUNC(x) * (x**IPOW) * JCS(x*r) * dx ]
%  
%  from zero to infinity, where JCS is either J0, J1, COS, or SIN.
% 
% Input parameters:
% FTYPE:    Type of transform, use 'J04' for electromagnetic problems
% RLO:      Smallest R-value to be calculated
% RHI:      Largest R-value to be calculated, when negative, only RLO
%             is calculated
% IKEEP:    Keep previously calculated kernel function evaluations if 1
% IPOW:     Power of lambda multiplied with kernel function, used only 
%             when IKEEP is 1
% EPS:      Desired relative accuracy
% FUNC:     Function handle to kernel function
% varargin: Cell-array of variables passed directly to FUNC
%
% Output parameters:
% CCONV:    Result of the transform, array of values for chosen R-values
% NOUT:     Number of R-values calculated
% ROUT:     The actual R-values used in the calculations
%
% The kernel function must accept an array of values of the transform 
% parameter x as the first input, and any additional inputs should be
% transferred using the 'varargin' cell-array. The output must be an 
% array of values of identical size.
%
% This function has been translated from the cconvol Fortran routine 
% originally written by: 
% Niels B鴌e Christensen, 
% Department of Earth Sciences,
% University of Aarhus
%
% For more information about the choice of parameters please refer to 
% the notes from the original routine included below.
%% Translated and modified by:
% Thomas Ingeman-Nielsen
% The Arctic Technology Center, BYG
% Technical University of Denmark
% Email: tin@byg.dtu.dk
 
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                     %
%     Original comments for CCONVOL                                   %
%                                                                     %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                     %
%     S U B R O U T I N E   C C O N V O L                             %
%                                                                     %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%  Subroutine CCONVOL calculates a J0, J1, COS, or SIN transform of a
%  COMPLEX function. The integral is computed as a convolution between
%  sampled values of the kernel function and Fast Hankel Transform
%  filter coefficients. All calculations are in double precision
%  REAL*8 and COMPLEX*16.
%
%  What is calculated is the integral:
%  
%  G(r)=integral of [ FUNC(x) * (x**IPOW) * JCS(x*r) * dx ]
%  
%  from zero to infinity, where JCS is either J0, J1, COS, or SIN.
%  
%  INPUT PARAMETERS:
%  =================
%   FTYPE (CHARACTER*3) determines the type of transform. FTYPE must be
%   given with capital letters.
%   FTYPE='J01' :  J0-transform with omega=pi filters
%                  (analytical input functions)
%   FTYPE='J02' :  J0-transform with omega=pi/2 filters
%                  (e.g. geoelectrical input functions)
%   FTYPE='J04' :  J0-transform with omega=pi/4 filters
%                  (e.g. electromagnetic input functions)
%   J1-transforms are given by FTYPE=J11, J12, and J14, respectively.
%   COS-transforms are given by FTYPE=CO1, CO2, and CO4, respectively.
%   SIN-transforms are given by FTYPE=SI1, SI2, and SI4, respectively.
%
%  The integral is calculated for logarithmically regularly spaced
%  values of R.
%
%  R = exp(N*DEL)  ,  min(N) = NGLO  ,   max(N) = NGHI
%
%  Calculation is performed for values of R between R1 and R2, where R1
%  is the second largest regular R-value smaller than RLO, and R2 is
%  the second smallest regular R-value greater than RHI.
%
%  If RHI is negative computation is done for R=RLO only and RLO does
%  not have to be one of the regular R-values above, but can have any
%  value. This option makes it possible to avoid interpolation, if only
%  one R-value is needed, e.g. frequency soundings with only one
%  transmitter/receiver separation.
%
%  FUNC is the COMPLEX kernel function.
%
%  IKEEP (INTEGER) determines if the kernel function values are to be kept from
%  the previous computation.
%  IKEEP=1 :  keep the old values
%  IKEEP=0 :  compute new values
%  If IKEEP=1 then the kernel function FUNC must be the same as in the
%  previous call, but the input function FUNC is now multiplied with
%  a power of the integration variable.
%  
%  IPOW (INTEGER) the power of the integration variable with which the
%  input function is multiplied, when IKEEP=1. Only the values
%  IPOW=-1, 1, 2 are allowed. If other powers or other functions are
%  needed, please use the convolution routine with the option of
%  including any user defined function.
%  This option has been implemented to save computation time for
%  related transforms often met in e.g. EM calculations.
%  
%  EPS is the desired relative accuracy of the calculation.
%
%  If RLO, or RHI violate their restricted intervals determined by the
%  dimensioning of the subroutine, they are reset to their limiting
%  values.
%  
%  OUTPUT PARAMETERS:
%  ==================
%  NOUT is the number of values of ROUT, where the integral is
%  calculated.
%  
%  CCONV is a COMPLEX array containing the values of the integral.
%  
%  ROUT and CCONV must be dimensioned:
%  REAL*8 ROUT(NG)
%  COMPLEX*16 CCONV(NG)
%  in the calling subroutine, where NG must be the same as in this
%  subroutine.
%  
%  Subroutine CCONVOL needs a block data subprogram to transfer the
%  filter coefficients for the Hankel transform through the common
%  blocks /J0BLOCK/ and /J1BLOCK/.
%  
%  DIMENSIONING OF THE ARRAYS:
%  ===========================
%  The subroutine is dimensioned through the PARAMETER statements in
%  the first few lines of the code.
%
%  The filter coefficients used in the subroutine are from number NHLO 
%  to number NHHI.
%  
%  The maximum interval within which the output function can be
%  calculated is given by the numbers NGLO and NGHI (see above under
%  input parameters).
%  
%  The sampling density of the filters used is given by the statement
%  "NDEC=??" indicating the number of samples per decade. The sampling
%  density can also be given by the cut-off frequency (wavenumber) SC,
%  in which case the above statement should be changed to "SC=??".
%  
%  NLIM is the number of terms in the discrete convolution, which are
%  calculated initially without checking if the desired relative accuracy
%  has been reached. Recommended value is NLIM=4*NDEC.
%  This saves computation time.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

persistent FTYPEOLD KMIN KMAX FILT FC
       
NHLO = -200;
NHHI = 100;
NGLO= -20;
NGHI = 50;
NG = NGHI-NGLO+1;
NFLO = NGLO-NHHI;
NFHI = NGHI-NHLO;
NDEC = 10;
NLIM = 4*NDEC;

% ----------

if isempty(FTYPEOLD)
    FTYPEOLD = 'XXX';
    FILT = zeros(NHHI-NHLO+1,1);  % will store filter coefficients
    FC = zeros(NFHI-NFLO+1,1);    % NGHI-NGLO+NHHI-NHLO = size 371    
end

SQPI2 = 1.2533141373155;    % sqrt(pi/2)

% ----------

KEEP = IKEEP;
IPOT = IPOW;

% --- CALCULATE MAX AND MIN RADIAL DISTANCE FROM INITIAL PARAMETERS

if NDEC ~= 0
    SC = NDEC/log(100);
else
    disp('Error: 0 samples per decade defined for NDEC');
    return;
end

DEL = 0.5/SC;
RLOMIN=exp(NGLO*DEL);
RHIMAX=exp(NGHI*DEL);

% --- CHECK FOR ERRONEUS PARAMETERS IN THE SUBROUTINE CALL.

if (RLO < RLOMIN) 
    RLO=RLOMIN;
    disp('PARAMETER RLO IN SUBROUTINE FJCST OUT OF RANGE.');
    disp([' RLO HAS BEEN SET TO THE MINIMUM VALUE = ' num2str(RLOMIN)])
end

if (RHI > RHIMAX)
    RHI = RHIMAX;
    disp('PARAMETER RHI IN SUBROUTINE FJCST OUT OF RANGE.');
    disp([' RHI HAS BEEN SET TO THE MAXIMUM VALUE = ' num2str(RHIMAX)]);
end

if ((IKEEP < 0) | (IKEEP > 1))
    disp('PARAMETER IKEEP IN SUBROUTINE FJCST OUT OF RANGE');
end

if ((IKEEP == 1) & (FTYPEOLD == 'XXX'))
    disp('IKEEP=1 AT FIRST CALL TO FJCST IS ILLEGAL');
    disp(' PROGRAM STOPPED!');
    return
end    

if ~exist('filters.mat', 'file')
    if ~exist('define_filters.m','file')
        disp(' filters.mat not found, unable to load filter coefficients!');
        disp(' PROGRAM STOPPED!');
        return
    end
    define_filters;
end

% --- THE CHOSEN FILTER COEFFICIENTS ARE PUT INTO THE ARRAY FILT

if (FTYPE ~= FTYPEOLD)  
    if ismember(FTYPE, {'J01';'J11';'J02';'J12';'J04';...
                'J14';'CO1';'CO2';'CO4';'SI1';'SI2';'SI4'})
        S = load('filters.mat', FTYPE);    % Define filter-coefficients
        FILT(NHLO+201:NHHI+201) = S.(FTYPE)(NHLO+201:NHHI+201);
        FTYPEOLD = FTYPE;
    else
        disp(' CHARACTER STRING "FTYPE" ILLEGAL IN CALL TO FJCST');
        disp(' PROGRAM STOPPED!');
        return
    end
end

% --- INITIALIZATIONS

E = exp(DEL);
E1 = 1/E;

if (RHI < 0)    % If only one R-distance required
    R1 = RLO;
    R2 = RLO;
    NLO = floor(log(RLO)/DEL+100)-100;
    R10 = exp(NLO*DEL);
    XFAC = R10/R1;
    NOUT = 1;
else            % Otherwise...
    NLO = floor(log(RLO)/DEL+100)-101;
    if (NLO < NGLO) 
        NLO = NGLO;
    end
    NHI = floor(log(RHI)/DEL+100)-98;
    if (NHI > NGHI) 
        NHI = NGHI;
    end
    NOUT = NHI-NLO+1;
    R1 = exp(NLO*DEL);
    R2 = exp(NHI*DEL);
    XFAC = 1;
end

% --- Define initial interval if FUNC is new

if (IKEEP == 0)
    KMIN = NLO;
    KMAX = NLO+NLIM;
    
    X = E/R1;
    X = X.*E1.^[1:NLIM+1];
    FC(KMIN+201:KMAX+201) = feval(FUNC,X,varargin{:});
end

% --- CALCULATIONS BEGIN HERE

% --- Calculate for smallest R-value

R = R1;

XFIRST = XFAC*E1^(KMIN-1);
S=0;
S = CONVOF(NLO,KMIN,KMAX,1,S,XFIRST,E1,FC,FILT,KEEP,IPOT);

if (S ~= 0)
    XFIRST = XFAC*E1^KMAX;
    [S,FC,KLAST] = CONVON(NLO,KMAX+1,NLO-NHLO,1,S,XFIRST,E1,FUNC,EPS,FC,FILT,KEEP,IPOT,varargin{:});
    KMAX = KLAST;
    
    XFIRST = XFAC*E1^KMIN;
    [S,FC,KLAST] = CONVON(NLO,KMIN-1,NLO-NHHI,-1,S,XFIRST,E,FUNC,EPS,FC,FILT,KEEP,IPOT,varargin{:});
    KMIN = KLAST;
end
CCONV(1) = S/R;
ROUT(1) = R;

if (NOUT ~= 1)
    
    % --- Calculate for greatest R-value
    
    R = R2;
    
    XFIRST = E1^(KMIN-1);
    S=0;
    S = CONVOF(NHI,KMIN,KMAX,1,S,XFIRST,E1,FC,FILT,KEEP,IPOT);
    if (S ~= 0)
        XFIRST = E1^KMAX;
        [S,FC,KLAST] = CONVON(NHI,KMAX+1,NHI-NHLO,1,S,XFIRST,E1,FUNC,EPS,FC,FILT,KEEP,IPOT,varargin{:});
        KMAX = KLAST;
    end
    
    CCONV(NOUT) = S/R;
    ROUT(NOUT) = R;
    
    if (NOUT > 2)
        
        % --- Calculate for all other R-values
        
        R = R1;
        for I=NLO+1:NHI-1
            S=0;
            XFIRST = E1^(KMIN-1);
            S = CONVOF(I,KMIN,KMAX,1,S,XFIRST,E1,FC,FILT,KEEP,IPOT);
            R = R*E;
            CCONV(I-NLO+1) = S/R;
            ROUT(I-NLO+1) = R;
        end
    end
end

% --- If COS or SIN filters, multiply with SQRT(PI/2)


if ~strcmp(FTYPE(1),'J')
    
    for I=1:NOUT
        CCONV(I)=SQPI2*CCONV(I);
    end
    
end

% --- END CALCULATIONS


%CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
%C                                                                     C
%C     S U B R O U T I N E   C O N V O F                               C
%C                                                                     C
%CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
function S = CONVOF(IR,K1,K2,KDEL,S,X,DX,FC,FILT,KEEP,IPOT)

NHLO = -200;
NHHI = 100;
NGLO = -20;
NGHI = 50;
NG = NGHI-NGLO+1;

NFLO = NGLO-NHHI;
NFHI = NGHI-NHLO;

% ----------

K = [K1:KDEL:K2];

if (KEEP == 0)
  
    S=S+sum(FC(K+201).*FILT(IR-K+201));
    
else
    X = X.*DX.^[1:length(K)];    
    if (IPOT == -1)
        S = S+sum(FC(K+201).*FILT(IR-K+201)./X);
    end
    
    if (IPOT == 1)
        S = S+sum(FC(K+201).*FILT(IR-K+201).*X);
    end
    
    if (IPOT == 2)
        S = S+sum(FC(K+201).*FILT(IR-K+201).*X.^2);
    end
end


%CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
%C                                                                     C
%C     S U B R O U T I N E   C O N V O N                               C
%C                                                                     C
%CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
function [S,FC,KLAST] = CONVON(IR,K1,K2,KDEL,S,X,DX,FUNC,EPS1,FC,FILT,KEEP,IPOT,varargin)

NHLO = -200;
NHHI = 100;
NGLO = -20;
NGHI = 50;
NG = NGHI-NGLO+1;

NFLO = NGLO-NHHI;
NFHI = NGHI-NHLO;

% ----------

if (KEEP == 0)
    
    for K=K1:KDEL:K2
        X = X*DX;
        FC(K+201) = feval(FUNC,X,varargin{:});
        SDEL = FC(K+201)*FILT(IR-K+201);
        S = S+SDEL;
        if (abs(SDEL/S) < EPS1)
            break
        end
    end
    
else
    
    if (IPOT == -1)
        for K=K1:KDEL:K2
            X = X*DX;
            FC(K+201) = feval(FUNC,X,varargin{:});
            SDEL = FC(K+201)*FILT(IR-K+201)/X;
            S = S+SDEL;
            if (abs(SDEL/S) < EPS1)
                break
            end
        end
        
    elseif (IPOT == 1)
        for K=K1:KDEL:K2
            X = X*DX;
            FC(K+201) = feval(FUNC,X,varargin{:});
            SDEL = FC(K+201)*FILT(IR-K+201)*X;
            S = S+SDEL;
            if (abs(SDEL/S) < EPS1)
                break
            end
        end
    elseif (IPOT == 2)
        for K=K1:KDEL:K2
            X = X*DX;
            FC(K+201) = feval(FUNC,X,varargin{:});
            SDEL = FC(K+201)*FILT(IR-K+201)*X*X;
            S = S+SDEL;
            if (abs(SDEL/S) < EPS1)
                break
            end
        end
    end
    
end

KLAST = K;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -