!MNH_LIC Copyright 1989-2020 CNRS, Meteo-France and Universite Paul Sabatier !MNH_LIC This is part of the Meso-NH software governed by the CeCILL-C licence !MNH_LIC version 1. See LICENSE, CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt !MNH_LIC for details. version 1. !----------------------------------------------------------------- C**FILE: svode.f C**AUTHOR: Karsten Suhre C**DATE: Fri Nov 10 09:17:45 GMT 1995 C**PURPOSE: solver SVODE C**ORIGINAL: original from Peter N. Brown, Alan C. Hindmarsh, George D. Byrne C**MODIFIED: K. Suhre: added Fortran90 Interface and some slight changes C indicated by "*KS:" C**MODIFIED: 01/12/03 (Gazen) change Chemical scheme interface C**MODIFIED: 25/03/2008 (M.Leriche & J.P.Pinty):add "MIN(100.,...)" threshold C** in exponential calculation --> problem with "ifort -O2" compiler C**MODIFIED: 22/02/2011 (J.Escobar) remove erroneous 'CALL ABORT' C**MODIFIED: 19/06/2014 (J.Escobar & M.Leriche) write(kout,...) to OUTPUT_LISTING file C & correct IN_LUN = 11 => IN_LUN = 78 to avoid fort.11 creation C**MODIFIED: 10/01/2019 (P.Wautelet) use newunit argument to open files C + bug corrections: some files were not closed C**MODIFIED: 10/01/2019 (P.Wautelet) replace double precision declarations by C real(kind(0.0d0)) (to allow compilation by NAG compiler) C**MODIFIED: 08/02/2019 (P.Wautelet) bug fixes: missing argument C + wrong use of an non initialized value C P. Wautelet 17/08/2020: small correction in call to LEPOLY C! C! C! C! C! WARNING : MAJOR CHANGE FOR COMPATIBILITY WITH MESO-NH C! TPK is passed as argument C! CALL F(...,TPK) C! CALL JAC(...,TPK) C! Look for *UPG*MNH C! C! C! C! C! C============================================================================== C BEGIN ORIGINAL FORTRAN77 CODE C============================================================================== CDECK SVODE SUBROUTINE SVODE (F, NEQ, Y, T, TOUT, ITOL, RTOL, ATOL, ITASK, 1 ISTATE, IOPT, RWORK, LRW, IWORK, LIW, JAC, MF, 2 RPAR, IPAR, KMI, KINDEX) C C EXTERNAL F, JAC ! C C*UPG*MNH C INTEGER KMI, KINDEX C C*UPG*MNH C REAL Y, T, TOUT, RTOL, ATOL, RWORK, RPAR INTEGER NEQ, ITOL, ITASK, ISTATE, IOPT, LRW, IWORK, LIW, 1 MF, IPAR DIMENSION Y(*), RTOL(*), ATOL(*), RWORK(LRW), IWORK(LIW), 1 RPAR(*), IPAR(*) C----------------------------------------------------------------------- C SVODE.. Variable-coefficient Ordinary Differential Equation solver, C with fixed-leading coefficient implementation. C This version is in single precision. C C SVODE solves the initial value problem for stiff or nonstiff C systems of first order ODEs, C dy/dt = f(t,y) , or, in component form, C dy(i)/dt = f(i) = f(i,t,y(1),y(2),...,y(NEQ)) (i = 1,...,NEQ). C SVODE is a package based on the EPISODE and EPISODEB packages, and C on the ODEPACK user interface standard, with minor modifications. C----------------------------------------------------------------------- C Revision History (YYMMDD) C 890615 Date Written C 890922 Added interrupt/restart ability, minor changes throughout. C 910228 Minor revisions in line format, prologue, etc. C 920227 Modifications by D. Pang: C (1) Applied subgennam to get generic intrinsic names. C (2) Changed intrinsic names to generic in comments. C (3) Added *DECK lines before each routine. C 920721 Names of routines and labeled Common blocks changed, so as C to be unique in combined single/double precision code (ACH). C 920722 Minor revisions to prologue (ACH). C----------------------------------------------------------------------- C References.. C C 1. P. N. Brown, G. D. Byrne, and A. C. Hindmarsh, "VODE: A Variable C Coefficient ODE Solver," SIAM J. Sci. Stat. Comput., 10 (1989), C pp. 1038-1051. Also, LLNL Report UCRL-98412, June 1988. C 2. G. D. Byrne and A. C. Hindmarsh, "A Polyalgorithm for the C Numerical Solution of Ordinary Differential Equations," C ACM Trans. Math. Software, 1 (1975), pp. 71-96. C 3. A. C. Hindmarsh and G. D. Byrne, "EPISODE: An Effective Package C for the Integration of Systems of Ordinary Differential C Equations," LLNL Report UCID-30112, Rev. 1, April 1977. C 4. G. D. Byrne and A. C. Hindmarsh, "EPISODEB: An Experimental C Package for the Integration of Systems of Ordinary Differential C Equations with Banded Jacobians," LLNL Report UCID-30132, April C 1976. C 5. A. C. Hindmarsh, "ODEPACK, a Systematized Collection of ODE C Solvers," in Scientific Computing, R. S. Stepleman et al., eds., C North-Holland, Amsterdam, 1983, pp. 55-64. C 6. K. R. Jackson and R. Sacks-Davis, "An Alternative Implementation C of Variable Step-Size Multistep Formulas for Stiff ODEs," ACM C Trans. Math. Software, 6 (1980), pp. 295-318. C----------------------------------------------------------------------- C Authors.. C C Peter N. Brown and Alan C. Hindmarsh C Computing and Mathematics Research Division, L-316 C Lawrence Livermore National Laboratory C Livermore, CA 94550 C and C George D. Byrne C Exxon Research and Engineering Co. C Clinton Township C Route 22 East C Annandale, NJ 08801 C----------------------------------------------------------------------- C Summary of usage. C C Communication between the user and the SVODE package, for normal C situations, is summarized here. This summary describes only a subset C of the full set of options available. See the full description for C details, including optional communication, nonstandard options, C and instructions for special situations. See also the example C problem (with program and output) following this summary. C C A. First provide a subroutine of the form.. C C SUBROUTINE F (NEQ, T, Y, YDOT, RPAR, IPAR) C REAL T, Y, YDOT, RPAR C DIMENSION Y(NEQ), YDOT(NEQ) C C which supplies the vector function f by loading YDOT(i) with f(i). C C B. Next determine (or guess) whether or not the problem is stiff. C Stiffness occurs when the Jacobian matrix df/dy has an eigenvalue C whose real part is negative and large in magnitude, compared to the C reciprocal of the t span of interest. If the problem is nonstiff, C use a method flag MF = 10. If it is stiff, there are four standard C choices for MF (21, 22, 24, 25), and SVODE requires the Jacobian C matrix in some form. In these cases (MF .gt. 0), SVODE will use a C saved copy of the Jacobian matrix. If this is undesirable because of C storage limitations, set MF to the corresponding negative value C (-21, -22, -24, -25). (See full description of MF below.) C The Jacobian matrix is regarded either as full (MF = 21 or 22), C or banded (MF = 24 or 25). In the banded case, SVODE requires two C half-bandwidth parameters ML and MU. These are, respectively, the C widths of the lower and upper parts of the band, excluding the main C diagonal. Thus the band consists of the locations (i,j) with C i-ML .le. j .le. i+MU, and the full bandwidth is ML+MU+1. C C C. If the problem is stiff, you are encouraged to supply the Jacobian C directly (MF = 21 or 24), but if this is not feasible, SVODE will C compute it internally by difference quotients (MF = 22 or 25). C If you are supplying the Jacobian, provide a subroutine of the form.. C C SUBROUTINE JAC (NEQ, T, Y, ML, MU, PD, NROWPD, RPAR, IPAR) C REAL T, Y, PD, RPAR C DIMENSION Y(NEQ), PD(NROWPD,NEQ) C C which supplies df/dy by loading PD as follows.. C For a full Jacobian (MF = 21), load PD(i,j) with df(i)/dy(j), C the partial derivative of f(i) with respect to y(j). (Ignore the C ML and MU arguments in this case.) C For a banded Jacobian (MF = 24), load PD(i-j+MU+1,j) with C df(i)/dy(j), i.e. load the diagonal lines of df/dy into the rows of C PD from the top down. C In either case, only nonzero elements need be loaded. C C D. Write a main program which calls subroutine SVODE once for C each point at which answers are desired. This should also provide C for possible use of logical unit 6 for output of error messages C by SVODE. On the first call to SVODE, supply arguments as follows.. C F = Name of subroutine for right-hand side vector f. C This name must be declared external in calling program. C NEQ = Number of first order ODE-s. C Y = Array of initial values, of length NEQ. C T = The initial value of the independent variable. C TOUT = First point where output is desired (.ne. T). C ITOL = 1 or 2 according as ATOL (below) is a scalar or array. C RTOL = Relative tolerance parameter (scalar). C ATOL = Absolute tolerance parameter (scalar or array). C The estimated local error in Y(i) will be controlled so as C to be roughly less (in magnitude) than C EWT(i) = RTOL*abs(Y(i)) + ATOL if ITOL = 1, or C EWT(i) = RTOL*abs(Y(i)) + ATOL(i) if ITOL = 2. C Thus the local error test passes if, in each component, C either the absolute error is less than ATOL (or ATOL(i)), C or the relative error is less than RTOL. C Use RTOL = 0.0 for pure absolute error control, and C use ATOL = 0.0 (or ATOL(i) = 0.0) for pure relative error C control. Caution.. Actual (global) errors may exceed these C local tolerances, so choose them conservatively. C ITASK = 1 for normal computation of output values of Y at t = TOUT. C ISTATE = Integer flag (input and output). Set ISTATE = 1. C IOPT = 0 to indicate no optional input used. C RWORK = Real work array of length at least.. C 20 + 16*NEQ for MF = 10, C 22 + 9*NEQ + 2*NEQ**2 for MF = 21 or 22, C 22 + 11*NEQ + (3*ML + 2*MU)*NEQ for MF = 24 or 25. C LRW = Declared length of RWORK (in user's DIMENSION statement). C IWORK = Integer work array of length at least.. C 30 for MF = 10, C 30 + NEQ for MF = 21, 22, 24, or 25. C If MF = 24 or 25, input in IWORK(1),IWORK(2) the lower C and upper half-bandwidths ML,MU. C LIW = Declared length of IWORK (in user's DIMENSION). C JAC = Name of subroutine for Jacobian matrix (MF = 21 or 24). C If used, this name must be declared external in calling C program. If not used, pass a dummy name. C MF = Method flag. Standard values are.. C 10 for nonstiff (Adams) method, no Jacobian used. C 21 for stiff (BDF) method, user-supplied full Jacobian. C 22 for stiff method, internally generated full Jacobian. C 24 for stiff method, user-supplied banded Jacobian. C 25 for stiff method, internally generated banded Jacobian. C RPAR,IPAR = user-defined real and integer arrays passed to F and JAC. C Note that the main program must declare arrays Y, RWORK, IWORK, C and possibly ATOL, RPAR, and IPAR. C C E. The output from the first call (or any call) is.. C Y = Array of computed values of y(t) vector. C T = Corresponding value of independent variable (normally TOUT). C ISTATE = 2 if SVODE was successful, negative otherwise. C -1 means excess work done on this call. (Perhaps wrong MF.) C -2 means excess accuracy requested. (Tolerances too small.) C -3 means illegal input detected. (See printed message.) C -4 means repeated error test failures. (Check all input.) C -5 means repeated convergence failures. (Perhaps bad C Jacobian supplied or wrong choice of MF or tolerances.) C -6 means error weight became zero during problem. (Solution C component i vanished, and ATOL or ATOL(i) = 0.) C C F. To continue the integration after a successful return, simply C reset TOUT and call SVODE again. No other parameters need be reset. C C----------------------------------------------------------------------- C EXAMPLE PROBLEM C C The following is a simple example problem, with the coding C needed for its solution by SVODE. The problem is from chemical C kinetics, and consists of the following three rate equations.. C dy1/dt = -.04*y1 + 1.e4*y2*y3 C dy2/dt = .04*y1 - 1.e4*y2*y3 - 3.e7*y2**2 C dy3/dt = 3.e7*y2**2 C on the interval from t = 0.0 to t = 4.e10, with initial conditions C y1 = 1.0, y2 = y3 = 0. The problem is stiff. C C The following coding solves this problem with SVODE, using MF = 21 C and printing results at t = .4, 4., ..., 4.e10. It uses C ITOL = 2 and ATOL much smaller for y2 than y1 or y3 because C y2 has much smaller values. C At the end of the run, statistical quantities of interest are C printed. (See optional output in the full description below.) C To generate Fortran source code, replace C in column 1 with a blank C in the coding below. C C EXTERNAL FEX, JEX C REAL ATOL, RPAR, RTOL, RWORK, T, TOUT, Y C DIMENSION Y(3), ATOL(3), RWORK(67), IWORK(33) C NEQ = 3 C Y(1) = 1.0E0 C Y(2) = 0.0E0 C Y(3) = 0.0E0 C T = 0.0E0 C TOUT = 0.4E0 C ITOL = 2 C RTOL = 1.E-4 C ATOL(1) = 1.E-8 C ATOL(2) = 1.E-14 C ATOL(3) = 1.E-6 C ITASK = 1 C ISTATE = 1 C IOPT = 0 C LRW = 67 C LIW = 33 C MF = 21 C DO 40 IOUT = 1,12 C CALL SVODE(FEX,NEQ,Y,T,TOUT,ITOL,RTOL,ATOL,ITASK,ISTATE, C 1 IOPT,RWORK,LRW,IWORK,LIW,JEX,MF,RPAR,IPAR) C WRITE(6,20)T,Y(1),Y(2),Y(3) C 20 FORMAT(' At t =',E12.4,' y =',3E14.6) C IF (ISTATE .LT. 0) GO TO 80 C 40 TOUT = TOUT*10. C WRITE(6,60) IWORK(11),IWORK(12),IWORK(13),IWORK(19), C 1 IWORK(20),IWORK(21),IWORK(22) C 60 FORMAT(/' No. steps =',I4,' No. f-s =',I4, C 1 ' No. J-s =',I4,' No. LU-s =',I4/ C 2 ' No. nonlinear iterations =',I4/ C 3 ' No. nonlinear convergence failures =',I4/ C 4 ' No. error test failures =',I4/) C STOP C 80 WRITE(6,90)ISTATE C 90 FORMAT(///' Error halt.. ISTATE =',I3) C STOP C END C C SUBROUTINE FEX (NEQ, T, Y, YDOT, RPAR, IPAR) C REAL RPAR, T, Y, YDOT C DIMENSION Y(NEQ), YDOT(NEQ) C YDOT(1) = -.04E0*Y(1) + 1.E4*Y(2)*Y(3) C YDOT(3) = 3.E7*Y(2)*Y(2) C YDOT(2) = -YDOT(1) - YDOT(3) C RETURN C END C C SUBROUTINE JEX (NEQ, T, Y, ML, MU, PD, NRPD, RPAR, IPAR) C REAL PD, RPAR, T, Y C DIMENSION Y(NEQ), PD(NRPD,NEQ) C PD(1,1) = -.04E0 C PD(1,2) = 1.E4*Y(3) C PD(1,3) = 1.E4*Y(2) C PD(2,1) = .04E0 C PD(2,3) = -PD(1,3) C PD(3,2) = 6.E7*Y(2) C PD(2,2) = -PD(1,2) - PD(3,2) C RETURN C END C C The following output was obtained from the above program on a C Cray-1 computer with the CFT compiler. C C At t = 4.0000e-01 y = 9.851680e-01 3.386314e-05 1.479817e-02 C At t = 4.0000e+00 y = 9.055255e-01 2.240539e-05 9.445214e-02 C At t = 4.0000e+01 y = 7.158108e-01 9.184883e-06 2.841800e-01 C At t = 4.0000e+02 y = 4.505032e-01 3.222940e-06 5.494936e-01 C At t = 4.0000e+03 y = 1.832053e-01 8.942690e-07 8.167938e-01 C At t = 4.0000e+04 y = 3.898560e-02 1.621875e-07 9.610142e-01 C At t = 4.0000e+05 y = 4.935882e-03 1.984013e-08 9.950641e-01 C At t = 4.0000e+06 y = 5.166183e-04 2.067528e-09 9.994834e-01 C At t = 4.0000e+07 y = 5.201214e-05 2.080593e-10 9.999480e-01 C At t = 4.0000e+08 y = 5.213149e-06 2.085271e-11 9.999948e-01 C At t = 4.0000e+09 y = 5.183495e-07 2.073399e-12 9.999995e-01 C At t = 4.0000e+10 y = 5.450996e-08 2.180399e-13 9.999999e-01 C C No. steps = 595 No. f-s = 832 No. J-s = 13 No. LU-s = 112 C No. nonlinear iterations = 831 C No. nonlinear convergence failures = 0 C No. error test failures = 22 C----------------------------------------------------------------------- C Full description of user interface to SVODE. C C The user interface to SVODE consists of the following parts. C C i. The call sequence to subroutine SVODE, which is a driver C routine for the solver. This includes descriptions of both C the call sequence arguments and of user-supplied routines. C Following these descriptions is C * a description of optional input available through the C call sequence, C * a description of optional output (in the work arrays), and C * instructions for interrupting and restarting a solution. C C ii. Descriptions of other routines in the SVODE package that may be C (optionally) called by the user. These provide the ability to C alter error message handling, save and restore the internal C COMMON, and obtain specified derivatives of the solution y(t). C C iii. Descriptions of COMMON blocks to be declared in overlay C or similar environments. C C iv. Description of two routines in the SVODE package, either of C which the user may replace with his own version, if desired. C these relate to the measurement of errors. C C----------------------------------------------------------------------- C Part i. Call Sequence. C C The call sequence parameters used for input only are C F, NEQ, TOUT, ITOL, RTOL, ATOL, ITASK, IOPT, LRW, LIW, JAC, MF, C and those used for both input and output are C Y, T, ISTATE. C The work arrays RWORK and IWORK are also used for conditional and C optional input and optional output. (The term output here refers C to the return from subroutine SVODE to the user's calling program.) C C The legality of input parameters will be thoroughly checked on the C initial call for the problem, but not checked thereafter unless a C change in input parameters is flagged by ISTATE = 3 in the input. C C The descriptions of the call arguments are as follows. C C F = The name of the user-supplied subroutine defining the C ODE system. The system must be put in the first-order C form dy/dt = f(t,y), where f is a vector-valued function C of the scalar t and the vector y. Subroutine F is to C compute the function f. It is to have the form C SUBROUTINE F (NEQ, T, Y, YDOT, RPAR, IPAR) C REAL T, Y, YDOT, RPAR C DIMENSION Y(NEQ), YDOT(NEQ) C where NEQ, T, and Y are input, and the array YDOT = f(t,y) C is output. Y and YDOT are arrays of length NEQ. C (In the DIMENSION statement above, NEQ can be replaced by C * to make Y and YDOT assumed size arrays.) C Subroutine F should not alter Y(1),...,Y(NEQ). C F must be declared EXTERNAL in the calling program. C C Subroutine F may access user-defined real and integer C work arrays RPAR and IPAR, which are to be dimensioned C in the main program. C C If quantities computed in the F routine are needed C externally to SVODE, an extra call to F should be made C for this purpose, for consistent and accurate results. C If only the derivative dy/dt is needed, use SVINDY instead. C C NEQ = The size of the ODE system (number of first order C ordinary differential equations). Used only for input. C NEQ may not be increased during the problem, but C can be decreased (with ISTATE = 3 in the input). C C Y = A real array for the vector of dependent variables, of C length NEQ or more. Used for both input and output on the C first call (ISTATE = 1), and only for output on other calls. C On the first call, Y must contain the vector of initial C values. In the output, Y contains the computed solution C evaluated at T. If desired, the Y array may be used C for other purposes between calls to the solver. C C This array is passed as the Y argument in all calls to C F and JAC. C C T = The independent variable. In the input, T is used only on C the first call, as the initial point of the integration. C In the output, after each call, T is the value at which a C computed solution Y is evaluated (usually the same as TOUT). C On an error return, T is the farthest point reached. C C TOUT = The next value of t at which a computed solution is desired. C Used only for input. C C When starting the problem (ISTATE = 1), TOUT may be equal C to T for one call, then should .ne. T for the next call. C For the initial T, an input value of TOUT .ne. T is used C in order to determine the direction of the integration C (i.e. the algebraic sign of the step sizes) and the rough C scale of the problem. Integration in either direction C (forward or backward in t) is permitted. C C If ITASK = 2 or 5 (one-step modes), TOUT is ignored after C the first call (i.e. the first call with TOUT .ne. T). C Otherwise, TOUT is required on every call. C C If ITASK = 1, 3, or 4, the values of TOUT need not be C monotone, but a value of TOUT which backs up is limited C to the current internal t interval, whose endpoints are C TCUR - HU and TCUR. (See optional output, below, for C TCUR and HU.) C C ITOL = An indicator for the type of error control. See C description below under ATOL. Used only for input. C C RTOL = A relative error tolerance parameter, either a scalar or C an array of length NEQ. See description below under ATOL. C Input only. C C ATOL = An absolute error tolerance parameter, either a scalar or C an array of length NEQ. Input only. C C The input parameters ITOL, RTOL, and ATOL determine C the error control performed by the solver. The solver will C control the vector e = (e(i)) of estimated local errors C in Y, according to an inequality of the form C rms-norm of ( e(i)/EWT(i) ) .le. 1, C where EWT(i) = RTOL(i)*abs(Y(i)) + ATOL(i), C and the rms-norm (root-mean-square norm) here is C rms-norm(v) = sqrt(sum v(i)**2 / NEQ). Here EWT = (EWT(i)) C is a vector of weights which must always be positive, and C the values of RTOL and ATOL should all be non-negative. C The following table gives the types (scalar/array) of C RTOL and ATOL, and the corresponding form of EWT(i). C C ITOL RTOL ATOL EWT(i) C 1 scalar scalar RTOL*ABS(Y(i)) + ATOL C 2 scalar array RTOL*ABS(Y(i)) + ATOL(i) C 3 array scalar RTOL(i)*ABS(Y(i)) + ATOL C 4 array array RTOL(i)*ABS(Y(i)) + ATOL(i) C C When either of these parameters is a scalar, it need not C be dimensioned in the user's calling program. C C If none of the above choices (with ITOL, RTOL, and ATOL C fixed throughout the problem) is suitable, more general C error controls can be obtained by substituting C user-supplied routines for the setting of EWT and/or for C the norm calculation. See Part iv below. C C If global errors are to be estimated by making a repeated C run on the same problem with smaller tolerances, then all C components of RTOL and ATOL (i.e. of EWT) should be scaled C down uniformly. C C ITASK = An index specifying the task to be performed. C Input only. ITASK has the following values and meanings. C 1 means normal computation of output values of y(t) at C t = TOUT (by overshooting and interpolating). C 2 means take one step only and return. C 3 means stop at the first internal mesh point at or C beyond t = TOUT and return. C 4 means normal computation of output values of y(t) at C t = TOUT but without overshooting t = TCRIT. C TCRIT must be input as RWORK(1). TCRIT may be equal to C or beyond TOUT, but not behind it in the direction of C integration. This option is useful if the problem C has a singularity at or beyond t = TCRIT. C 5 means take one step, without passing TCRIT, and return. C TCRIT must be input as RWORK(1). C C Note.. If ITASK = 4 or 5 and the solver reaches TCRIT C (within roundoff), it will return T = TCRIT (exactly) to C indicate this (unless ITASK = 4 and TOUT comes before TCRIT, C in which case answers at T = TOUT are returned first). C C ISTATE = an index used for input and output to specify the C the state of the calculation. C C In the input, the values of ISTATE are as follows. C 1 means this is the first call for the problem C (initializations will be done). See note below. C 2 means this is not the first call, and the calculation C is to continue normally, with no change in any input C parameters except possibly TOUT and ITASK. C (If ITOL, RTOL, and/or ATOL are changed between calls C with ISTATE = 2, the new values will be used but not C tested for legality.) C 3 means this is not the first call, and the C calculation is to continue normally, but with C a change in input parameters other than C TOUT and ITASK. Changes are allowed in C NEQ, ITOL, RTOL, ATOL, IOPT, LRW, LIW, MF, ML, MU, C and any of the optional input except H0. C (See IWORK description for ML and MU.) C Note.. A preliminary call with TOUT = T is not counted C as a first call here, as no initialization or checking of C input is done. (Such a call is sometimes useful to include C the initial conditions in the output.) C Thus the first call for which TOUT .ne. T requires C ISTATE = 1 in the input. C C In the output, ISTATE has the following values and meanings. C 1 means nothing was done, as TOUT was equal to T with C ISTATE = 1 in the input. C 2 means the integration was performed successfully. C -1 means an excessive amount of work (more than MXSTEP C steps) was done on this call, before completing the C requested task, but the integration was otherwise C successful as far as T. (MXSTEP is an optional input C and is normally 500.) To continue, the user may C simply reset ISTATE to a value .gt. 1 and call again. C (The excess work step counter will be reset to 0.) C In addition, the user may increase MXSTEP to avoid C this error return. (See optional input below.) C -2 means too much accuracy was requested for the precision C of the machine being used. This was detected before C completing the requested task, but the integration C was successful as far as T. To continue, the tolerance C parameters must be reset, and ISTATE must be set C to 3. The optional output TOLSF may be used for this C purpose. (Note.. If this condition is detected before C taking any steps, then an illegal input return C (ISTATE = -3) occurs instead.) C -3 means illegal input was detected, before taking any C integration steps. See written message for details. C Note.. If the solver detects an infinite loop of calls C to the solver with illegal input, it will cause C the run to stop. C -4 means there were repeated error test failures on C one attempted step, before completing the requested C task, but the integration was successful as far as T. C The problem may have a singularity, or the input C may be inappropriate. C -5 means there were repeated convergence test failures on C one attempted step, before completing the requested C task, but the integration was successful as far as T. C This may be caused by an inaccurate Jacobian matrix, C if one is being used. C -6 means EWT(i) became zero for some i during the C integration. Pure relative error control (ATOL(i)=0.0) C was requested on a variable which has now vanished. C The integration was successful as far as T. C C Note.. Since the normal output value of ISTATE is 2, C it does not need to be reset for normal continuation. C Also, since a negative input value of ISTATE will be C regarded as illegal, a negative output value requires the C user to change it, and possibly other input, before C calling the solver again. C C IOPT = An integer flag to specify whether or not any optional C input is being used on this call. Input only. C The optional input is listed separately below. C IOPT = 0 means no optional input is being used. C Default values will be used in all cases. C IOPT = 1 means optional input is being used. C C RWORK = A real working array (single precision). C The length of RWORK must be at least C 20 + NYH*(MAXORD + 1) + 3*NEQ + LWM where C NYH = the initial value of NEQ, C MAXORD = 12 (if METH = 1) or 5 (if METH = 2) (unless a C smaller value is given as an optional input), C LWM = length of work space for matrix-related data.. C LWM = 0 if MITER = 0, C LWM = 2*NEQ**2 + 2 if MITER = 1 or 2, and MF.gt.0, C LWM = NEQ**2 + 2 if MITER = 1 or 2, and MF.lt.0, C LWM = NEQ + 2 if MITER = 3, C LWM = (3*ML+2*MU+2)*NEQ + 2 if MITER = 4 or 5, and MF.gt.0, C LWM = (2*ML+MU+1)*NEQ + 2 if MITER = 4 or 5, and MF.lt.0. C (See the MF description for METH and MITER.) C Thus if MAXORD has its default value and NEQ is constant, C this length is.. C 20 + 16*NEQ for MF = 10, C 22 + 16*NEQ + 2*NEQ**2 for MF = 11 or 12, C 22 + 16*NEQ + NEQ**2 for MF = -11 or -12, C 22 + 17*NEQ for MF = 13, C 22 + 18*NEQ + (3*ML+2*MU)*NEQ for MF = 14 or 15, C 22 + 17*NEQ + (2*ML+MU)*NEQ for MF = -14 or -15, C 20 + 9*NEQ for MF = 20, C 22 + 9*NEQ + 2*NEQ**2 for MF = 21 or 22, C 22 + 9*NEQ + NEQ**2 for MF = -21 or -22, C 22 + 10*NEQ for MF = 23, C 22 + 11*NEQ + (3*ML+2*MU)*NEQ for MF = 24 or 25. C 22 + 10*NEQ + (2*ML+MU)*NEQ for MF = -24 or -25. C The first 20 words of RWORK are reserved for conditional C and optional output. C C The following word in RWORK is a conditional input.. C RWORK(1) = TCRIT = critical value of t which the solver C is not to overshoot. Required if ITASK is C 4 or 5, and ignored otherwise. (See ITASK.) C C LRW = The length of the array RWORK, as declared by the user. C (This will be checked by the solver.) C C IWORK = An integer work array. The length of IWORK must be at least C 30 if MITER = 0 or 3 (MF = 10, 13, 20, 23), or C 30 + NEQ otherwise (abs(MF) = 11,12,14,15,21,22,24,25). C The first 30 words of IWORK are reserved for conditional and C optional input and optional output. C C The following 2 words in IWORK are conditional input.. C IWORK(1) = ML These are the lower and upper C IWORK(2) = MU half-bandwidths, respectively, of the C banded Jacobian, excluding the main diagonal. C The band is defined by the matrix locations C (i,j) with i-ML .le. j .le. i+MU. ML and MU C must satisfy 0 .le. ML,MU .le. NEQ-1. C These are required if MITER is 4 or 5, and C ignored otherwise. ML and MU may in fact be C the band parameters for a matrix to which C df/dy is only approximately equal. C C LIW = the length of the array IWORK, as declared by the user. C (This will be checked by the solver.) C C Note.. The work arrays must not be altered between calls to SVODE C for the same problem, except possibly for the conditional and C optional input, and except for the last 3*NEQ words of RWORK. C The latter space is used for internal scratch space, and so is C available for use by the user outside SVODE between calls, if C desired (but not for use by F or JAC). C C JAC = The name of the user-supplied routine (MITER = 1 or 4) to C compute the Jacobian matrix, df/dy, as a function of C the scalar t and the vector y. It is to have the form C SUBROUTINE JAC (NEQ, T, Y, ML, MU, PD, NROWPD, C RPAR, IPAR) C REAL T, Y, PD, RPAR C DIMENSION Y(NEQ), PD(NROWPD, NEQ) C where NEQ, T, Y, ML, MU, and NROWPD are input and the array C PD is to be loaded with partial derivatives (elements of the C Jacobian matrix) in the output. PD must be given a first C dimension of NROWPD. T and Y have the same meaning as in C Subroutine F. (In the DIMENSION statement above, NEQ can C be replaced by * to make Y and PD assumed size arrays.) C In the full matrix case (MITER = 1), ML and MU are C ignored, and the Jacobian is to be loaded into PD in C columnwise manner, with df(i)/dy(j) loaded into PD(i,j). C In the band matrix case (MITER = 4), the elements C within the band are to be loaded into PD in columnwise C manner, with diagonal lines of df/dy loaded into the rows C of PD. Thus df(i)/dy(j) is to be loaded into PD(i-j+MU+1,j). C ML and MU are the half-bandwidth parameters. (See IWORK). C The locations in PD in the two triangular areas which C correspond to nonexistent matrix elements can be ignored C or loaded arbitrarily, as they are overwritten by SVODE. C JAC need not provide df/dy exactly. A crude C approximation (possibly with a smaller bandwidth) will do. C In either case, PD is preset to zero by the solver, C so that only the nonzero elements need be loaded by JAC. C Each call to JAC is preceded by a call to F with the same C arguments NEQ, T, and Y. Thus to gain some efficiency, C intermediate quantities shared by both calculations may be C saved in a user COMMON block by F and not recomputed by JAC, C if desired. Also, JAC may alter the Y array, if desired. C JAC must be declared external in the calling program. C Subroutine JAC may access user-defined real and integer C work arrays, RPAR and IPAR, whose dimensions are set by the C user in the main program. C C MF = The method flag. Used only for input. The legal values of C MF are 10, 11, 12, 13, 14, 15, 20, 21, 22, 23, 24, 25, C -11, -12, -14, -15, -21, -22, -24, -25. C MF is a signed two-digit integer, MF = JSV*(10*METH + MITER). C JSV = SIGN(MF) indicates the Jacobian-saving strategy.. C JSV = 1 means a copy of the Jacobian is saved for reuse C in the corrector iteration algorithm. C JSV = -1 means a copy of the Jacobian is not saved C (valid only for MITER = 1, 2, 4, or 5). C METH indicates the basic linear multistep method.. C METH = 1 means the implicit Adams method. C METH = 2 means the method based on backward C differentiation formulas (BDF-s). C MITER indicates the corrector iteration method.. C MITER = 0 means functional iteration (no Jacobian matrix C is involved). C MITER = 1 means chord iteration with a user-supplied C full (NEQ by NEQ) Jacobian. C MITER = 2 means chord iteration with an internally C generated (difference quotient) full Jacobian C (using NEQ extra calls to F per df/dy value). C MITER = 3 means chord iteration with an internally C generated diagonal Jacobian approximation C (using 1 extra call to F per df/dy evaluation). C MITER = 4 means chord iteration with a user-supplied C banded Jacobian. C MITER = 5 means chord iteration with an internally C generated banded Jacobian (using ML+MU+1 extra C calls to F per df/dy evaluation). C If MITER = 1 or 4, the user must supply a subroutine JAC C (the name is arbitrary) as described above under JAC. C For other values of MITER, a dummy argument can be used. C C RPAR User-specified array used to communicate real parameters C to user-supplied subroutines. If RPAR is a vector, then C it must be dimensioned in the user's main program. If it C is unused or it is a scalar, then it need not be C dimensioned. C C IPAR User-specified array used to communicate integer parameter C to user-supplied subroutines. The comments on dimensioning C RPAR apply to IPAR. C----------------------------------------------------------------------- C Optional Input. C C The following is a list of the optional input provided for in the C call sequence. (See also Part ii.) For each such input variable, C this table lists its name as used in this documentation, its C location in the call sequence, its meaning, and the default value. C The use of any of this input requires IOPT = 1, and in that C case all of this input is examined. A value of zero for any C of these optional input variables will cause the default value to be C used. Thus to use a subset of the optional input, simply preload C locations 5 to 10 in RWORK and IWORK to 0.0 and 0 respectively, and C then set those of interest to nonzero values. C C NAME LOCATION MEANING AND DEFAULT VALUE C C H0 RWORK(5) The step size to be attempted on the first step. C The default value is determined by the solver. C C HMAX RWORK(6) The maximum absolute step size allowed. C The default value is infinite. C C HMIN RWORK(7) The minimum absolute step size allowed. C The default value is 0. (This lower bound is not C enforced on the final step before reaching TCRIT C when ITASK = 4 or 5.) C C MAXORD IWORK(5) The maximum order to be allowed. The default C value is 12 if METH = 1, and 5 if METH = 2. C If MAXORD exceeds the default value, it will C be reduced to the default value. C If MAXORD is changed during the problem, it may C cause the current order to be reduced. C C MXSTEP IWORK(6) Maximum number of (internally defined) steps C allowed during one call to the solver. C The default value is 500. C C MXHNIL IWORK(7) Maximum number of messages printed (per problem) C warning that T + H = T on a step (H = step size). C This must be positive to result in a non-default C value. The default value is 10. C C----------------------------------------------------------------------- C Optional Output. C C As optional additional output from SVODE, the variables listed C below are quantities related to the performance of SVODE C which are available to the user. These are communicated by way of C the work arrays, but also have internal mnemonic names as shown. C Except where stated otherwise, all of this output is defined C on any successful return from SVODE, and on any return with C ISTATE = -1, -2, -4, -5, or -6. On an illegal input return C (ISTATE = -3), they will be unchanged from their existing values C (if any), except possibly for TOLSF, LENRW, and LENIW. C On any error return, output relevant to the error will be defined, C as noted below. C C NAME LOCATION MEANING C C HU RWORK(11) The step size in t last used (successfully). C C HCUR RWORK(12) The step size to be attempted on the next step. C C TCUR RWORK(13) The current value of the independent variable C which the solver has actually reached, i.e. the C current internal mesh point in t. In the output, C TCUR will always be at least as far from the C initial value of t as the current argument T, C but may be farther (if interpolation was done). C C TOLSF RWORK(14) A tolerance scale factor, greater than 1.0, C computed when a request for too much accuracy was C detected (ISTATE = -3 if detected at the start of C the problem, ISTATE = -2 otherwise). If ITOL is C left unaltered but RTOL and ATOL are uniformly C scaled up by a factor of TOLSF for the next call, C then the solver is deemed likely to succeed. C (The user may also ignore TOLSF and alter the C tolerance parameters in any other way appropriate.) C C NST IWORK(11) The number of steps taken for the problem so far. C C NFE IWORK(12) The number of f evaluations for the problem so far. C C NJE IWORK(13) The number of Jacobian evaluations so far. C C NQU IWORK(14) The method order last used (successfully). C C NQCUR IWORK(15) The order to be attempted on the next step. C C IMXER IWORK(16) The index of the component of largest magnitude in C the weighted local error vector ( e(i)/EWT(i) ), C on an error return with ISTATE = -4 or -5. C C LENRW IWORK(17) The length of RWORK actually required. C This is defined on normal returns and on an illegal C input return for insufficient storage. C C LENIW IWORK(18) The length of IWORK actually required. C This is defined on normal returns and on an illegal C input return for insufficient storage. C C NLU IWORK(19) The number of matrix LU decompositions so far. C C NNI IWORK(20) The number of nonlinear (Newton) iterations so far. C C NCFN IWORK(21) The number of convergence failures of the nonlinear C solver so far. C C NETF IWORK(22) The number of error test failures of the integrator C so far. C C The following two arrays are segments of the RWORK array which C may also be of interest to the user as optional output. C For each array, the table below gives its internal name, C its base address in RWORK, and its description. C C NAME BASE ADDRESS DESCRIPTION C C YH 21 The Nordsieck history array, of size NYH by C (NQCUR + 1), where NYH is the initial value C of NEQ. For j = 0,1,...,NQCUR, column j+1 C of YH contains HCUR**j/factorial(j) times C the j-th derivative of the interpolating C polynomial currently representing the C solution, evaluated at t = TCUR. C C ACOR LENRW-NEQ+1 Array of size NEQ used for the accumulated C corrections on each step, scaled in the output C to represent the estimated local error in Y C on the last step. This is the vector e in C the description of the error control. It is C defined only on a successful return from SVODE. C C----------------------------------------------------------------------- C Interrupting and Restarting C C If the integration of a given problem by SVODE is to be C interrrupted and then later continued, such as when restarting C an interrupted run or alternating between two or more ODE problems, C the user should save, following the return from the last SVODE call C prior to the interruption, the contents of the call sequence C variables and internal COMMON blocks, and later restore these C values before the next SVODE call for that problem. To save C and restore the COMMON blocks, use subroutine SVSRCO, as C described below in part ii. C C In addition, if non-default values for either LUN or MFLAG are C desired, an extra call to XSETUN and/or XSETF should be made just C before continuing the integration. See Part ii below for details. C C----------------------------------------------------------------------- C Part ii. Other Routines Callable. C C The following are optional calls which the user may make to C gain additional capabilities in conjunction with SVODE. C (The routines XSETUN and XSETF are designed to conform to the C SLATEC error handling package.) C C FORM OF CALL FUNCTION C CALL XSETUN(LUN) Set the logical unit number, LUN, for C output of messages from SVODE, if C the default is not desired. C The default value of LUN is 6. C C CALL XSETF(MFLAG) Set a flag to control the printing of C messages by SVODE. C MFLAG = 0 means do not print. (Danger.. C This risks losing valuable information.) C MFLAG = 1 means print (the default). C C Either of the above calls may be made at C any time and will take effect immediately. C C CALL SVSRCO(RSAV,ISAV,JOB) Saves and restores the contents of C the internal COMMON blocks used by C SVODE. (See Part iii below.) C RSAV must be a real array of length 49 C or more, and ISAV must be an integer C array of length 40 or more. C JOB=1 means save COMMON into RSAV/ISAV. C JOB=2 means restore COMMON from RSAV/ISAV. C SVSRCO is useful if one is C interrupting a run and restarting C later, or alternating between two or C more problems solved with SVODE. C C CALL SVINDY(,,,,,) Provide derivatives of y, of various C (See below.) orders, at a specified point T, if C desired. It may be called only after C a successful return from SVODE. C C The detailed instructions for using SVINDY are as follows. C The form of the call is.. C C CALL SVINDY (T, K, RWORK(21), NYH, DKY, IFLAG) C C The input parameters are.. C C T = Value of independent variable where answers are desired C (normally the same as the T last returned by SVODE). C For valid results, T must lie between TCUR - HU and TCUR. C (See optional output for TCUR and HU.) C K = Integer order of the derivative desired. K must satisfy C 0 .le. K .le. NQCUR, where NQCUR is the current order C (see optional output). The capability corresponding C to K = 0, i.e. computing y(T), is already provided C by SVODE directly. Since NQCUR .ge. 1, the first C derivative dy/dt is always available with SVINDY. C RWORK(21) = The base address of the history array YH. C NYH = Column length of YH, equal to the initial value of NEQ. C C The output parameters are.. C C DKY = A real array of length NEQ containing the computed value C of the K-th derivative of y(t). C IFLAG = Integer flag, returned as 0 if K and T were legal, C -1 if K was illegal, and -2 if T was illegal. C On an error return, a message is also written. C----------------------------------------------------------------------- C Part iii. COMMON Blocks. C If SVODE is to be used in an overlay situation, the user C must declare, in the primary overlay, the variables in.. C (1) the call sequence to SVODE, C (2) the two internal COMMON blocks C /SVOD01/ of length 81 (48 single precision words C followed by 33 integer words), C /SVOD02/ of length 9 (1 single precision word C followed by 8 integer words), C C If SVODE is used on a system in which the contents of internal C COMMON blocks are not preserved between calls, the user should C declare the above two COMMON blocks in his main program to insure C that their contents are preserved. C C----------------------------------------------------------------------- C Part iv. Optionally Replaceable Solver Routines. C C Below are descriptions of two routines in the SVODE package which C relate to the measurement of errors. Either routine can be C replaced by a user-supplied version, if desired. However, since such C a replacement may have a major impact on performance, it should be C done only when absolutely necessary, and only with great caution. C (Note.. The means by which the package version of a routine is C superseded by the user's version may be system-dependent.) C C (a) SEWSET. C The following subroutine is called just before each internal C integration step, and sets the array of error weights, EWT, as C described under ITOL/RTOL/ATOL above.. C SUBROUTINE SEWSET (NEQ, ITOL, RTOL, ATOL, YCUR, EWT) C where NEQ, ITOL, RTOL, and ATOL are as in the SVODE call sequence, C YCUR contains the current dependent variable vector, and C EWT is the array of weights set by SEWSET. C C If the user supplies this subroutine, it must return in EWT(i) C (i = 1,...,NEQ) a positive quantity suitable for comparison with C errors in Y(i). The EWT array returned by SEWSET is passed to the C SVNORM routine (See below.), and also used by SVODE in the computation C of the optional output IMXER, the diagonal Jacobian approximation, C and the increments for difference quotient Jacobians. C C In the user-supplied version of SEWSET, it may be desirable to use C the current values of derivatives of y. Derivatives up to order NQ C are available from the history array YH, described above under C Optional Output. In SEWSET, YH is identical to the YCUR array, C extended to NQ + 1 columns with a column length of NYH and scale C factors of h**j/factorial(j). On the first call for the problem, C given by NST = 0, NQ is 1 and H is temporarily set to 1.0. C NYH is the initial value of NEQ. The quantities NQ, H, and NST C can be obtained by including in SEWSET the statements.. C REAL RVOD, H, HU C COMMON /SVOD01/ RVOD(48), IVOD(33) C COMMON /SVOD02/ HU, NCFN, NETF, NFE, NJE, NLU, NNI, NQU, NST C NQ = IVOD(28) C H = RVOD(21) C Thus, for example, the current value of dy/dt can be obtained as C YCUR(NYH+i)/H (i=1,...,NEQ) (and the division by H is C unnecessary when NST = 0). C C (b) SVNORM. C The following is a real function routine which computes the weighted C root-mean-square norm of a vector v.. C D = SVNORM (N, V, W) C where.. C N = the length of the vector, C V = real array of length N containing the vector, C W = real array of length N containing weights, C D = sqrt( (1/N) * sum(V(i)*W(i))**2 ). C SVNORM is called with N = NEQ and with W(i) = 1.0/EWT(i), where C EWT is as set by subroutine SEWSET. C C If the user supplies this function, it should return a non-negative C value of SVNORM suitable for use in the error control in SVODE. C None of the arguments should be altered by SVNORM. C For example, a user-supplied SVNORM routine might.. C -substitute a max-norm of (V(i)*W(i)) for the rms-norm, or C -ignore some components of V in the norm, with the effect of C suppressing the error control on those components of Y. C----------------------------------------------------------------------- C Other Routines in the SVODE Package. C C In addition to subroutine SVODE, the SVODE package includes the C following subroutines and function routines.. C SVHIN computes an approximate step size for the initial step. C SVINDY computes an interpolated value of the y vector at t = TOUT. C SVSTEP is the core integrator, which does one step of the C integration and the associated error control. C SVSET sets all method coefficients and test constants. C SVNLSD solves the underlying nonlinear system -- the corrector. C SVJAC computes and preprocesses the Jacobian matrix J = df/dy C and the Newton iteration matrix P = I - (h/l1)*J. C SVSOL manages solution of linear system in chord iteration. C SVJUST adjusts the history array on a change of order. C SEWSET sets the error weight vector EWT before each step. C SVNORM computes the weighted r.m.s. norm of a vector. C SVSRCO is a user-callable routines to save and restore C the contents of the internal COMMON blocks. C SACOPY is a routine to copy one two-dimensional array to another. C SGEFA and SGESL are routines from LINPACK for solving full C systems of linear algebraic equations. C SGBFA and SGBSL are routines from LINPACK for solving banded C linear systems. C SAXPY, SSCAL, and CH_SCOPY are basic linear algebra modules (BLAS). C R1MACH sets the unit roundoff of the machine. C XERRWV, XSETUN, XSETF, LUNSAV, and MFLGSV handle the printing of all C error messages and warnings. XERRWV is machine-dependent. C Note.. SVNORM, R1MACH, LUNSAV, and MFLGSV are function routines. C All the others are subroutines. C C The intrinsic and external routines used by the SVODE package are.. C ABS, MAX, MIN, REAL, SIGN, SQRT, and WRITE. C C----------------------------------------------------------------------- C C Type declarations for labeled COMMON block SVOD01 -------------------- C REAL ACNRM, CCMXJ, CONP, CRATE, DRC, EL, 1 ETA, ETAMAX, H, HMIN, HMXI, HNEW, HSCAL, PRL1, 2 RC, RL1, TAU, TQ, TN, UROUND INTEGER ICF, INIT, IPUP, JCUR, JSTART, JSV, KFLAG, KUTH, 1 L, LMAX, LYH, LEWT, LACOR, LSAVF, LWM, LIWM, 2 LOCJS, MAXORD, METH, MITER, MSBJ, MXHNIL, MXSTEP, 3 N, NEWH, NEWQ, NHNIL, NQ, NQNYH, NQWAIT, NSLJ, 4 NSLP, NYH C C Type declarations for labeled COMMON block SVOD02 -------------------- C REAL HU INTEGER NCFN, NETF, NFE, NJE, NLU, NNI, NQU, NST C C Type declarations for local variables -------------------------------- C EXTERNAL SVNLSD LOGICAL IHIT REAL ATOLI, BIG, EWTI, FOUR, H0, HMAX, HMX, HUN, ONE, 1 PT2, RH, RTOLI, SIZE, TCRIT, TNEXT, TOLSF, TP, TWO, ZERO INTEGER I, IER, IFLAG, IMXER, JCO, KGO, LENIW, LENJ, LENP, LENRW, 1 LENWM, LF0, MBAND, ML, MORD, MU, MXHNL0, MXSTP0, NITER, NSLAST CHARACTER*80 MSG C C Type declaration for function subroutines called --------------------- C REAL R1MACH, SVNORM C DIMENSION MORD(2) C----------------------------------------------------------------------- C The following Fortran-77 declaration is to cause the values of the C listed (local) variables to be saved between calls to SVODE. C----------------------------------------------------------------------- SAVE MORD, MXHNL0, MXSTP0 SAVE ZERO, ONE, TWO, FOUR, PT2, HUN C----------------------------------------------------------------------- C The following internal COMMON blocks contain variables which are C communicated between subroutines in the SVODE package, or which are C to be saved between calls to SVODE. C In each block, real variables precede integers. C The block /SVOD01/ appears in subroutines SVODE, SVINDY, SVSTEP, C SVSET, SVNLSD, SVJAC, SVSOL, SVJUST and SVSRCO. C The block /SVOD02/ appears in subroutines SVODE, SVINDY, SVSTEP, C SVNLSD, SVJAC, and SVSRCO. C C The variables stored in the internal COMMON blocks are as follows.. C C ACNRM = Weighted r.m.s. norm of accumulated correction vectors. C CCMXJ = Threshhold on DRC for updating the Jacobian. (See DRC.) C CONP = The saved value of TQ(5). C CRATE = Estimated corrector convergence rate constant. C DRC = Relative change in H*RL1 since last SVJAC call. C EL = Real array of integration coefficients. See SVSET. C ETA = Saved tentative ratio of new to old H. C ETAMAX = Saved maximum value of ETA to be allowed. C H = The step size. C HMIN = The minimum absolute value of the step size H to be used. C HMXI = Inverse of the maximum absolute value of H to be used. C HMXI = 0.0 is allowed and corresponds to an infinite HMAX. C HNEW = The step size to be attempted on the next step. C HSCAL = Stepsize in scaling of YH array. C PRL1 = The saved value of RL1. C RC = Ratio of current H*RL1 to value on last SVJAC call. C RL1 = The reciprocal of the coefficient EL(1). C TAU = Real vector of past NQ step sizes, length 13. C TQ = A real vector of length 5 in which SVSET stores constants C used for the convergence test, the error test, and the C selection of H at a new order. C TN = The independent variable, updated on each step taken. C UROUND = The machine unit roundoff. The smallest positive real number C such that 1.0 + UROUND .ne. 1.0 C ICF = Integer flag for convergence failure in SVNLSD.. C 0 means no failures. C 1 means convergence failure with out of date Jacobian C (recoverable error). C 2 means convergence failure with current Jacobian or C singular matrix (unrecoverable error). C INIT = Saved integer flag indicating whether initialization of the C problem has been done (INIT = 1) or not. C IPUP = Saved flag to signal updating of Newton matrix. C JCUR = Output flag from SVJAC showing Jacobian status.. C JCUR = 0 means J is not current. C JCUR = 1 means J is current. C JSTART = Integer flag used as input to SVSTEP.. C 0 means perform the first step. C 1 means take a new step continuing from the last. C -1 means take the next step with a new value of MAXORD, C HMIN, HMXI, N, METH, MITER, and/or matrix parameters. C On return, SVSTEP sets JSTART = 1. C JSV = Integer flag for Jacobian saving, = sign(MF). C KFLAG = A completion code from SVSTEP with the following meanings.. C 0 the step was succesful. C -1 the requested error could not be achieved. C -2 corrector convergence could not be achieved. C -3, -4 fatal error in VNLS (can not occur here). C KUTH = Input flag to SVSTEP showing whether H was reduced by the C driver. KUTH = 1 if H was reduced, = 0 otherwise. C L = Integer variable, NQ + 1, current order plus one. C LMAX = MAXORD + 1 (used for dimensioning). C LOCJS = A pointer to the saved Jacobian, whose storage starts at C WM(LOCJS), if JSV = 1. C LYH, LEWT, LACOR, LSAVF, LWM, LIWM = Saved integer pointers C to segments of RWORK and IWORK. C MAXORD = The maximum order of integration method to be allowed. C METH/MITER = The method flags. See MF. C MSBJ = The maximum number of steps between J evaluations, = 50. C MXHNIL = Saved value of optional input MXHNIL. C MXSTEP = Saved value of optional input MXSTEP. C N = The number of first-order ODEs, = NEQ. C NEWH = Saved integer to flag change of H. C NEWQ = The method order to be used on the next step. C NHNIL = Saved counter for occurrences of T + H = T. C NQ = Integer variable, the current integration method order. C NQNYH = Saved value of NQ*NYH. C NQWAIT = A counter controlling the frequency of order changes. C An order change is about to be considered if NQWAIT = 1. C NSLJ = The number of steps taken as of the last Jacobian update. C NSLP = Saved value of NST as of last Newton matrix update. C NYH = Saved value of the initial value of NEQ. C HU = The step size in t last used. C NCFN = Number of nonlinear convergence failures so far. C NETF = The number of error test failures of the integrator so far. C NFE = The number of f evaluations for the problem so far. C NJE = The number of Jacobian evaluations so far. C NLU = The number of matrix LU decompositions so far. C NNI = Number of nonlinear iterations so far. C NQU = The method order last used. C NST = The number of steps taken for the problem so far. C----------------------------------------------------------------------- COMMON /SVOD01/ ACNRM, CCMXJ, CONP, CRATE, DRC, EL(13), 1 ETA, ETAMAX, H, HMIN, HMXI, HNEW, HSCAL, PRL1, 2 RC, RL1, TAU(13), TQ(5), TN, UROUND, 3 ICF, INIT, IPUP, JCUR, JSTART, JSV, KFLAG, KUTH, 4 L, LMAX, LYH, LEWT, LACOR, LSAVF, LWM, LIWM, 5 LOCJS, MAXORD, METH, MITER, MSBJ, MXHNIL, MXSTEP, 6 N, NEWH, NEWQ, NHNIL, NQ, NQNYH, NQWAIT, NSLJ, 7 NSLP, NYH COMMON /SVOD02/ HU, NCFN, NETF, NFE, NJE, NLU, NNI, NQU, NST C DATA MORD(1) /12/, MORD(2) /5/, MXSTP0 /500/, MXHNL0 /10/ DATA ZERO /0.0E0/, ONE /1.0E0/, TWO /2.0E0/, FOUR /4.0E0/, 1 PT2 /0.2E0/, HUN /100.0E0/ C----------------------------------------------------------------------- C Block A. C This code block is executed on every call. C It tests ISTATE and ITASK for legality and branches appropriately. C If ISTATE .gt. 1 but the flag INIT shows that initialization has C not yet been done, an error return occurs. C If ISTATE = 1 and TOUT = T, return immediately. C----------------------------------------------------------------------- IF (ISTATE .LT. 1 .OR. ISTATE .GT. 3) GO TO 601 IF (ITASK .LT. 1 .OR. ITASK .GT. 5) GO TO 602 IF (ISTATE .EQ. 1) GO TO 10 IF (INIT .NE. 1) GO TO 603 IF (ISTATE .EQ. 2) GO TO 200 GO TO 20 10 INIT = 0 IF (TOUT .EQ. T) RETURN C----------------------------------------------------------------------- C Block B. C The next code block is executed for the initial call (ISTATE = 1), C or for a continuation call with parameter changes (ISTATE = 3). C It contains checking of all input and various initializations. C C First check legality of the non-optional input NEQ, ITOL, IOPT, C MF, ML, and MU. C----------------------------------------------------------------------- 20 IF (NEQ .LE. 0) GO TO 604 IF (ISTATE .EQ. 1) GO TO 25 IF (NEQ .GT. N) GO TO 605 25 N = NEQ IF (ITOL .LT. 1 .OR. ITOL .GT. 4) GO TO 606 IF (IOPT .LT. 0 .OR. IOPT .GT. 1) GO TO 607 JSV = SIGN(1,MF) MF = ABS(MF) METH = MF/10 MITER = MF - 10*METH IF (METH .LT. 1 .OR. METH .GT. 2) GO TO 608 IF (MITER .LT. 0 .OR. MITER .GT. 5) GO TO 608 IF (MITER .LE. 3) GO TO 30 ML = IWORK(1) MU = IWORK(2) IF (ML .LT. 0 .OR. ML .GE. N) GO TO 609 IF (MU .LT. 0 .OR. MU .GE. N) GO TO 610 30 CONTINUE C Next process and check the optional input. --------------------------- IF (IOPT .EQ. 1) GO TO 40 MAXORD = MORD(METH) MXSTEP = MXSTP0 MXHNIL = MXHNL0 IF (ISTATE .EQ. 1) H0 = ZERO HMXI = ZERO HMIN = ZERO GO TO 60 40 MAXORD = IWORK(5) IF (MAXORD .LT. 0) GO TO 611 IF (MAXORD .EQ. 0) MAXORD = 100 MAXORD = MIN(MAXORD,MORD(METH)) MXSTEP = IWORK(6) IF (MXSTEP .LT. 0) GO TO 612 IF (MXSTEP .EQ. 0) MXSTEP = MXSTP0 MXHNIL = IWORK(7) IF (MXHNIL .LT. 0) GO TO 613 IF (MXHNIL .EQ. 0) MXHNIL = MXHNL0 IF (ISTATE .NE. 1) GO TO 50 H0 = RWORK(5) IF ((TOUT - T)*H0 .LT. ZERO) GO TO 614 50 HMAX = RWORK(6) IF (HMAX .LT. ZERO) GO TO 615 HMXI = ZERO IF (HMAX .GT. ZERO) HMXI = ONE/HMAX HMIN = RWORK(7) IF (HMIN .LT. ZERO) GO TO 616 C----------------------------------------------------------------------- C Set work array pointers and check lengths LRW and LIW. C Pointers to segments of RWORK and IWORK are named by prefixing L to C the name of the segment. E.g., the segment YH starts at RWORK(LYH). C Segments of RWORK (in order) are denoted YH, WM, EWT, SAVF, ACOR. C Within WM, LOCJS is the location of the saved Jacobian (JSV .gt. 0). C----------------------------------------------------------------------- 60 LYH = 21 IF (ISTATE .EQ. 1) NYH = N LWM = LYH + (MAXORD + 1)*NYH JCO = MAX(0,JSV) IF (MITER .EQ. 0) LENWM = 0 IF (MITER .EQ. 1 .OR. MITER .EQ. 2) THEN LENWM = 2 + (1 + JCO)*N*N LOCJS = N*N + 3 ENDIF IF (MITER .EQ. 3) LENWM = 2 + N IF (MITER .EQ. 4 .OR. MITER .EQ. 5) THEN MBAND = ML + MU + 1 LENP = (MBAND + ML)*N LENJ = MBAND*N LENWM = 2 + LENP + JCO*LENJ LOCJS = LENP + 3 ENDIF LEWT = LWM + LENWM LSAVF = LEWT + N LACOR = LSAVF + N LENRW = LACOR + N - 1 IWORK(17) = LENRW LIWM = 1 LENIW = 30 + N IF (MITER .EQ. 0 .OR. MITER .EQ. 3) LENIW = 30 IWORK(18) = LENIW IF (LENRW .GT. LRW) GO TO 617 IF (LENIW .GT. LIW) GO TO 618 C Check RTOL and ATOL for legality. ------------------------------------ RTOLI = RTOL(1) ATOLI = ATOL(1) DO 70 I = 1,N IF (ITOL .GE. 3) RTOLI = RTOL(I) IF (ITOL .EQ. 2 .OR. ITOL .EQ. 4) ATOLI = ATOL(I) IF (RTOLI .LT. ZERO) GO TO 619 IF (ATOLI .LT. ZERO) GO TO 620 70 CONTINUE IF (ISTATE .EQ. 1) GO TO 100 C If ISTATE = 3, set flag to signal parameter changes to SVSTEP. ------- JSTART = -1 IF (NQ .LE. MAXORD) GO TO 90 C MAXORD was reduced below NQ. Copy YH(*,MAXORD+2) into SAVF. --------- CALL CH_SCOPY (N, RWORK(LWM), 1, RWORK(LSAVF), 1) C Reload WM(1) = RWORK(LWM), since LWM may have changed. --------------- 90 IF (MITER .GT. 0) RWORK(LWM) = SQRT(UROUND) C----------------------------------------------------------------------- C Block C. C The next block is for the initial call only (ISTATE = 1). C It contains all remaining initializations, the initial call to F, C and the calculation of the initial step size. C The error weights in EWT are inverted after being loaded. C----------------------------------------------------------------------- 100 UROUND = R1MACH(4) TN = T IF (ITASK .NE. 4 .AND. ITASK .NE. 5) GO TO 110 TCRIT = RWORK(1) IF ((TCRIT - TOUT)*(TOUT - T) .LT. ZERO) GO TO 625 IF (H0 .NE. ZERO .AND. (T + H0 - TCRIT)*H0 .GT. ZERO) 1 H0 = TCRIT - T 110 JSTART = 0 IF (MITER .GT. 0) RWORK(LWM) = SQRT(UROUND) CCMXJ = PT2 MSBJ = 50 NHNIL = 0 NST = 0 NJE = 0 NNI = 0 NCFN = 0 NETF = 0 NLU = 0 NSLJ = 0 NSLAST = 0 HU = ZERO NQU = 0 C Initial call to F. (LF0 points to YH(*,2).) ------------------------- LF0 = LYH + NYH C C*UPG*MNH C CALL F (N, T, Y, RWORK(LF0), RPAR, IPAR, KMI, KINDEX) C C*UPG*MNH C NFE = 1 C Load the initial value vector in YH. --------------------------------- CALL CH_SCOPY (N, Y, 1, RWORK(LYH), 1) C Load and invert the EWT array. (H is temporarily set to 1.0.) ------- NQ = 1 H = ONE CALL SEWSET (N, ITOL, RTOL, ATOL, RWORK(LYH), RWORK(LEWT)) DO 120 I = 1,N IF (RWORK(I+LEWT-1) .LE. ZERO) GO TO 621 120 RWORK(I+LEWT-1) = ONE/RWORK(I+LEWT-1) IF (H0 .NE. ZERO) GO TO 180 C Call SVHIN to set initial step size H0 to be attempted. -------------- CALL SVHIN (N, T, RWORK(LYH), RWORK(LF0), F, RPAR, IPAR, TOUT, 1 UROUND, RWORK(LEWT), ITOL, ATOL, Y, RWORK(LACOR), H0, 2 NITER, IER, KMI, KINDEX) NFE = NFE + NITER IF (IER .NE. 0) GO TO 622 C Adjust H0 if necessary to meet HMAX bound. --------------------------- 180 RH = ABS(H0)*HMXI IF (RH .GT. ONE) H0 = H0/RH C Load H with H0 and scale YH(*,2) by H0. ------------------------------ H = H0 CALL SSCAL (N, H0, RWORK(LF0), 1) GO TO 270 C----------------------------------------------------------------------- C Block D. C The next code block is for continuation calls only (ISTATE = 2 or 3) C and is to check stop conditions before taking a step. C----------------------------------------------------------------------- 200 NSLAST = NST KUTH = 0 GO TO (210, 250, 220, 230, 240), ITASK 210 IF ((TN - TOUT)*H .LT. ZERO) GO TO 250 CALL SVINDY (TOUT, 0, RWORK(LYH), NYH, Y, IFLAG) IF (IFLAG .NE. 0) GO TO 627 T = TOUT GO TO 420 220 TP = TN - HU*(ONE + HUN*UROUND) IF ((TP - TOUT)*H .GT. ZERO) GO TO 623 IF ((TN - TOUT)*H .LT. ZERO) GO TO 250 GO TO 400 230 TCRIT = RWORK(1) IF ((TN - TCRIT)*H .GT. ZERO) GO TO 624 IF ((TCRIT - TOUT)*H .LT. ZERO) GO TO 625 IF ((TN - TOUT)*H .LT. ZERO) GO TO 245 CALL SVINDY (TOUT, 0, RWORK(LYH), NYH, Y, IFLAG) IF (IFLAG .NE. 0) GO TO 627 T = TOUT GO TO 420 240 TCRIT = RWORK(1) IF ((TN - TCRIT)*H .GT. ZERO) GO TO 624 245 HMX = ABS(TN) + ABS(H) IHIT = ABS(TN - TCRIT) .LE. HUN*UROUND*HMX IF (IHIT) GO TO 400 TNEXT = TN + HNEW*(ONE + FOUR*UROUND) IF ((TNEXT - TCRIT)*H .LE. ZERO) GO TO 250 H = (TCRIT - TN)*(ONE - FOUR*UROUND) KUTH = 1 C----------------------------------------------------------------------- C Block E. C The next block is normally executed for all calls and contains C the call to the one-step core integrator SVSTEP. C C This is a looping point for the integration steps. C C First check for too many steps being taken, update EWT (if not at C start of problem), check for too much accuracy being requested, and C check for H below the roundoff level in T. C----------------------------------------------------------------------- 250 CONTINUE IF ((NST-NSLAST) .GE. MXSTEP) GO TO 500 CALL SEWSET (N, ITOL, RTOL, ATOL, RWORK(LYH), RWORK(LEWT)) DO 260 I = 1,N IF (RWORK(I+LEWT-1) .LE. ZERO) GO TO 510 260 RWORK(I+LEWT-1) = ONE/RWORK(I+LEWT-1) 270 TOLSF = UROUND*SVNORM (N, RWORK(LYH), RWORK(LEWT)) IF (TOLSF .LE. ONE) GO TO 280 TOLSF = TOLSF*TWO IF (NST .EQ. 0) GO TO 626 GO TO 520 280 IF ((TN + H) .NE. TN) GO TO 290 CKS: strange things happen on HP f90 (this error message is CKS: often printed but results are the same than on Linux) CKS: let's jump over these prints GOTO 290 NHNIL = NHNIL + 1 IF (NHNIL .GT. MXHNIL) GO TO 290 MSG = 'SVODE-- Warning..internal T (=R1) and H (=R2) are' CALL XERRWV (MSG, 50, 101, 1, 0, 0, 0, 0, ZERO, ZERO) MSG=' such that in the machine, T + H = T on the next step ' CALL XERRWV (MSG, 60, 101, 1, 0, 0, 0, 0, ZERO, ZERO) MSG = ' (H = step size). solver will continue anyway' CALL XERRWV (MSG, 50, 101, 1, 0, 0, 0, 2, TN, H) IF (NHNIL .LT. MXHNIL) GO TO 290 MSG = 'SVODE-- Above warning has been issued I1 times. ' CALL XERRWV (MSG, 50, 102, 1, 0, 0, 0, 0, ZERO, ZERO) MSG = ' it will not be issued again for this problem' CALL XERRWV (MSG, 50, 102, 1, 1, MXHNIL, 0, 0, ZERO, ZERO) 290 CONTINUE C----------------------------------------------------------------------- C CALL SVSTEP (Y, YH, NYH, YH, EWT, SAVF, VSAV, ACOR, C WM, IWM, F, JAC, F, SVNLSD, RPAR, IPAR) C----------------------------------------------------------------------- CALL SVSTEP (Y, RWORK(LYH), NYH, RWORK(LYH), RWORK(LEWT), 1 RWORK(LSAVF), Y, RWORK(LACOR), RWORK(LWM), IWORK(LIWM), 2 F, JAC, F, SVNLSD, RPAR, IPAR, KMI, KINDEX) KGO = 1 - KFLAG C Branch on KFLAG. Note..In this version, KFLAG can not be set to -3. C KFLAG .eq. 0, -1, -2 GO TO (300, 530, 540), KGO C----------------------------------------------------------------------- C Block F. C The following block handles the case of a successful return from the C core integrator (KFLAG = 0). Test for stop conditions. C----------------------------------------------------------------------- 300 INIT = 1 KUTH = 0 GO TO (310, 400, 330, 340, 350), ITASK C ITASK = 1. If TOUT has been reached, interpolate. ------------------- 310 IF ((TN - TOUT)*H .LT. ZERO) GO TO 250 CALL SVINDY (TOUT, 0, RWORK(LYH), NYH, Y, IFLAG) T = TOUT GO TO 420 C ITASK = 3. Jump to exit if TOUT was reached. ------------------------ 330 IF ((TN - TOUT)*H .GE. ZERO) GO TO 400 GO TO 250 C ITASK = 4. See if TOUT or TCRIT was reached. Adjust H if necessary. 340 IF ((TN - TOUT)*H .LT. ZERO) GO TO 345 CALL SVINDY (TOUT, 0, RWORK(LYH), NYH, Y, IFLAG) T = TOUT GO TO 420 345 HMX = ABS(TN) + ABS(H) IHIT = ABS(TN - TCRIT) .LE. HUN*UROUND*HMX IF (IHIT) GO TO 400 TNEXT = TN + HNEW*(ONE + FOUR*UROUND) IF ((TNEXT - TCRIT)*H .LE. ZERO) GO TO 250 H = (TCRIT - TN)*(ONE - FOUR*UROUND) KUTH = 1 GO TO 250 C ITASK = 5. See if TCRIT was reached and jump to exit. --------------- 350 HMX = ABS(TN) + ABS(H) IHIT = ABS(TN - TCRIT) .LE. HUN*UROUND*HMX C----------------------------------------------------------------------- C Block G. C The following block handles all successful returns from SVODE. C If ITASK .ne. 1, Y is loaded from YH and T is set accordingly. C ISTATE is set to 2, and the optional output is loaded into the work C arrays before returning. C----------------------------------------------------------------------- 400 CONTINUE CALL CH_SCOPY (N, RWORK(LYH), 1, Y, 1) T = TN IF (ITASK .NE. 4 .AND. ITASK .NE. 5) GO TO 420 IF (IHIT) T = TCRIT 420 ISTATE = 2 RWORK(11) = HU RWORK(12) = HNEW RWORK(13) = TN IWORK(11) = NST IWORK(12) = NFE IWORK(13) = NJE IWORK(14) = NQU IWORK(15) = NEWQ IWORK(19) = NLU IWORK(20) = NNI IWORK(21) = NCFN IWORK(22) = NETF RETURN C----------------------------------------------------------------------- C Block H. C The following block handles all unsuccessful returns other than C those for illegal input. First the error message routine is called. C if there was an error test or convergence test failure, IMXER is set. C Then Y is loaded from YH, T is set to TN, and the illegal input C The optional output is loaded into the work arrays before returning. C----------------------------------------------------------------------- C The maximum number of steps was taken before reaching TOUT. ---------- 500 MSG = 'SVODE-- At current T (=R1), MXSTEP (=I1) steps ' CALL XERRWV (MSG, 50, 201, 1, 0, 0, 0, 0, ZERO, ZERO) MSG = ' taken on this call before reaching TOUT ' CALL XERRWV (MSG, 50, 201, 1, 1, MXSTEP, 0, 1, TN, ZERO) ISTATE = -1 GO TO 580 C EWT(i) .le. 0.0 for some i (not at start of problem). ---------------- 510 EWTI = RWORK(LEWT+I-1) MSG = 'SVODE-- At T (=R1), EWT(I1) has become R2 .le. 0.' CALL XERRWV (MSG, 50, 202, 1, 1, I, 0, 2, TN, EWTI) ISTATE = -6 GO TO 580 C Too much accuracy requested for machine precision. ------------------- 520 MSG = 'SVODE-- At T (=R1), too much accuracy requested ' CALL XERRWV (MSG, 50, 203, 1, 0, 0, 0, 0, ZERO, ZERO) MSG = ' for precision of machine.. see TOLSF (=R2) ' CALL XERRWV (MSG, 50, 203, 1, 0, 0, 0, 2, TN, TOLSF) RWORK(14) = TOLSF ISTATE = -2 GO TO 580 C KFLAG = -1. Error test failed repeatedly or with ABS(H) = HMIN. ----- 530 MSG = 'SVODE-- At T(=R1) and step size H(=R2), the error' CALL XERRWV (MSG, 50, 204, 1, 0, 0, 0, 0, ZERO, ZERO) MSG = ' test failed repeatedly or with abs(H) = HMIN' CALL XERRWV (MSG, 50, 204, 1, 0, 0, 0, 2, TN, H) ISTATE = -4 GO TO 560 C KFLAG = -2. Convergence failed repeatedly or with abs(H) = HMIN. ---- 540 MSG = 'SVODE-- At T (=R1) and step size H (=R2), the ' CALL XERRWV (MSG, 50, 205, 1, 0, 0, 0, 0, ZERO, ZERO) MSG = ' corrector convergence failed repeatedly ' CALL XERRWV (MSG, 50, 205, 1, 0, 0, 0, 0, ZERO, ZERO) MSG = ' or with abs(H) = HMIN ' CALL XERRWV (MSG, 30, 205, 1, 0, 0, 0, 2, TN, H) ISTATE = -5 C Compute IMXER if relevant. ------------------------------------------- 560 BIG = ZERO IMXER = 1 DO 570 I = 1,N SIZE = ABS(RWORK(I+LACOR-1)*RWORK(I+LEWT-1)) IF (BIG .GE. SIZE) GO TO 570 BIG = SIZE IMXER = I 570 CONTINUE IWORK(16) = IMXER C Set Y vector, T, and optional output. -------------------------------- 580 CONTINUE CALL CH_SCOPY (N, RWORK(LYH), 1, Y, 1) T = TN RWORK(11) = HU RWORK(12) = H RWORK(13) = TN IWORK(11) = NST IWORK(12) = NFE IWORK(13) = NJE IWORK(14) = NQU IWORK(15) = NQ IWORK(19) = NLU IWORK(20) = NNI IWORK(21) = NCFN IWORK(22) = NETF RETURN C----------------------------------------------------------------------- C Block I. C The following block handles all error returns due to illegal input C (ISTATE = -3), as detected before calling the core integrator. C First the error message routine is called. If the illegal input C is a negative ISTATE, the run is aborted (apparent infinite loop). C----------------------------------------------------------------------- 601 MSG = 'SVODE-- ISTATE (=I1) illegal ' CALL XERRWV (MSG, 30, 1, 1, 1, ISTATE, 0, 0, ZERO, ZERO) IF (ISTATE .LT. 0) GO TO 800 GO TO 700 602 MSG = 'SVODE-- ITASK (=I1) illegal ' CALL XERRWV (MSG, 30, 2, 1, 1, ITASK, 0, 0, ZERO, ZERO) GO TO 700 603 MSG='SVODE-- ISTATE (=I1) .gt. 1 but SVODE not initialized ' CALL XERRWV (MSG, 60, 3, 1, 1, ISTATE, 0, 0, ZERO, ZERO) GO TO 700 604 MSG = 'SVODE-- NEQ (=I1) .lt. 1 ' CALL XERRWV (MSG, 30, 4, 1, 1, NEQ, 0, 0, ZERO, ZERO) GO TO 700 605 MSG = 'SVODE-- ISTATE = 3 and NEQ increased (I1 to I2) ' CALL XERRWV (MSG, 50, 5, 1, 2, N, NEQ, 0, ZERO, ZERO) GO TO 700 606 MSG = 'SVODE-- ITOL (=I1) illegal ' CALL XERRWV (MSG, 30, 6, 1, 1, ITOL, 0, 0, ZERO, ZERO) GO TO 700 607 MSG = 'SVODE-- IOPT (=I1) illegal ' CALL XERRWV (MSG, 30, 7, 1, 1, IOPT, 0, 0, ZERO, ZERO) GO TO 700 608 MSG = 'SVODE-- MF (=I1) illegal ' CALL XERRWV (MSG, 30, 8, 1, 1, MF, 0, 0, ZERO, ZERO) GO TO 700 609 MSG = 'SVODE-- ML (=I1) illegal.. .lt.0 or .ge.NEQ (=I2)' CALL XERRWV (MSG, 50, 9, 1, 2, ML, NEQ, 0, ZERO, ZERO) GO TO 700 610 MSG = 'SVODE-- MU (=I1) illegal.. .lt.0 or .ge.NEQ (=I2)' CALL XERRWV (MSG, 50, 10, 1, 2, MU, NEQ, 0, ZERO, ZERO) GO TO 700 611 MSG = 'SVODE-- MAXORD (=I1) .lt. 0 ' CALL XERRWV (MSG, 30, 11, 1, 1, MAXORD, 0, 0, ZERO, ZERO) GO TO 700 612 MSG = 'SVODE-- MXSTEP (=I1) .lt. 0 ' CALL XERRWV (MSG, 30, 12, 1, 1, MXSTEP, 0, 0, ZERO, ZERO) GO TO 700 613 MSG = 'SVODE-- MXHNIL (=I1) .lt. 0 ' CALL XERRWV (MSG, 30, 13, 1, 1, MXHNIL, 0, 0, ZERO, ZERO) GO TO 700 614 MSG = 'SVODE-- TOUT (=R1) behind T (=R2) ' CALL XERRWV (MSG, 40, 14, 1, 0, 0, 0, 2, TOUT, T) MSG = ' integration direction is given by H0 (=R1) ' CALL XERRWV (MSG, 50, 14, 1, 0, 0, 0, 1, H0, ZERO) GO TO 700 615 MSG = 'SVODE-- HMAX (=R1) .lt. 0.0 ' CALL XERRWV (MSG, 30, 15, 1, 0, 0, 0, 1, HMAX, ZERO) GO TO 700 616 MSG = 'SVODE-- HMIN (=R1) .lt. 0.0 ' CALL XERRWV (MSG, 30, 16, 1, 0, 0, 0, 1, HMIN, ZERO) GO TO 700 617 CONTINUE MSG='SVODE-- RWORK length needed, LENRW (=I1), exceeds LRW (=I2)' CALL XERRWV (MSG, 60, 17, 1, 2, LENRW, LRW, 0, ZERO, ZERO) GO TO 700 618 CONTINUE MSG='SVODE-- IWORK length needed, LENIW (=I1), exceeds LIW (=I2)' CALL XERRWV (MSG, 60, 18, 1, 2, LENIW, LIW, 0, ZERO, ZERO) GO TO 700 619 MSG = 'SVODE-- RTOL(I1) is R1 .lt. 0.0 ' CALL XERRWV (MSG, 40, 19, 1, 1, I, 0, 1, RTOLI, ZERO) GO TO 700 620 MSG = 'SVODE-- ATOL(I1) is R1 .lt. 0.0 ' CALL XERRWV (MSG, 40, 20, 1, 1, I, 0, 1, ATOLI, ZERO) GO TO 700 621 EWTI = RWORK(LEWT+I-1) MSG = 'SVODE-- EWT(I1) is R1 .le. 0.0 ' CALL XERRWV (MSG, 40, 21, 1, 1, I, 0, 1, EWTI, ZERO) GO TO 700 622 CONTINUE MSG='SVODE-- TOUT (=R1) too close to T(=R2) to start integration' CALL XERRWV (MSG, 60, 22, 1, 0, 0, 0, 2, TOUT, T) GO TO 700 623 CONTINUE MSG='SVODE-- ITASK = I1 and TOUT (=R1) behind TCUR - HU (= R2) ' CALL XERRWV (MSG, 60, 23, 1, 1, ITASK, 0, 2, TOUT, TP) GO TO 700 624 CONTINUE MSG='SVODE-- ITASK = 4 or 5 and TCRIT (=R1) behind TCUR (=R2) ' CALL XERRWV (MSG, 60, 24, 1, 0, 0, 0, 2, TCRIT, TN) GO TO 700 625 CONTINUE MSG='SVODE-- ITASK = 4 or 5 and TCRIT (=R1) behind TOUT (=R2) ' CALL XERRWV (MSG, 60, 25, 1, 0, 0, 0, 2, TCRIT, TOUT) GO TO 700 626 MSG = 'SVODE-- At start of problem, too much accuracy ' CALL XERRWV (MSG, 50, 26, 1, 0, 0, 0, 0, ZERO, ZERO) MSG=' requested for precision of machine.. see TOLSF (=R1) ' CALL XERRWV (MSG, 60, 26, 1, 0, 0, 0, 1, TOLSF, ZERO) RWORK(14) = TOLSF GO TO 700 627 MSG='SVODE-- Trouble from SVINDY. ITASK = I1, TOUT = R1. ' CALL XERRWV (MSG, 60, 27, 1, 1, ITASK, 0, 1, TOUT, ZERO) C 700 CONTINUE ISTATE = -3 RETURN C 800 MSG = 'SVODE-- Run aborted.. apparent infinite loop ' CALL XERRWV (MSG, 50, 303, 2, 0, 0, 0, 0, ZERO, ZERO) RETURN END SUBROUTINE SVODE C C####################################################################### C CDECK SVHIN C ############################################################### SUBROUTINE SVHIN (N, T0, Y0, YDOT, F, RPAR, IPAR, TOUT, UROUND, 1 EWT, ITOL, ATOL, Y, TEMP, H0, NITER, IER, KMI, KINDEX) C ############################################################### EXTERNAL F REAL T0, Y0, YDOT, RPAR, TOUT, UROUND, EWT, ATOL, Y, 1 TEMP, H0 INTEGER N, IPAR, ITOL, NITER, IER DIMENSION Y0(*), YDOT(*), EWT(*), ATOL(*), Y(*), 1 TEMP(*), RPAR(*), IPAR(*) INTEGER KMI, KINDEX C----------------------------------------------------------------------- C Call sequence input -- N, T0, Y0, YDOT, F, RPAR, IPAR, TOUT, UROUND, C EWT, ITOL, ATOL, Y, TEMP C Call sequence output -- H0, NITER, IER C COMMON block variables accessed -- None C C Subroutines called by SVHIN.. F C Function routines called by SVHIN.. SVNORM C----------------------------------------------------------------------- C This routine computes the step size, H0, to be attempted on the C first step, when the user has not supplied a value for this. C C First we check that TOUT - T0 differs significantly from zero. Then C an iteration is done to approximate the initial second derivative C and this is used to define h from w.r.m.s.norm(h**2 * yddot / 2) = 1. C A bias factor of 1/2 is applied to the resulting h. C The sign of H0 is inferred from the initial values of TOUT and T0. C C Communication with SVHIN is done with the following variables.. C C N = Size of ODE system, input. C T0 = Initial value of independent variable, input. C Y0 = Vector of initial conditions, input. C YDOT = Vector of initial first derivatives, input. C F = Name of subroutine for right-hand side f(t,y), input. C RPAR, IPAR = Dummy names for user's real and integer work arrays. C TOUT = First output value of independent variable C UROUND = Machine unit roundoff C EWT, ITOL, ATOL = Error weights and tolerance parameters C as described in the driver routine, input. C Y, TEMP = Work arrays of length N. C H0 = Step size to be attempted, output. C NITER = Number of iterations (and of f evaluations) to compute H0, C output. C IER = The error flag, returned with the value C IER = 0 if no trouble occurred, or C IER = -1 if TOUT and T0 are considered too close to proceed. C----------------------------------------------------------------------- C C Type declarations for local variables -------------------------------- C REAL AFI, ATOLI, DELYI, HALF, HG, HLB, HNEW, HRAT, 1 HUB, HUN, PT1, T1, TDIST, TROUND, TWO, YDDNRM INTEGER I, ITER C C Type declaration for function subroutines called --------------------- C REAL SVNORM C----------------------------------------------------------------------- C The following Fortran-77 declaration is to cause the values of the C listed (local) variables to be saved between calls to this integrator. C----------------------------------------------------------------------- SAVE HALF, HUN, PT1, TWO DATA HALF /0.5E0/, HUN /100.0E0/, PT1 /0.1E0/, TWO /2.0E0/ C NITER = 0 TDIST = ABS(TOUT - T0) TROUND = UROUND*MAX(ABS(T0),ABS(TOUT)) IF (TDIST .LT. TWO*TROUND) GO TO 100 C C Set a lower bound on h based on the roundoff level in T0 and TOUT. --- HLB = HUN*TROUND C Set an upper bound on h based on TOUT-T0 and the initial Y and YDOT. - HUB = PT1*TDIST ATOLI = ATOL(1) DO 10 I = 1, N IF (ITOL .EQ. 2 .OR. ITOL .EQ. 4) ATOLI = ATOL(I) DELYI = PT1*ABS(Y0(I)) + ATOLI AFI = ABS(YDOT(I)) IF (AFI*HUB .GT. DELYI) HUB = DELYI/AFI 10 CONTINUE C C Set initial guess for h as geometric mean of upper and lower bounds. - ITER = 0 HG = SQRT(HLB*HUB) C If the bounds have crossed, exit with the mean value. ---------------- IF (HUB .LT. HLB) THEN H0 = HG GO TO 90 ENDIF C C Looping point for iteration. ----------------------------------------- 50 CONTINUE C Estimate the second derivative as a difference quotient in f. -------- T1 = T0 + HG DO 60 I = 1, N 60 Y(I) = Y0(I) + HG*YDOT(I) C C*UPG*MNH C CALL F (N, T1, Y, TEMP, RPAR, IPAR, KMI, KINDEX) C C*UPG*MNH C DO 70 I = 1, N 70 TEMP(I) = (TEMP(I) - YDOT(I))/HG YDDNRM = SVNORM (N, TEMP, EWT) C Get the corresponding new value of h. -------------------------------- IF (YDDNRM*HUB*HUB .GT. TWO) THEN HNEW = SQRT(TWO/YDDNRM) ELSE HNEW = SQRT(HG*HUB) ENDIF ITER = ITER + 1 C----------------------------------------------------------------------- C Test the stopping conditions. C Stop if the new and previous h values differ by a factor of .lt. 2. C Stop if four iterations have been done. Also, stop with previous h C if HNEW/HG .gt. 2 after first iteration, as this probably means that C the second derivative value is bad because of cancellation error. C----------------------------------------------------------------------- IF (ITER .GE. 4) GO TO 80 HRAT = HNEW/HG IF ( (HRAT .GT. HALF) .AND. (HRAT .LT. TWO) ) GO TO 80 IF ( (ITER .GE. 2) .AND. (HNEW .GT. TWO*HG) ) THEN HNEW = HG GO TO 80 ENDIF HG = HNEW GO TO 50 C C Iteration done. Apply bounds, bias factor, and sign. Then exit. ---- 80 H0 = HNEW*HALF IF (H0 .LT. HLB) H0 = HLB IF (H0 .GT. HUB) H0 = HUB 90 H0 = SIGN(H0, TOUT - T0) NITER = ITER IER = 0 RETURN C Error return for TOUT - T0 too small. -------------------------------- 100 IER = -1 RETURN END SUBROUTINE SVHIN C C####################################################################### C CDECK SVINDY C ############################################## SUBROUTINE SVINDY (T, K, YH, LDYH, DKY, IFLAG) C ############################################## REAL T, YH, DKY INTEGER K, LDYH, IFLAG DIMENSION YH(LDYH,*), DKY(*) C----------------------------------------------------------------------- C Call sequence input -- T, K, YH, LDYH C Call sequence output -- DKY, IFLAG C COMMON block variables accessed.. C /SVOD01/ -- H, TN, UROUND, L, N, NQ C /SVOD02/ -- HU C C Subroutines called by SVINDY.. SSCAL, XERRWV C Function routines called by SVINDY.. None C----------------------------------------------------------------------- C SVINDY computes interpolated values of the K-th derivative of the C dependent variable vector y, and stores it in DKY. This routine C is called within the package with K = 0 and T = TOUT, but may C also be called by the user for any K up to the current order. C (See detailed instructions in the usage documentation.) C----------------------------------------------------------------------- C The computed values in DKY are gotten by interpolation using the C Nordsieck history array YH. This array corresponds uniquely to a C vector-valued polynomial of degree NQCUR or less, and DKY is set C to the K-th derivative of this polynomial at T. C The formula for DKY is.. C q C DKY(i) = sum c(j,K) * (T - TN)**(j-K) * H**(-j) * YH(i,j+1) C j=K C where c(j,K) = j*(j-1)*...*(j-K+1), q = NQCUR, TN = TCUR, H = HCUR. C The quantities NQ = NQCUR, L = NQ+1, N, TN, and H are C communicated by COMMON. The above sum is done in reverse order. C IFLAG is returned negative if either K or T is out of bounds. C C Discussion above and comments in driver explain all variables. C----------------------------------------------------------------------- C C Type declarations for labeled COMMON block SVOD01 -------------------- C REAL ACNRM, CCMXJ, CONP, CRATE, DRC, EL, 1 ETA, ETAMAX, H, HMIN, HMXI, HNEW, HSCAL, PRL1, 2 RC, RL1, TAU, TQ, TN, UROUND INTEGER ICF, INIT, IPUP, JCUR, JSTART, JSV, KFLAG, KUTH, 1 L, LMAX, LYH, LEWT, LACOR, LSAVF, LWM, LIWM, 2 LOCJS, MAXORD, METH, MITER, MSBJ, MXHNIL, MXSTEP, 3 N, NEWH, NEWQ, NHNIL, NQ, NQNYH, NQWAIT, NSLJ, 4 NSLP, NYH C C Type declarations for labeled COMMON block SVOD02 -------------------- C REAL HU INTEGER NCFN, NETF, NFE, NJE, NLU, NNI, NQU, NST C C Type declarations for local variables -------------------------------- C REAL C, HUN, R, S, TFUZZ, TN1, TP, ZERO INTEGER I, IC, J, JB, JB2, JJ, JJ1, JP1 CHARACTER*80 MSG C----------------------------------------------------------------------- C The following Fortran-77 declaration is to cause the values of the C listed (local) variables to be saved between calls to this integrator. C----------------------------------------------------------------------- SAVE HUN, ZERO C COMMON /SVOD01/ ACNRM, CCMXJ, CONP, CRATE, DRC, EL(13), 1 ETA, ETAMAX, H, HMIN, HMXI, HNEW, HSCAL, PRL1, 2 RC, RL1, TAU(13), TQ(5), TN, UROUND, 3 ICF, INIT, IPUP, JCUR, JSTART, JSV, KFLAG, KUTH, 4 L, LMAX, LYH, LEWT, LACOR, LSAVF, LWM, LIWM, 5 LOCJS, MAXORD, METH, MITER, MSBJ, MXHNIL, MXSTEP, 6 N, NEWH, NEWQ, NHNIL, NQ, NQNYH, NQWAIT, NSLJ, 7 NSLP, NYH COMMON /SVOD02/ HU, NCFN, NETF, NFE, NJE, NLU, NNI, NQU, NST C DATA HUN /100.0E0/, ZERO /0.0E0/ C IFLAG = 0 IF (K .LT. 0 .OR. K .GT. NQ) GO TO 80 TFUZZ = HUN*UROUND*(TN + HU) TP = TN - HU - TFUZZ TN1 = TN + TFUZZ IF ((T-TP)*(T-TN1) .GT. ZERO) GO TO 90 C S = (T - TN)/H IC = 1 IF (K .EQ. 0) GO TO 15 JJ1 = L - K DO 10 JJ = JJ1, NQ 10 IC = IC*JJ 15 C = REAL(IC) DO 20 I = 1, N 20 DKY(I) = C*YH(I,L) IF (K .EQ. NQ) GO TO 55 JB2 = NQ - K DO 50 JB = 1, JB2 J = NQ - JB JP1 = J + 1 IC = 1 IF (K .EQ. 0) GO TO 35 JJ1 = JP1 - K DO 30 JJ = JJ1, J 30 IC = IC*JJ 35 C = REAL(IC) DO 40 I = 1, N 40 DKY(I) = C*YH(I,JP1) + S*DKY(I) 50 CONTINUE IF (K .EQ. 0) RETURN 55 R = H**(-K) CALL SSCAL (N, R, DKY, 1) RETURN C 80 MSG = 'SVINDY-- K (=I1) illegal ' CALL XERRWV (MSG, 30, 51, 1, 1, K, 0, 0, ZERO, ZERO) IFLAG = -1 RETURN 90 MSG = 'SVINDY-- T (=R1) illegal ' CALL XERRWV (MSG, 30, 52, 1, 0, 0, 0, 1, T, ZERO) MSG=' T not in interval TCUR - HU (= R1) to TCUR (=R2) ' CALL XERRWV (MSG, 60, 52, 1, 0, 0, 0, 2, TP, TN) IFLAG = -2 RETURN END SUBROUTINE SVINDY c C####################################################################### C CDECK SVSTEP C C ########################################################### SUBROUTINE SVSTEP (Y, YH, LDYH, YH1, EWT, SAVF, VSAV, ACOR, 1 WM, IWM, F, JAC, PSOL, VNLS, RPAR, IPAR, KMI, KINDEX) C ########################################################### C EXTERNAL F, JAC, PSOL, VNLS REAL Y, YH, YH1, EWT, SAVF, VSAV, ACOR, WM, RPAR INTEGER LDYH, IWM, IPAR DIMENSION Y(*), YH(LDYH,*), YH1(*), EWT(*), SAVF(*), VSAV(*), 1 ACOR(*), WM(*), IWM(*), RPAR(*), IPAR(*) INTEGER KMI, KINDEX C----------------------------------------------------------------------- C Call sequence input -- Y, YH, LDYH, YH1, EWT, SAVF, VSAV, C ACOR, WM, IWM, F, JAC, PSOL, VNLS, RPAR, IPAR C Call sequence output -- YH, ACOR, WM, IWM C COMMON block variables accessed.. C /SVOD01/ ACNRM, EL(13), H, HMIN, HMXI, HNEW, HSCAL, RC, TAU(13), C TQ(5), TN, JCUR, JSTART, KFLAG, KUTH, C L, LMAX, MAXORD, MITER, N, NEWQ, NQ, NQWAIT C /SVOD02/ HU, NCFN, NETF, NFE, NQU, NST C C Subroutines called by SVSTEP.. F, SAXPY, CH_SCOPY, SSCAL, C SVJUST, VNLS, SVSET C Function routines called by SVSTEP.. SVNORM C----------------------------------------------------------------------- C SVSTEP performs one step of the integration of an initial value C problem for a system of ordinary differential equations. C SVSTEP calls subroutine VNLS for the solution of the nonlinear system C arising in the time step. Thus it is independent of the problem C Jacobian structure and the type of nonlinear system solution method. C SVSTEP returns a completion flag KFLAG (in COMMON). C A return with KFLAG = -1 or -2 means either ABS(H) = HMIN or 10 C consecutive failures occurred. On a return with KFLAG negative, C the values of TN and the YH array are as of the beginning of the last C step, and H is the last step size attempted. C C Communication with SVSTEP is done with the following variables.. C C Y = An array of length N used for the dependent variable vector. C YH = An LDYH by LMAX array containing the dependent variables C and their approximate scaled derivatives, where C LMAX = MAXORD + 1. YH(i,j+1) contains the approximate C j-th derivative of y(i), scaled by H**j/factorial(j) C (j = 0,1,...,NQ). On entry for the first step, the first C two columns of YH must be set from the initial values. C LDYH = A constant integer .ge. N, the first dimension of YH. C N is the number of ODEs in the system. C YH1 = A one-dimensional array occupying the same space as YH. C EWT = An array of length N containing multiplicative weights C for local error measurements. Local errors in y(i) are C compared to 1.0/EWT(i) in various error tests. C SAVF = An array of working storage, of length N. C also used for input of YH(*,MAXORD+2) when JSTART = -1 C and MAXORD .lt. the current order NQ. C VSAV = A work array of length N passed to subroutine VNLS. C ACOR = A work array of length N, used for the accumulated C corrections. On a successful return, ACOR(i) contains C the estimated one-step local error in y(i). C WM,IWM = Real and integer work arrays associated with matrix C operations in VNLS. C F = Dummy name for the user supplied subroutine for f. C JAC = Dummy name for the user supplied Jacobian subroutine. C PSOL = Dummy name for the subroutine passed to VNLS, for C possible use there. C VNLS = Dummy name for the nonlinear system solving subroutine, C whose real name is dependent on the method used. C RPAR, IPAR = Dummy names for user's real and integer work arrays. C----------------------------------------------------------------------- C C Type declarations for labeled COMMON block SVOD01 -------------------- C REAL ACNRM, CCMXJ, CONP, CRATE, DRC, EL, 1 ETA, ETAMAX, H, HMIN, HMXI, HNEW, HSCAL, PRL1, 2 RC, RL1, TAU, TQ, TN, UROUND INTEGER ICF, INIT, IPUP, JCUR, JSTART, JSV, KFLAG, KUTH, 1 L, LMAX, LYH, LEWT, LACOR, LSAVF, LWM, LIWM, 2 LOCJS, MAXORD, METH, MITER, MSBJ, MXHNIL, MXSTEP, 3 N, NEWH, NEWQ, NHNIL, NQ, NQNYH, NQWAIT, NSLJ, 4 NSLP, NYH C C Type declarations for labeled COMMON block SVOD02 -------------------- C REAL HU INTEGER NCFN, NETF, NFE, NJE, NLU, NNI, NQU, NST C C Type declarations for local variables -------------------------------- C REAL ADDON, BIAS1,BIAS2,BIAS3, CNQUOT, DDN, DSM, DUP, 1 ETACF, ETAMIN, ETAMX1, ETAMX2, ETAMX3, ETAMXF, 2 ETAQ, ETAQM1, ETAQP1, FLOTL, ONE, ONEPSM, 3 R, THRESH, TOLD, ZERO INTEGER I, I1, I2, IBACK, J, JB, KFC, KFH, MXNCF, NCF, NFLAG C C Type declaration for function subroutines called --------------------- C REAL SVNORM C----------------------------------------------------------------------- C The following Fortran-77 declaration is to cause the values of the C listed (local) variables to be saved between calls to this integrator. C----------------------------------------------------------------------- SAVE ADDON, BIAS1, BIAS2, BIAS3, 1 ETACF, ETAMIN, ETAMX1, ETAMX2, ETAMX3, ETAMXF, 2 KFC, KFH, MXNCF, ONEPSM, THRESH, ONE, ZERO C----------------------------------------------------------------------- COMMON /SVOD01/ ACNRM, CCMXJ, CONP, CRATE, DRC, EL(13), 1 ETA, ETAMAX, H, HMIN, HMXI, HNEW, HSCAL, PRL1, 2 RC, RL1, TAU(13), TQ(5), TN, UROUND, 3 ICF, INIT, IPUP, JCUR, JSTART, JSV, KFLAG, KUTH, 4 L, LMAX, LYH, LEWT, LACOR, LSAVF, LWM, LIWM, 5 LOCJS, MAXORD, METH, MITER, MSBJ, MXHNIL, MXSTEP, 6 N, NEWH, NEWQ, NHNIL, NQ, NQNYH, NQWAIT, NSLJ, 7 NSLP, NYH COMMON /SVOD02/ HU, NCFN, NETF, NFE, NJE, NLU, NNI, NQU, NST C DATA KFC/-3/, KFH/-7/, MXNCF/10/ DATA ADDON /1.0E-6/, BIAS1 /6.0E0/, BIAS2 /6.0E0/, 1 BIAS3 /10.0E0/, ETACF /0.25E0/, ETAMIN /0.1E0/, 2 ETAMXF /0.2E0/, ETAMX1 /1.0E4/, ETAMX2 /10.0E0/, 3 ETAMX3 /10.0E0/, ONEPSM /1.00001E0/, THRESH /1.5E0/ DATA ONE/1.0E0/, ZERO/0.0E0/ C KFLAG = 0 TOLD = TN NCF = 0 JCUR = 0 NFLAG = 0 IF (JSTART .GT. 0) GO TO 20 IF (JSTART .EQ. -1) GO TO 100 C----------------------------------------------------------------------- C On the first call, the order is set to 1, and other variables are C initialized. ETAMAX is the maximum ratio by which H can be increased C in a single step. It is normally 1.5, but is larger during the C first 10 steps to compensate for the small initial H. If a failure C occurs (in corrector convergence or error test), ETAMAX is set to 1 C for the next increase. C----------------------------------------------------------------------- LMAX = MAXORD + 1 NQ = 1 L = 2 NQNYH = NQ*LDYH TAU(1) = H PRL1 = ONE RC = ZERO ETAMAX = ETAMX1 NQWAIT = 2 HSCAL = H GO TO 200 C----------------------------------------------------------------------- C Take preliminary actions on a normal continuation step (JSTART.GT.0). C If the driver changed H, then ETA must be reset and NEWH set to 1. C If a change of order was dictated on the previous step, then C it is done here and appropriate adjustments in the history are made. C On an order decrease, the history array is adjusted by SVJUST. C On an order increase, the history array is augmented by a column. C On a change of step size H, the history array YH is rescaled. C----------------------------------------------------------------------- 20 CONTINUE IF (KUTH .EQ. 1) THEN ETA = MIN(ETA,H/HSCAL) NEWH = 1 ENDIF 50 IF (NEWH .EQ. 0) GO TO 200 IF (NEWQ .EQ. NQ) GO TO 150 IF (NEWQ .LT. NQ) THEN CALL SVJUST (YH, LDYH, -1) NQ = NEWQ L = NQ + 1 NQWAIT = L GO TO 150 ENDIF IF (NEWQ .GT. NQ) THEN CALL SVJUST (YH, LDYH, 1) NQ = NEWQ L = NQ + 1 NQWAIT = L GO TO 150 ENDIF C----------------------------------------------------------------------- C The following block handles preliminaries needed when JSTART = -1. C If N was reduced, zero out part of YH to avoid undefined references. C If MAXORD was reduced to a value less than the tentative order NEWQ, C then NQ is set to MAXORD, and a new H ratio ETA is chosen. C Otherwise, we take the same preliminary actions as for JSTART .gt. 0. C In any case, NQWAIT is reset to L = NQ + 1 to prevent further C changes in order for that many steps. C The new H ratio ETA is limited by the input H if KUTH = 1, C by HMIN if KUTH = 0, and by HMXI in any case. C Finally, the history array YH is rescaled. C----------------------------------------------------------------------- 100 CONTINUE LMAX = MAXORD + 1 IF (N .EQ. LDYH) GO TO 120 I1 = 1 + (NEWQ + 1)*LDYH I2 = (MAXORD + 1)*LDYH IF (I1 .GT. I2) GO TO 120 DO 110 I = I1, I2 110 YH1(I) = ZERO 120 IF (NEWQ .LE. MAXORD) GO TO 140 FLOTL = REAL(LMAX) IF (MAXORD .LT. NQ-1) THEN DDN = SVNORM (N, SAVF, EWT)/TQ(1) ETA = ONE/((BIAS1*DDN)**(ONE/FLOTL) + ADDON) ENDIF IF (MAXORD .EQ. NQ .AND. NEWQ .EQ. NQ+1) ETA = ETAQ IF (MAXORD .EQ. NQ-1 .AND. NEWQ .EQ. NQ+1) THEN ETA = ETAQM1 CALL SVJUST (YH, LDYH, -1) ENDIF IF (MAXORD .EQ. NQ-1 .AND. NEWQ .EQ. NQ) THEN DDN = SVNORM (N, SAVF, EWT)/TQ(1) ETA = ONE/((BIAS1*DDN)**(ONE/FLOTL) + ADDON) CALL SVJUST (YH, LDYH, -1) ENDIF ETA = MIN(ETA,ONE) NQ = MAXORD L = LMAX 140 IF (KUTH .EQ. 1) ETA = MIN(ETA,ABS(H/HSCAL)) IF (KUTH .EQ. 0) ETA = MAX(ETA,HMIN/ABS(HSCAL)) ETA = ETA/MAX(ONE,ABS(HSCAL)*HMXI*ETA) NEWH = 1 NQWAIT = L IF (NEWQ .LE. MAXORD) GO TO 50 C Rescale the history array for a change in H by a factor of ETA. ------ 150 R = ONE DO 180 J = 2, L R = R*ETA CALL SSCAL (N, R, YH(1,J), 1 ) 180 CONTINUE H = HSCAL*ETA HSCAL = H RC = RC*ETA NQNYH = NQ*LDYH C----------------------------------------------------------------------- C This section computes the predicted values by effectively C multiplying the YH array by the Pascal triangle matrix. C SVSET is called to calculate all integration coefficients. C RC is the ratio of new to old values of the coefficient H/EL(2)=h/l1. C----------------------------------------------------------------------- 200 TN = TN + H I1 = NQNYH + 1 DO 220 JB = 1, NQ I1 = I1 - LDYH DO 210 I = I1, NQNYH 210 YH1(I) = YH1(I) + YH1(I+LDYH) 220 CONTINUE CALL SVSET RL1 = ONE/EL(2) RC = RC*(RL1/PRL1) PRL1 = RL1 C C Call the nonlinear system solver. ------------------------------------ C CALL VNLS (Y, YH, LDYH, VSAV, SAVF, EWT, ACOR, IWM, WM, 1 F, JAC, PSOL, NFLAG, RPAR, IPAR, KMI, KINDEX) C IF (NFLAG .EQ. 0) GO TO 450 C----------------------------------------------------------------------- C The VNLS routine failed to achieve convergence (NFLAG .NE. 0). C The YH array is retracted to its values before prediction. C The step size H is reduced and the step is retried, if possible. C Otherwise, an error exit is taken. C----------------------------------------------------------------------- NCF = NCF + 1 NCFN = NCFN + 1 ETAMAX = ONE TN = TOLD I1 = NQNYH + 1 DO 430 JB = 1, NQ I1 = I1 - LDYH DO 420 I = I1, NQNYH 420 YH1(I) = YH1(I) - YH1(I+LDYH) 430 CONTINUE IF (NFLAG .LT. -1) GO TO 680 IF (ABS(H) .LE. HMIN*ONEPSM) GO TO 670 IF (NCF .EQ. MXNCF) GO TO 670 ETA = ETACF ETA = MAX(ETA,HMIN/ABS(H)) NFLAG = -1 GO TO 150 C----------------------------------------------------------------------- C The corrector has converged (NFLAG = 0). The local error test is C made and control passes to statement 500 if it fails. C----------------------------------------------------------------------- 450 CONTINUE DSM = ACNRM/TQ(2) IF (DSM .GT. ONE) GO TO 500 C----------------------------------------------------------------------- C After a successful step, update the YH and TAU arrays and decrement C NQWAIT. If NQWAIT is then 1 and NQ .lt. MAXORD, then ACOR is saved C for use in a possible order increase on the next step. C If ETAMAX = 1 (a failure occurred this step), keep NQWAIT .ge. 2. C----------------------------------------------------------------------- KFLAG = 0 NST = NST + 1 HU = H NQU = NQ DO 470 IBACK = 1, NQ I = L - IBACK 470 TAU(I+1) = TAU(I) TAU(1) = H DO 480 J = 1, L CALL SAXPY (N, EL(J), ACOR, 1, YH(1,J), 1 ) 480 CONTINUE NQWAIT = NQWAIT - 1 IF ((L .EQ. LMAX) .OR. (NQWAIT .NE. 1)) GO TO 490 CALL CH_SCOPY (N, ACOR, 1, YH(1,LMAX), 1 ) CONP = TQ(5) 490 IF (ETAMAX .NE. ONE) GO TO 560 IF (NQWAIT .LT. 2) NQWAIT = 2 NEWQ = NQ NEWH = 0 ETA = ONE HNEW = H GO TO 690 C----------------------------------------------------------------------- C The error test failed. KFLAG keeps track of multiple failures. C Restore TN and the YH array to their previous values, and prepare C to try the step again. Compute the optimum step size for the C same order. After repeated failures, H is forced to decrease C more rapidly. C----------------------------------------------------------------------- 500 KFLAG = KFLAG - 1 NETF = NETF + 1 NFLAG = -2 TN = TOLD I1 = NQNYH + 1 DO 520 JB = 1, NQ I1 = I1 - LDYH DO 510 I = I1, NQNYH 510 YH1(I) = YH1(I) - YH1(I+LDYH) 520 CONTINUE IF (ABS(H) .LE. HMIN*ONEPSM) GO TO 660 ETAMAX = ONE IF (KFLAG .LE. KFC) GO TO 530 C Compute ratio of new H to current H at the current order. ------------ FLOTL = REAL(L) ETA = ONE/((BIAS2*DSM)**(ONE/FLOTL) + ADDON) ETA = MAX(ETA,HMIN/ABS(H),ETAMIN) IF ((KFLAG .LE. -2) .AND. (ETA .GT. ETAMXF)) ETA = ETAMXF GO TO 150 C----------------------------------------------------------------------- C Control reaches this section if 3 or more consecutive failures C have occurred. It is assumed that the elements of the YH array C have accumulated errors of the wrong order. The order is reduced C by one, if possible. Then H is reduced by a factor of 0.1 and C the step is retried. After a total of 7 consecutive failures, C an exit is taken with KFLAG = -1. C----------------------------------------------------------------------- 530 IF (KFLAG .EQ. KFH) GO TO 660 IF (NQ .EQ. 1) GO TO 540 ETA = MAX(ETAMIN,HMIN/ABS(H)) CALL SVJUST (YH, LDYH, -1) L = NQ NQ = NQ - 1 NQWAIT = L GO TO 150 540 ETA = MAX(ETAMIN,HMIN/ABS(H)) H = H*ETA HSCAL = H TAU(1) = H C C*UPG*MNH C CALL F (N, TN, Y, SAVF, RPAR, IPAR, KMI, KINDEX) C C*UPG*MNH C NFE = NFE + 1 DO 550 I = 1, N 550 YH(I,2) = H*SAVF(I) NQWAIT = 10 GO TO 200 C----------------------------------------------------------------------- C If NQWAIT = 0, an increase or decrease in order by one is considered. C Factors ETAQ, ETAQM1, ETAQP1 are computed by which H could C be multiplied at order q, q-1, or q+1, respectively. C The largest of these is determined, and the new order and C step size set accordingly. C A change of H or NQ is made only if H increases by at least a C factor of THRESH. If an order change is considered and rejected, C then NQWAIT is set to 2 (reconsider it after 2 steps). C----------------------------------------------------------------------- C Compute ratio of new H to current H at the current order. ------------ 560 FLOTL = REAL(L) ETAQ = ONE/((BIAS2*DSM)**(ONE/FLOTL) + ADDON) IF (NQWAIT .NE. 0) GO TO 600 NQWAIT = 2 ETAQM1 = ZERO IF (NQ .EQ. 1) GO TO 570 C Compute ratio of new H to current H at the current order less one. --- DDN = SVNORM (N, YH(1,L), EWT)/TQ(1) ETAQM1 = ONE/((BIAS1*DDN)**(ONE/(FLOTL - ONE)) + ADDON) 570 ETAQP1 = ZERO IF (L .EQ. LMAX) GO TO 580 C Compute ratio of new H to current H at current order plus one. ------- CNQUOT = (TQ(5)/CONP)*(H/TAU(2))**L DO 575 I = 1, N 575 SAVF(I) = ACOR(I) - CNQUOT*YH(I,LMAX) DUP = SVNORM (N, SAVF, EWT)/TQ(3) ETAQP1 = ONE/((BIAS3*DUP)**(ONE/(FLOTL + ONE)) + ADDON) 580 IF (ETAQ .GE. ETAQP1) GO TO 590 IF (ETAQP1 .GT. ETAQM1) GO TO 620 GO TO 610 590 IF (ETAQ .LT. ETAQM1) GO TO 610 600 ETA = ETAQ NEWQ = NQ GO TO 630 610 ETA = ETAQM1 NEWQ = NQ - 1 GO TO 630 620 ETA = ETAQP1 NEWQ = NQ + 1 CALL CH_SCOPY (N, ACOR, 1, YH(1,LMAX), 1) C Test tentative new H against THRESH, ETAMAX, and HMXI, then exit. ---- 630 IF (ETA .LT. THRESH .OR. ETAMAX .EQ. ONE) GO TO 640 ETA = MIN(ETA,ETAMAX) ETA = ETA/MAX(ONE,ABS(H)*HMXI*ETA) NEWH = 1 HNEW = H*ETA GO TO 690 640 NEWQ = NQ NEWH = 0 ETA = ONE HNEW = H GO TO 690 C----------------------------------------------------------------------- C All returns are made through this section. C On a successful return, ETAMAX is reset and ACOR is scaled. C----------------------------------------------------------------------- 660 KFLAG = -1 GO TO 720 670 KFLAG = -2 GO TO 720 680 IF (NFLAG .EQ. -2) KFLAG = -3 IF (NFLAG .EQ. -3) KFLAG = -4 GO TO 720 690 ETAMAX = ETAMX3 IF (NST .LE. 10) ETAMAX = ETAMX2 700 R = ONE/TQ(2) CALL SSCAL (N, R, ACOR, 1) 720 JSTART = 1 RETURN END SUBROUTINE SVSTEP C####################################################################### C CDECK SVSET C ################ SUBROUTINE SVSET C ################ C----------------------------------------------------------------------- C Call sequence communication.. None C COMMON block variables accessed.. C /SVOD01/ -- EL(13), H, TAU(13), TQ(5), L(= NQ + 1), C METH, NQ, NQWAIT C C Subroutines called by SVSET.. None C Function routines called by SVSET.. None C----------------------------------------------------------------------- C SVSET is called by SVSTEP and sets coefficients for use there. C C For each order NQ, the coefficients in EL are calculated by use of C the generating polynomial lambda(x), with coefficients EL(i). C lambda(x) = EL(1) + EL(2)*x + ... + EL(NQ+1)*(x**NQ). C For the backward differentiation formulas, C NQ-1 C lambda(x) = (1 + x/xi*(NQ)) * product (1 + x/xi(i) ) . C i = 1 C For the Adams formulas, C NQ-1 C (d/dx) lambda(x) = c * product (1 + x/xi(i) ) , C i = 1 C lambda(-1) = 0, lambda(0) = 1, C where c is a normalization constant. C In both cases, xi(i) is defined by C H*xi(i) = t sub n - t sub (n-i) C = H + TAU(1) + TAU(2) + ... TAU(i-1). C C C In addition to variables described previously, communication C with SVSET uses the following.. C TAU = A vector of length 13 containing the past NQ values C of H. C EL = A vector of length 13 in which vset stores the C coefficients for the corrector formula. C TQ = A vector of length 5 in which vset stores constants C used for the convergence test, the error test, and the C selection of H at a new order. C METH = The basic method indicator. C NQ = The current order. C L = NQ + 1, the length of the vector stored in EL, and C the number of columns of the YH array being used. C NQWAIT = A counter controlling the frequency of order changes. C An order change is about to be considered if NQWAIT = 1. C----------------------------------------------------------------------- C C Type declarations for labeled COMMON block SVOD01 -------------------- C REAL ACNRM, CCMXJ, CONP, CRATE, DRC, EL, 1 ETA, ETAMAX, H, HMIN, HMXI, HNEW, HSCAL, PRL1, 2 RC, RL1, TAU, TQ, TN, UROUND INTEGER ICF, INIT, IPUP, JCUR, JSTART, JSV, KFLAG, KUTH, 1 L, LMAX, LYH, LEWT, LACOR, LSAVF, LWM, LIWM, 2 LOCJS, MAXORD, METH, MITER, MSBJ, MXHNIL, MXSTEP, 3 N, NEWH, NEWQ, NHNIL, NQ, NQNYH, NQWAIT, NSLJ, 4 NSLP, NYH C C Type declarations for local variables -------------------------------- C REAL AHATN0, ALPH0, CNQM1, CORTES, CSUM, ELP, EM, 1 EM0, FLOTI, FLOTL, FLOTNQ, HSUM, ONE, RXI, RXIS, S, SIX, 2 T1, T2, T3, T4, T5, T6, TWO, XI, ZERO INTEGER I, IBACK, J, JP1, NQM1, NQM2 C DIMENSION EM(13) C----------------------------------------------------------------------- C The following Fortran-77 declaration is to cause the values of the C listed (local) variables to be saved between calls to this integrator. C----------------------------------------------------------------------- SAVE CORTES, ONE, SIX, TWO, ZERO C COMMON /SVOD01/ ACNRM, CCMXJ, CONP, CRATE, DRC, EL(13), 1 ETA, ETAMAX, H, HMIN, HMXI, HNEW, HSCAL, PRL1, 2 RC, RL1, TAU(13), TQ(5), TN, UROUND, 3 ICF, INIT, IPUP, JCUR, JSTART, JSV, KFLAG, KUTH, 4 L, LMAX, LYH, LEWT, LACOR, LSAVF, LWM, LIWM, 5 LOCJS, MAXORD, METH, MITER, MSBJ, MXHNIL, MXSTEP, 6 N, NEWH, NEWQ, NHNIL, NQ, NQNYH, NQWAIT, NSLJ, 7 NSLP, NYH C DATA CORTES /0.1E0/ DATA ONE /1.0E0/, SIX /6.0E0/, TWO /2.0E0/, ZERO /0.0E0/ C FLOTL = REAL(L) NQM1 = NQ - 1 NQM2 = NQ - 2 GO TO (100, 200), METH C C Set coefficients for Adams methods. ---------------------------------- 100 IF (NQ .NE. 1) GO TO 110 EL(1) = ONE EL(2) = ONE TQ(1) = ONE TQ(2) = TWO TQ(3) = SIX*TQ(2) TQ(5) = ONE GO TO 300 110 HSUM = H EM(1) = ONE FLOTNQ = FLOTL - ONE DO 115 I = 2, L 115 EM(I) = ZERO DO 150 J = 1, NQM1 IF ((J .NE. NQM1) .OR. (NQWAIT .NE. 1)) GO TO 130 S = ONE CSUM = ZERO DO 120 I = 1, NQM1 CSUM = CSUM + S*EM(I)/REAL(I+1) 120 S = -S TQ(1) = EM(NQM1)/(FLOTNQ*CSUM) 130 RXI = H/HSUM DO 140 IBACK = 1, J I = (J + 2) - IBACK 140 EM(I) = EM(I) + EM(I-1)*RXI HSUM = HSUM + TAU(J) 150 CONTINUE C Compute integral from -1 to 0 of polynomial and of x times it. ------- S = ONE EM0 = ZERO CSUM = ZERO DO 160 I = 1, NQ FLOTI = REAL(I) EM0 = EM0 + S*EM(I)/FLOTI CSUM = CSUM + S*EM(I)/(FLOTI+ONE) 160 S = -S C In EL, form coefficients of normalized integrated polynomial. -------- S = ONE/EM0 EL(1) = ONE DO 170 I = 1, NQ 170 EL(I+1) = S*EM(I)/REAL(I) XI = HSUM/H TQ(2) = XI*EM0/CSUM TQ(5) = XI/EL(L) IF (NQWAIT .NE. 1) GO TO 300 C For higher order control constant, multiply polynomial by 1+x/xi(q). - RXI = ONE/XI DO 180 IBACK = 1, NQ I = (L + 1) - IBACK 180 EM(I) = EM(I) + EM(I-1)*RXI C Compute integral of polynomial. -------------------------------------- S = ONE CSUM = ZERO DO 190 I = 1, L CSUM = CSUM + S*EM(I)/REAL(I+1) 190 S = -S TQ(3) = FLOTL*EM0/CSUM GO TO 300 C C Set coefficients for BDF methods. ------------------------------------ 200 DO 210 I = 3, L 210 EL(I) = ZERO EL(1) = ONE EL(2) = ONE ALPH0 = -ONE AHATN0 = -ONE HSUM = H RXI = ONE RXIS = ONE IF (NQ .EQ. 1) GO TO 240 DO 230 J = 1, NQM2 C In EL, construct coefficients of (1+x/xi(1))*...*(1+x/xi(j+1)). ------ HSUM = HSUM + TAU(J) RXI = H/HSUM JP1 = J + 1 ALPH0 = ALPH0 - ONE/REAL(JP1) DO 220 IBACK = 1, JP1 I = (J + 3) - IBACK 220 EL(I) = EL(I) + EL(I-1)*RXI 230 CONTINUE ALPH0 = ALPH0 - ONE/REAL(NQ) RXIS = -EL(2) - ALPH0 HSUM = HSUM + TAU(NQM1) RXI = H/HSUM AHATN0 = -EL(2) - RXI DO 235 IBACK = 1, NQ I = (NQ + 2) - IBACK 235 EL(I) = EL(I) + EL(I-1)*RXIS 240 T1 = ONE - AHATN0 + ALPH0 T2 = ONE + REAL(NQ)*T1 TQ(2) = ABS(ALPH0*T2/T1) TQ(5) = ABS(T2/(EL(L)*RXI/RXIS)) IF (NQWAIT .NE. 1) GO TO 300 CNQM1 = RXIS/EL(L) T3 = ALPH0 + ONE/REAL(NQ) T4 = AHATN0 + RXI ELP = T3/(ONE - T4 + T3) TQ(1) = ABS(ELP/CNQM1) HSUM = HSUM + TAU(NQ) RXI = H/HSUM T5 = ALPH0 - ONE/REAL(NQ+1) T6 = AHATN0 - RXI ELP = T2/(ONE - T6 + T5) TQ(3) = ABS(ELP*RXI*(FLOTL + ONE)*T5) 300 TQ(4) = CORTES*TQ(2) RETURN END C####################################################################### C CDECK SVJUST C ################################## SUBROUTINE SVJUST (YH, LDYH, IORD) C ################################## REAL YH INTEGER LDYH, IORD DIMENSION YH(LDYH,*) C----------------------------------------------------------------------- C Call sequence input -- YH, LDYH, IORD C Call sequence output -- YH C COMMON block input -- NQ, METH, LMAX, HSCAL, TAU(13), N C COMMON block variables accessed.. C /SVOD01/ -- HSCAL, TAU(13), LMAX, METH, N, NQ, C C Subroutines called by SVJUST.. SAXPY C Function routines called by SVJUST.. None C----------------------------------------------------------------------- C This subroutine adjusts the YH array on reduction of order, C and also when the order is increased for the stiff option (METH = 2). C Communication with SVJUST uses the following.. C IORD = An integer flag used when METH = 2 to indicate an order C increase (IORD = +1) or an order decrease (IORD = -1). C HSCAL = Step size H used in scaling of Nordsieck array YH. C (If IORD = +1, SVJUST assumes that HSCAL = TAU(1).) C See References 1 and 2 for details. C----------------------------------------------------------------------- C C Type declarations for labeled COMMON block SVOD01 -------------------- C REAL ACNRM, CCMXJ, CONP, CRATE, DRC, EL, 1 ETA, ETAMAX, H, HMIN, HMXI, HNEW, HSCAL, PRL1, 2 RC, RL1, TAU, TQ, TN, UROUND INTEGER ICF, INIT, IPUP, JCUR, JSTART, JSV, KFLAG, KUTH, 1 L, LMAX, LYH, LEWT, LACOR, LSAVF, LWM, LIWM, 2 LOCJS, MAXORD, METH, MITER, MSBJ, MXHNIL, MXSTEP, 3 N, NEWH, NEWQ, NHNIL, NQ, NQNYH, NQWAIT, NSLJ, 4 NSLP, NYH C C Type declarations for local variables -------------------------------- C REAL ALPH0, ALPH1, HSUM, ONE, PROD, T1, XI,XIOLD, ZERO INTEGER I, IBACK, J, JP1, LP1, NQM1, NQM2, NQP1 C----------------------------------------------------------------------- C The following Fortran-77 declaration is to cause the values of the C listed (local) variables to be saved between calls to this integrator. C----------------------------------------------------------------------- SAVE ONE, ZERO C COMMON /SVOD01/ ACNRM, CCMXJ, CONP, CRATE, DRC, EL(13), 1 ETA, ETAMAX, H, HMIN, HMXI, HNEW, HSCAL, PRL1, 2 RC, RL1, TAU(13), TQ(5), TN, UROUND, 3 ICF, INIT, IPUP, JCUR, JSTART, JSV, KFLAG, KUTH, 4 L, LMAX, LYH, LEWT, LACOR, LSAVF, LWM, LIWM, 5 LOCJS, MAXORD, METH, MITER, MSBJ, MXHNIL, MXSTEP, 6 N, NEWH, NEWQ, NHNIL, NQ, NQNYH, NQWAIT, NSLJ, 7 NSLP, NYH C DATA ONE /1.0E0/, ZERO /0.0E0/ C IF ((NQ .EQ. 2) .AND. (IORD .NE. 1)) RETURN NQM1 = NQ - 1 NQM2 = NQ - 2 GO TO (100, 200), METH C----------------------------------------------------------------------- C Nonstiff option... C Check to see if the order is being increased or decreased. C----------------------------------------------------------------------- 100 CONTINUE IF (IORD .EQ. 1) GO TO 180 C Order decrease. ------------------------------------------------------ DO 110 J = 1, LMAX 110 EL(J) = ZERO EL(2) = ONE HSUM = ZERO DO 130 J = 1, NQM2 C Construct coefficients of x*(x+xi(1))*...*(x+xi(j)). ----------------- HSUM = HSUM + TAU(J) XI = HSUM/HSCAL JP1 = J + 1 DO 120 IBACK = 1, JP1 I = (J + 3) - IBACK 120 EL(I) = EL(I)*XI + EL(I-1) 130 CONTINUE C Construct coefficients of integrated polynomial. --------------------- DO 140 J = 2, NQM1 140 EL(J+1) = REAL(NQ)*EL(J)/REAL(J) C Subtract correction terms from YH array. ----------------------------- DO 170 J = 3, NQ DO 160 I = 1, N 160 YH(I,J) = YH(I,J) - YH(I,L)*EL(J) 170 CONTINUE RETURN C Order increase. ------------------------------------------------------ C Zero out next column in YH array. ------------------------------------ 180 CONTINUE LP1 = L + 1 DO 190 I = 1, N 190 YH(I,LP1) = ZERO RETURN C----------------------------------------------------------------------- C Stiff option... C Check to see if the order is being increased or decreased. C----------------------------------------------------------------------- 200 CONTINUE IF (IORD .EQ. 1) GO TO 300 C Order decrease. ------------------------------------------------------ DO 210 J = 1, LMAX 210 EL(J) = ZERO EL(3) = ONE HSUM = ZERO DO 230 J = 1,NQM2 C Construct coefficients of x*x*(x+xi(1))*...*(x+xi(j)). --------------- HSUM = HSUM + TAU(J) XI = HSUM/HSCAL JP1 = J + 1 DO 220 IBACK = 1, JP1 I = (J + 4) - IBACK 220 EL(I) = EL(I)*XI + EL(I-1) 230 CONTINUE C Subtract correction terms from YH array. ----------------------------- DO 250 J = 3,NQ DO 240 I = 1, N 240 YH(I,J) = YH(I,J) - YH(I,L)*EL(J) 250 CONTINUE RETURN C Order increase. ------------------------------------------------------ 300 DO 310 J = 1, LMAX 310 EL(J) = ZERO EL(3) = ONE ALPH0 = -ONE ALPH1 = ONE PROD = ONE XIOLD = ONE HSUM = HSCAL IF (NQ .EQ. 1) GO TO 340 DO 330 J = 1, NQM1 C Construct coefficients of x*x*(x+xi(1))*...*(x+xi(j)). --------------- JP1 = J + 1 HSUM = HSUM + TAU(JP1) XI = HSUM/HSCAL PROD = PROD*XI ALPH0 = ALPH0 - ONE/REAL(JP1) ALPH1 = ALPH1 + ONE/XI DO 320 IBACK = 1, JP1 I = (J + 4) - IBACK 320 EL(I) = EL(I)*XIOLD + EL(I-1) XIOLD = XI 330 CONTINUE 340 CONTINUE T1 = (-ALPH0 - ALPH1)/PROD C Load column L + 1 in YH array. --------------------------------------- LP1 = L + 1 DO 350 I = 1, N 350 YH(I,LP1) = T1*YH(I,LMAX) C Add correction terms to YH array. ------------------------------------ NQP1 = NQ + 1 DO 370 J = 3, NQP1 CALL SAXPY (N, EL(J), YH(1,LP1), 1, YH(1,J), 1 ) 370 CONTINUE RETURN END SUBROUTINE SVJUST C C####################################################################### C CDECK SVNLSD C ############################################################### SUBROUTINE SVNLSD (Y, YH, LDYH, VSAV, SAVF, EWT, ACOR, IWM, WM, 1 F, JAC, PDUM, NFLAG, RPAR, IPAR, KMI, KINDEX) C ############################################################### EXTERNAL F, JAC, PDUM REAL Y, YH, VSAV, SAVF, EWT, ACOR, WM, RPAR INTEGER LDYH, IWM, NFLAG, IPAR DIMENSION Y(*), YH(LDYH,*), VSAV(*), SAVF(*), EWT(*), ACOR(*), 1 IWM(*), WM(*), RPAR(*), IPAR(*) INTEGER KMI,KINDEX C----------------------------------------------------------------------- C Call sequence input -- Y, YH, LDYH, SAVF, EWT, ACOR, IWM, WM, C F, JAC, NFLAG, RPAR, IPAR C Call sequence output -- YH, ACOR, WM, IWM, NFLAG C COMMON block variables accessed.. C /SVOD01/ ACNRM, CRATE, DRC, H, RC, RL1, TQ(5), TN, ICF, C JCUR, METH, MITER, N, NSLP C /SVOD02/ HU, NCFN, NETF, NFE, NJE, NLU, NNI, NQU, NST C C Subroutines called by SVNLSD.. F, SAXPY, CH_SCOPY, SSCAL, SVJAC, SVSOL C Function routines called by SVNLSD.. SVNORM C----------------------------------------------------------------------- C Subroutine SVNLSD is a nonlinear system solver, which uses functional C iteration or a chord (modified Newton) method. For the chord method C direct linear algebraic system solvers are used. Subroutine SVNLSD C then handles the corrector phase of this integration package. C C Communication with SVNLSD is done with the following variables. (For C more details, please see the comments in the driver subroutine.) C C Y = The dependent variable, a vector of length N, input. C YH = The Nordsieck (Taylor) array, LDYH by LMAX, input C and output. On input, it contains predicted values. C LDYH = A constant .ge. N, the first dimension of YH, input. C VSAV = Unused work array. C SAVF = A work array of length N. C EWT = An error weight vector of length N, input. C ACOR = A work array of length N, used for the accumulated C corrections to the predicted y vector. C WM,IWM = Real and integer work arrays associated with matrix C operations in chord iteration (MITER .ne. 0). C F = Dummy name for user supplied routine for f. C JAC = Dummy name for user supplied Jacobian routine. C PDUM = Unused dummy subroutine name. Included for uniformity C over collection of integrators. C NFLAG = Input/output flag, with values and meanings as follows.. C INPUT C 0 first call for this time step. C -1 convergence failure in previous call to SVNLSD. C -2 error test failure in SVSTEP. C OUTPUT C 0 successful completion of nonlinear solver. C -1 convergence failure or singular matrix. C -2 unrecoverable error in matrix preprocessing C (cannot occur here). C -3 unrecoverable error in solution (cannot occur C here). C RPAR, IPAR = Dummy names for user's real and integer work arrays. C C IPUP = Own variable flag with values and meanings as follows.. C 0, do not update the Newton matrix. C MITER .ne. 0, update Newton matrix, because it is the C initial step, order was changed, the error C test failed, or an update is indicated by C the scalar RC or step counter NST. C C For more details, see comments in driver subroutine. C----------------------------------------------------------------------- C Type declarations for labeled COMMON block SVOD01 -------------------- C REAL ACNRM, CCMXJ, CONP, CRATE, DRC, EL, 1 ETA, ETAMAX, H, HMIN, HMXI, HNEW, HSCAL, PRL1, 2 RC, RL1, TAU, TQ, TN, UROUND INTEGER ICF, INIT, IPUP, JCUR, JSTART, JSV, KFLAG, KUTH, 1 L, LMAX, LYH, LEWT, LACOR, LSAVF, LWM, LIWM, 2 LOCJS, MAXORD, METH, MITER, MSBJ, MXHNIL, MXSTEP, 3 N, NEWH, NEWQ, NHNIL, NQ, NQNYH, NQWAIT, NSLJ, 4 NSLP, NYH C C Type declarations for labeled COMMON block SVOD02 -------------------- C REAL HU INTEGER NCFN, NETF, NFE, NJE, NLU, NNI, NQU, NST C C Type declarations for local variables -------------------------------- C REAL CCMAX, CRDOWN, CSCALE, DCON, DEL, DELP, ONE, 1 RDIV, TWO, ZERO INTEGER I, IERPJ, IERSL, M, MAXCOR, MSBP C C Type declaration for function subroutines called --------------------- C REAL SVNORM C----------------------------------------------------------------------- C The following Fortran-77 declaration is to cause the values of the C listed (local) variables to be saved between calls to this integrator. C----------------------------------------------------------------------- SAVE CCMAX, CRDOWN, MAXCOR, MSBP, RDIV, ONE, TWO, ZERO C COMMON /SVOD01/ ACNRM, CCMXJ, CONP, CRATE, DRC, EL(13), 1 ETA, ETAMAX, H, HMIN, HMXI, HNEW, HSCAL, PRL1, 2 RC, RL1, TAU(13), TQ(5), TN, UROUND, 3 ICF, INIT, IPUP, JCUR, JSTART, JSV, KFLAG, KUTH, 4 L, LMAX, LYH, LEWT, LACOR, LSAVF, LWM, LIWM, 5 LOCJS, MAXORD, METH, MITER, MSBJ, MXHNIL, MXSTEP, 6 N, NEWH, NEWQ, NHNIL, NQ, NQNYH, NQWAIT, NSLJ, 7 NSLP, NYH COMMON /SVOD02/ HU, NCFN, NETF, NFE, NJE, NLU, NNI, NQU, NST C DATA CCMAX /0.3E0/, CRDOWN /0.3E0/, MAXCOR /3/, MSBP /20/, 1 RDIV /2.0E0/ DATA ONE /1.0E0/, TWO /2.0E0/, ZERO /0.0E0/ C----------------------------------------------------------------------- C On the first step, on a change of method order, or after a C nonlinear convergence failure with NFLAG = -2, set IPUP = MITER C to force a Jacobian update when MITER .ne. 0. C----------------------------------------------------------------------- IF (JSTART .EQ. 0) NSLP = 0 IF (NFLAG .EQ. 0) ICF = 0 IF (NFLAG .EQ. -2) IPUP = MITER IF ( (JSTART .EQ. 0) .OR. (JSTART .EQ. -1) ) IPUP = MITER C If this is functional iteration, set CRATE .eq. 1 and drop to 220 IF (MITER .EQ. 0) THEN CRATE = ONE GO TO 220 ENDIF C----------------------------------------------------------------------- C RC is the ratio of new to old values of the coefficient H/EL(2)=h/l1. C When RC differs from 1 by more than CCMAX, IPUP is set to MITER C to force SVJAC to be called, if a Jacobian is involved. C In any case, SVJAC is called at least every MSBP steps. C----------------------------------------------------------------------- DRC = ABS(RC-ONE) IF (DRC .GT. CCMAX .OR. NST .GE. NSLP+MSBP) IPUP = MITER C----------------------------------------------------------------------- C Up to MAXCOR corrector iterations are taken. A convergence test is C made on the r.m.s. norm of each correction, weighted by the error C weight vector EWT. The sum of the corrections is accumulated in the C vector ACOR(i). The YH array is not altered in the corrector loop. C----------------------------------------------------------------------- 220 M = 0 DELP = ZERO CALL CH_SCOPY (N, YH(1,1), 1, Y, 1 ) C C*UPG*MNH C CALL F (N, TN, Y, SAVF, RPAR, IPAR, KMI, KINDEX) C C*UPG*MNH C NFE = NFE + 1 IF (IPUP .LE. 0) GO TO 250 C----------------------------------------------------------------------- C If indicated, the matrix P = I - h*rl1*J is reevaluated and C preprocessed before starting the corrector iteration. IPUP is set C to 0 as an indicator that this has been done. C----------------------------------------------------------------------- CALL SVJAC (Y, YH, LDYH, EWT, ACOR, SAVF, WM, IWM, F, JAC, IERPJ, 1 RPAR, IPAR, KMI, KINDEX) IPUP = 0 RC = ONE DRC = ZERO CRATE = ONE NSLP = NST C If matrix is singular, take error return to force cut in step size. -- IF (IERPJ .NE. 0) GO TO 430 250 DO 260 I = 1,N 260 ACOR(I) = ZERO C This is a looping point for the corrector iteration. ----------------- 270 IF (MITER .NE. 0) GO TO 350 C----------------------------------------------------------------------- C In the case of functional iteration, update Y directly from C the result of the last function evaluation. C----------------------------------------------------------------------- DO 280 I = 1,N 280 SAVF(I) = RL1*(H*SAVF(I) - YH(I,2)) DO 290 I = 1,N 290 Y(I) = SAVF(I) - ACOR(I) DEL = SVNORM (N, Y, EWT) DO 300 I = 1,N 300 Y(I) = YH(I,1) + SAVF(I) CALL CH_SCOPY (N, SAVF, 1, ACOR, 1) GO TO 400 C----------------------------------------------------------------------- C In the case of the chord method, compute the corrector error, C and solve the linear system with that as right-hand side and C P as coefficient matrix. The correction is scaled by the factor C 2/(1+RC) to account for changes in h*rl1 since the last SVJAC call. C----------------------------------------------------------------------- 350 DO 360 I = 1,N 360 Y(I) = (RL1*H)*SAVF(I) - (RL1*YH(I,2) + ACOR(I)) CALL SVSOL (WM, IWM, Y, IERSL) NNI = NNI + 1 IF (IERSL .GT. 0) GO TO 410 IF (METH .EQ. 2 .AND. RC .NE. ONE) THEN CSCALE = TWO/(ONE + RC) CALL SSCAL (N, CSCALE, Y, 1) ENDIF DEL = SVNORM (N, Y, EWT) CALL SAXPY (N, ONE, Y, 1, ACOR, 1) DO 380 I = 1,N 380 Y(I) = YH(I,1) + ACOR(I) C----------------------------------------------------------------------- C Test for convergence. If M .gt. 0, an estimate of the convergence C rate constant is stored in CRATE, and this is used in the test. C----------------------------------------------------------------------- 400 IF (M .NE. 0) CRATE = MAX(CRDOWN*CRATE,DEL/DELP) DCON = DEL*MIN(ONE,CRATE)/TQ(4) IF (DCON .LE. ONE) GO TO 450 M = M + 1 IF (M .EQ. MAXCOR) GO TO 410 IF (M .GE. 2 .AND. DEL .GT. RDIV*DELP) GO TO 410 DELP = DEL C C*UPG*MNH C CALL F (N, TN, Y, SAVF, RPAR, IPAR, KMI, KINDEX) C C*UPG*MNH C NFE = NFE + 1 GO TO 270 C 410 IF (MITER .EQ. 0 .OR. JCUR .EQ. 1) GO TO 430 ICF = 1 IPUP = MITER GO TO 220 C 430 CONTINUE NFLAG = -1 ICF = 2 IPUP = MITER RETURN C C Return for successful step. ------------------------------------------ 450 NFLAG = 0 JCUR = 0 ICF = 0 IF (M .EQ. 0) ACNRM = DEL IF (M .GT. 0) ACNRM = SVNORM (N, ACOR, EWT) RETURN END SUBROUTINE SVNLSD C C####################################################################### C CDECK SVJAC C ################################################################ SUBROUTINE SVJAC (Y, YH, LDYH, EWT, FTEM, SAVF, WM, IWM, F, JAC, 1 IERPJ, RPAR, IPAR, KMI, KINDEX) C ################################################################ EXTERNAL F, JAC REAL Y, YH, EWT, FTEM, SAVF, WM, RPAR INTEGER LDYH, IWM, IERPJ, IPAR DIMENSION Y(*), YH(LDYH,*), EWT(*), FTEM(*), SAVF(*), 1 WM(*), IWM(*), RPAR(*), IPAR(*) INTEGER KMI, KINDEX C----------------------------------------------------------------------- C Call sequence input -- Y, YH, LDYH, EWT, FTEM, SAVF, WM, IWM, C F, JAC, RPAR, IPAR C Call sequence output -- WM, IWM, IERPJ C COMMON block variables accessed.. C /SVOD01/ CCMXJ, DRC, H, RL1, TN, UROUND, ICF, JCUR, LOCJS, C MSBJ, NSLJ C /SVOD02/ NFE, NST, NJE, NLU C C Subroutines called by SVJAC.. F, JAC, SACOPY, CH_SCOPY, SGBFA, SGEFA, C SSCAL C Function routines called by SVJAC.. SVNORM C----------------------------------------------------------------------- C SVJAC is called by SVSTEP to compute and process the matrix C P = I - h*rl1*J , where J is an approximation to the Jacobian. C Here J is computed by the user-supplied routine JAC if C MITER = 1 or 4, or by finite differencing if MITER = 2, 3, or 5. C If MITER = 3, a diagonal approximation to J is used. C If JSV = -1, J is computed from scratch in all cases. C If JSV = 1 and MITER = 1, 2, 4, or 5, and if the saved value of J is C considered acceptable, then P is constructed from the saved J. C J is stored in wm and replaced by P. If MITER .ne. 3, P is then C subjected to LU decomposition in preparation for later solution C of linear systems with P as coefficient matrix. This is done C by SGEFA if MITER = 1 or 2, and by SGBFA if MITER = 4 or 5. C C Communication with SVJAC is done with the following variables. (For C more details, please see the comments in the driver subroutine.) C Y = Vector containing predicted values on entry. C YH = The Nordsieck array, an LDYH by LMAX array, input. C LDYH = A constant .ge. N, the first dimension of YH, input. C EWT = An error weight vector of length N. C SAVF = Array containing f evaluated at predicted y, input. C WM = Real work space for matrices. In the output, it containS C the inverse diagonal matrix if MITER = 3 and the LU C decomposition of P if MITER is 1, 2 , 4, or 5. C Storage of matrix elements starts at WM(3). C Storage of the saved Jacobian starts at WM(LOCJS). C WM also contains the following matrix-related data.. C WM(1) = SQRT(UROUND), used in numerical Jacobian step. C WM(2) = H*RL1, saved for later use if MITER = 3. C IWM = Integer work space containing pivot information, C starting at IWM(31), if MITER is 1, 2, 4, or 5. C IWM also contains band parameters ML = IWM(1) and C MU = IWM(2) if MITER is 4 or 5. C F = Dummy name for the user supplied subroutine for f. C JAC = Dummy name for the user supplied Jacobian subroutine. C RPAR, IPAR = Dummy names for user's real and integer work arrays. C RL1 = 1/EL(2) (input). C IERPJ = Output error flag, = 0 if no trouble, 1 if the P C matrix is found to be singular. C JCUR = Output flag to indicate whether the Jacobian matrix C (or approximation) is now current. C JCUR = 0 means J is not current. C JCUR = 1 means J is current. C----------------------------------------------------------------------- C C Type declarations for labeled COMMON block SVOD01 -------------------- C REAL ACNRM, CCMXJ, CONP, CRATE, DRC, EL, 1 ETA, ETAMAX, H, HMIN, HMXI, HNEW, HSCAL, PRL1, 2 RC, RL1, TAU, TQ, TN, UROUND INTEGER ICF, INIT, IPUP, JCUR, JSTART, JSV, KFLAG, KUTH, 1 L, LMAX, LYH, LEWT, LACOR, LSAVF, LWM, LIWM, 2 LOCJS, MAXORD, METH, MITER, MSBJ, MXHNIL, MXSTEP, 3 N, NEWH, NEWQ, NHNIL, NQ, NQNYH, NQWAIT, NSLJ, 4 NSLP, NYH C C Type declarations for labeled COMMON block SVOD02 -------------------- C REAL HU INTEGER NCFN, NETF, NFE, NJE, NLU, NNI, NQU, NST C C Type declarations for local variables -------------------------------- C REAL CON, DI, FAC, HRL1, ONE, PT1, R, R0, SRUR, THOU, 1 YI, YJ, YJJ, ZERO INTEGER I, I1, I2, IER, II, J, J1, JJ, JOK, LENP, MBA, MBAND, 1 MEB1, MEBAND, ML, ML3, MU, NP1 C C Type declaration for function subroutines called --------------------- C REAL SVNORM C----------------------------------------------------------------------- C The following Fortran-77 declaration is to cause the values of the C listed (local) variables to be saved between calls to this subroutine. C----------------------------------------------------------------------- SAVE ONE, PT1, THOU, ZERO C----------------------------------------------------------------------- COMMON /SVOD01/ ACNRM, CCMXJ, CONP, CRATE, DRC, EL(13), 1 ETA, ETAMAX, H, HMIN, HMXI, HNEW, HSCAL, PRL1, 2 RC, RL1, TAU(13), TQ(5), TN, UROUND, 3 ICF, INIT, IPUP, JCUR, JSTART, JSV, KFLAG, KUTH, 4 L, LMAX, LYH, LEWT, LACOR, LSAVF, LWM, LIWM, 5 LOCJS, MAXORD, METH, MITER, MSBJ, MXHNIL, MXSTEP, 6 N, NEWH, NEWQ, NHNIL, NQ, NQNYH, NQWAIT, NSLJ, 7 NSLP, NYH COMMON /SVOD02/ HU, NCFN, NETF, NFE, NJE, NLU, NNI, NQU, NST C DATA ONE /1.0E0/, THOU /1000.0E0/, ZERO /0.0E0/, PT1 /0.1E0/ C IERPJ = 0 HRL1 = H*RL1 C See whether J should be evaluated (JOK = -1) or not (JOK = 1). ------- JOK = JSV IF (JSV .EQ. 1) THEN IF (NST .EQ. 0 .OR. NST .GT. NSLJ+MSBJ) JOK = -1 IF (ICF .EQ. 1 .AND. DRC .LT. CCMXJ) JOK = -1 IF (ICF .EQ. 2) JOK = -1 ENDIF C End of setting JOK. -------------------------------------------------- C IF (JOK .EQ. -1 .AND. MITER .EQ. 1) THEN C If JOK = -1 and MITER = 1, call JAC to evaluate Jacobian. ------------ NJE = NJE + 1 NSLJ = NST JCUR = 1 LENP = N*N DO 110 I = 1,LENP 110 WM(I+2) = ZERO C C*UPG*MNH C CALL JAC (N, TN, Y, 0, 0, WM(3), N, RPAR, IPAR, KMI, KINDEX) C C*UPG*MNH C IF (JSV .EQ. 1) CALL CH_SCOPY (LENP, WM(3), 1, WM(LOCJS), 1) ENDIF C IF (JOK .EQ. -1 .AND. MITER .EQ. 2) THEN C If MITER = 2, make N calls to F to approximate the Jacobian. --------- NJE = NJE + 1 NSLJ = NST JCUR = 1 FAC = SVNORM (N, SAVF, EWT) R0 = THOU*ABS(H)*UROUND*REAL(N)*FAC IF (R0 .EQ. ZERO) R0 = ONE SRUR = WM(1) J1 = 2 DO 230 J = 1,N YJ = Y(J) R = MAX(SRUR*ABS(YJ),R0/EWT(J)) Y(J) = Y(J) + R FAC = ONE/R C C*UPG*MNH C CALL F (N, TN, Y, FTEM, RPAR, IPAR, KMI, KINDEX) C C*UPG*MNH C DO 220 I = 1,N 220 WM(I+J1) = (FTEM(I) - SAVF(I))*FAC Y(J) = YJ J1 = J1 + N 230 CONTINUE NFE = NFE + N LENP = N*N IF (JSV .EQ. 1) CALL CH_SCOPY (LENP, WM(3), 1, WM(LOCJS), 1) ENDIF C IF (JOK .EQ. 1 .AND. (MITER .EQ. 1 .OR. MITER .EQ. 2)) THEN JCUR = 0 LENP = N*N CALL CH_SCOPY (LENP, WM(LOCJS), 1, WM(3), 1) ENDIF C IF (MITER .EQ. 1 .OR. MITER .EQ. 2) THEN C Multiply Jacobian by scalar, add identity, and do LU decomposition. -- CON = -HRL1 CALL SSCAL (LENP, CON, WM(3), 1) J = 3 NP1 = N + 1 DO 250 I = 1,N WM(J) = WM(J) + ONE 250 J = J + NP1 NLU = NLU + 1 CALL SGEFA (WM(3), N, N, IWM(31), IER) IF (IER .NE. 0) IERPJ = 1 RETURN ENDIF C End of code block for MITER = 1 or 2. -------------------------------- C IF (MITER .EQ. 3) THEN C If MITER = 3, construct a diagonal approximation to J and P. --------- NJE = NJE + 1 JCUR = 1 WM(2) = HRL1 R = RL1*PT1 DO 310 I = 1,N 310 Y(I) = Y(I) + R*(H*SAVF(I) - YH(I,2)) C C*UPG*MNH C CALL F (N, TN, Y, WM(3), RPAR, IPAR, KMI, KINDEX) C C*UPG*MNH C NFE = NFE + 1 DO 320 I = 1,N R0 = H*SAVF(I) - YH(I,2) DI = PT1*R0 - H*(WM(I+2) - SAVF(I)) WM(I+2) = ONE IF (ABS(R0) .LT. UROUND/EWT(I)) GO TO 320 IF (ABS(DI) .EQ. ZERO) GO TO 330 WM(I+2) = PT1*R0/DI 320 CONTINUE RETURN 330 IERPJ = 1 RETURN ENDIF C End of code block for MITER = 3. ------------------------------------- C C Set constants for MITER = 4 or 5. ------------------------------------ ML = IWM(1) MU = IWM(2) ML3 = ML + 3 MBAND = ML + MU + 1 MEBAND = MBAND + ML LENP = MEBAND*N C IF (JOK .EQ. -1 .AND. MITER .EQ. 4) THEN C If JOK = -1 and MITER = 4, call JAC to evaluate Jacobian. ------------ NJE = NJE + 1 NSLJ = NST JCUR = 1 DO 410 I = 1,LENP 410 WM(I+2) = ZERO C C*UPG*MNH C CALL JAC (N, TN, Y, ML, MU, WM(ML3), MEBAND, RPAR, IPAR, 1 KMI, KINDEX) C C*UPG*MNH C IF (JSV .EQ. 1) 1 CALL SACOPY (MBAND, N, WM(ML3), MEBAND, WM(LOCJS), MBAND) ENDIF C IF (JOK .EQ. -1 .AND. MITER .EQ. 5) THEN C If MITER = 5, make N calls to F to approximate the Jacobian. --------- NJE = NJE + 1 NSLJ = NST JCUR = 1 MBA = MIN(MBAND,N) MEB1 = MEBAND - 1 SRUR = WM(1) FAC = SVNORM (N, SAVF, EWT) R0 = THOU*ABS(H)*UROUND*REAL(N)*FAC IF (R0 .EQ. ZERO) R0 = ONE DO 560 J = 1,MBA DO 530 I = J,N,MBAND YI = Y(I) R = MAX(SRUR*ABS(YI),R0/EWT(I)) 530 Y(I) = Y(I) + R C C*UPG*MNH C CALL F (N, TN, Y, FTEM, RPAR, IPAR, KMI, KINDEX) C C*UPG*MNH C DO 550 JJ = J,N,MBAND Y(JJ) = YH(JJ,1) YJJ = Y(JJ) R = MAX(SRUR*ABS(YJJ),R0/EWT(JJ)) FAC = ONE/R I1 = MAX(JJ-MU,1) I2 = MIN(JJ+ML,N) II = JJ*MEB1 - ML + 2 DO 540 I = I1,I2 540 WM(II+I) = (FTEM(I) - SAVF(I))*FAC 550 CONTINUE 560 CONTINUE NFE = NFE + MBA IF (JSV .EQ. 1) 1 CALL SACOPY (MBAND, N, WM(ML3), MEBAND, WM(LOCJS), MBAND) ENDIF C IF (JOK .EQ. 1) THEN JCUR = 0 CALL SACOPY (MBAND, N, WM(LOCJS), MBAND, WM(ML3), MEBAND) ENDIF C C Multiply Jacobian by scalar, add identity, and do LU decomposition. CON = -HRL1 CALL SSCAL (LENP, CON, WM(3), 1 ) II = MBAND + 2 DO 580 I = 1,N WM(II) = WM(II) + ONE 580 II = II + MEBAND NLU = NLU + 1 CALL SGBFA (WM(3), MEBAND, N, ML, MU, IWM(31), IER) IF (IER .NE. 0) IERPJ = 1 RETURN C End of code block for MITER = 4 or 5. -------------------------------- C END SUBROUTINE SVJAC C C####################################################################### C CDECK SACOPY C ################################################## SUBROUTINE SACOPY (NROW, NCOL, A, NROWA, B, NROWB) C ################################################## REAL A, B INTEGER NROW, NCOL, NROWA, NROWB DIMENSION A(NROWA,NCOL), B(NROWB,NCOL) C----------------------------------------------------------------------- C Call sequence input -- NROW, NCOL, A, NROWA, NROWB C Call sequence output -- B C COMMON block variables accessed -- None C C Subroutines called by SACOPY.. CH_SCOPY C Function routines called by SACOPY.. None C----------------------------------------------------------------------- C This routine copies one rectangular array, A, to another, B, C where A and B may have different row dimensions, NROWA and NROWB. C The data copied consists of NROW rows and NCOL columns. C----------------------------------------------------------------------- INTEGER IC C DO 20 IC = 1,NCOL CALL CH_SCOPY (NROW, A(1,IC), 1, B(1,IC), 1) 20 CONTINUE C RETURN END SUBROUTINE SACOPY C####################################################################### C CDECK SVSOL C #################################### SUBROUTINE SVSOL (WM, IWM, X, IERSL) C #################################### REAL WM, X INTEGER IWM, IERSL DIMENSION WM(*), IWM(*), X(*) C----------------------------------------------------------------------- C Call sequence input -- WM, IWM, X C Call sequence output -- X, IERSL C COMMON block variables accessed.. C /SVOD01/ -- H, RL1, MITER, N C C Subroutines called by SVSOL.. SGESL, SGBSL C Function routines called by SVSOL.. None C----------------------------------------------------------------------- C This routine manages the solution of the linear system arising from C a chord iteration. It is called if MITER .ne. 0. C If MITER is 1 or 2, it calls SGESL to accomplish this. C If MITER = 3 it updates the coefficient H*RL1 in the diagonal C matrix, and then computes the solution. C If MITER is 4 or 5, it calls SGBSL. C Communication with SVSOL uses the following variables.. C WM = Real work space containing the inverse diagonal matrix if C MITER = 3 and the LU decomposition of the matrix otherwise. C Storage of matrix elements starts at WM(3). C WM also contains the following matrix-related data.. C WM(1) = SQRT(UROUND) (not used here), C WM(2) = HRL1, the previous value of H*RL1, used if MITER = 3. C IWM = Integer work space containing pivot information, starting at C IWM(31), if MITER is 1, 2, 4, or 5. IWM also contains band C parameters ML = IWM(1) and MU = IWM(2) if MITER is 4 or 5. C X = The right-hand side vector on input, and the solution vector C on output, of length N. C IERSL = Output flag. IERSL = 0 if no trouble occurred. C IERSL = 1 if a singular matrix arose with MITER = 3. C----------------------------------------------------------------------- C C Type declarations for labeled COMMON block SVOD01 -------------------- C REAL ACNRM, CCMXJ, CONP, CRATE, DRC, EL, 1 ETA, ETAMAX, H, HMIN, HMXI, HNEW, HSCAL, PRL1, 2 RC, RL1, TAU, TQ, TN, UROUND INTEGER ICF, INIT, IPUP, JCUR, JSTART, JSV, KFLAG, KUTH, 1 L, LMAX, LYH, LEWT, LACOR, LSAVF, LWM, LIWM, 2 LOCJS, MAXORD, METH, MITER, MSBJ, MXHNIL, MXSTEP, 3 N, NEWH, NEWQ, NHNIL, NQ, NQNYH, NQWAIT, NSLJ, 4 NSLP, NYH C C Type declarations for local variables -------------------------------- C INTEGER I, MEBAND, ML, MU REAL DI, HRL1, ONE, PHRL1, R, ZERO C----------------------------------------------------------------------- C The following Fortran-77 declaration is to cause the values of the C listed (local) variables to be saved between calls to this integrator. C----------------------------------------------------------------------- SAVE ONE, ZERO C COMMON /SVOD01/ ACNRM, CCMXJ, CONP, CRATE, DRC, EL(13), 1 ETA, ETAMAX, H, HMIN, HMXI, HNEW, HSCAL, PRL1, 2 RC, RL1, TAU(13), TQ(5), TN, UROUND, 3 ICF, INIT, IPUP, JCUR, JSTART, JSV, KFLAG, KUTH, 4 L, LMAX, LYH, LEWT, LACOR, LSAVF, LWM, LIWM, 5 LOCJS, MAXORD, METH, MITER, MSBJ, MXHNIL, MXSTEP, 6 N, NEWH, NEWQ, NHNIL, NQ, NQNYH, NQWAIT, NSLJ, 7 NSLP, NYH C DATA ONE /1.0E0/, ZERO /0.0E0/ C IERSL = 0 GO TO (100, 100, 300, 400, 400), MITER 100 CALL SGESL (WM(3), N, N, IWM(31), X, 0) RETURN C 300 PHRL1 = WM(2) HRL1 = H*RL1 WM(2) = HRL1 IF (HRL1 .EQ. PHRL1) GO TO 330 R = HRL1/PHRL1 DO 320 I = 1,N DI = ONE - R*(ONE - ONE/WM(I+2)) IF (ABS(DI) .EQ. ZERO) GO TO 390 320 WM(I+2) = ONE/DI C 330 DO 340 I = 1,N 340 X(I) = WM(I+2)*X(I) RETURN 390 IERSL = 1 RETURN C 400 ML = IWM(1) MU = IWM(2) MEBAND = 2*ML + MU + 1 CALL SGBSL (WM(3), MEBAND, N, ML, MU, IWM(31), X, 0) RETURN END SUBROUTINE SVSOL C####################################################################### C CDECK SVSRCO C ################################### SUBROUTINE SVSRCO (RSAV, ISAV, JOB) C ################################### REAL RSAV INTEGER ISAV, JOB DIMENSION RSAV(*), ISAV(*) C----------------------------------------------------------------------- C Call sequence input -- RSAV, ISAV, JOB C Call sequence output -- RSAV, ISAV C COMMON block variables accessed -- All of /SVOD01/ and /SVOD02/ C C Subroutines/functions called by SVSRCO.. None C----------------------------------------------------------------------- C This routine saves or restores (depending on JOB) the contents of the C COMMON blocks SVOD01 and SVOD02, which are used internally by SVODE. C C RSAV = real array of length 49 or more. C ISAV = integer array of length 41 or more. C JOB = flag indicating to save or restore the COMMON blocks.. C JOB = 1 if COMMON is to be saved (written to RSAV/ISAV). C JOB = 2 if COMMON is to be restored (read from RSAV/ISAV). C A call with JOB = 2 presumes a prior call with JOB = 1. C----------------------------------------------------------------------- REAL RVOD1, RVOD2 INTEGER IVOD1, IVOD2 INTEGER I, LENIV1, LENIV2, LENRV1, LENRV2 C----------------------------------------------------------------------- C The following Fortran-77 declaration is to cause the values of the C listed (local) variables to be saved between calls to this integrator. C----------------------------------------------------------------------- SAVE LENRV1, LENIV1, LENRV2, LENIV2 C COMMON /SVOD01/ RVOD1(48), IVOD1(33) COMMON /SVOD02/ RVOD2(1), IVOD2(8) DATA LENRV1/48/, LENIV1/33/, LENRV2/1/, LENIV2/8/ C IF (JOB .EQ. 2) GO TO 100 DO 10 I = 1,LENRV1 10 RSAV(I) = RVOD1(I) DO 15 I = 1,LENRV2 15 RSAV(LENRV1+I) = RVOD2(I) C DO 20 I = 1,LENIV1 20 ISAV(I) = IVOD1(I) DO 25 I = 1,LENIV2 25 ISAV(LENIV1+I) = IVOD2(I) C RETURN C 100 CONTINUE DO 110 I = 1,LENRV1 110 RVOD1(I) = RSAV(I) DO 115 I = 1,LENRV2 115 RVOD2(I) = RSAV(LENRV1+I) C DO 120 I = 1,LENIV1 120 IVOD1(I) = ISAV(I) DO 125 I = 1,LENIV2 125 IVOD2(I) = ISAV(LENIV1+I) C RETURN END SUBROUTINE SVSRCO C####################################################################### C CDECK SEWSET C ################################################## SUBROUTINE SEWSET (N, ITOL, RTOL, ATOL, YCUR, EWT) C ################################################## REAL RTOL, ATOL, YCUR, EWT INTEGER N, ITOL DIMENSION RTOL(*), ATOL(*), YCUR(N), EWT(N) C----------------------------------------------------------------------- C Call sequence input -- N, ITOL, RTOL, ATOL, YCUR C Call sequence output -- EWT C COMMON block variables accessed -- None C C Subroutines/functions called by SEWSET.. None C----------------------------------------------------------------------- C This subroutine sets the error weight vector EWT according to C EWT(i) = RTOL(i)*abs(YCUR(i)) + ATOL(i), i = 1,...,N, C with the subscript on RTOL and/or ATOL possibly replaced by 1 above, C depending on the value of ITOL. C----------------------------------------------------------------------- INTEGER I C GO TO (10, 20, 30, 40), ITOL 10 CONTINUE DO 15 I = 1, N 15 EWT(I) = RTOL(1)*ABS(YCUR(I)) + ATOL(1) RETURN 20 CONTINUE DO 25 I = 1, N 25 EWT(I) = RTOL(1)*ABS(YCUR(I)) + ATOL(I) RETURN 30 CONTINUE DO 35 I = 1, N 35 EWT(I) = RTOL(I)*ABS(YCUR(I)) + ATOL(1) RETURN 40 CONTINUE DO 45 I = 1, N 45 EWT(I) = RTOL(I)*ABS(YCUR(I)) + ATOL(I) RETURN END SUBROUTINE SEWSET C####################################################################### C CDECK SVNORM C ############################## FUNCTION SVNORM (N, V, W) C ############################## REAL SVNORM REAL V, W INTEGER N DIMENSION V(N), W(N) C----------------------------------------------------------------------- C Call sequence input -- N, V, W C Call sequence output -- None C COMMON block variables accessed -- None C C Subroutines/functions called by SVNORM.. None C----------------------------------------------------------------------- C This function routine computes the weighted root-mean-square norm C of the vector of length N contained in the array V, with weights C contained in the array W of length N.. C SVNORM = sqrt( (1/N) * sum( V(i)*W(i) )**2 ) C----------------------------------------------------------------------- REAL SUM INTEGER I C SUM = 0.0E0 DO 10 I = 1, N 10 SUM = SUM + (V(I)*W(I))**2 SVNORM = SQRT(SUM/REAL(N)) RETURN END C####################################################################### C CDECK XERRWV C ################################################################## SUBROUTINE XERRWV (MSG, NMES, NERR, LEVEL, NI, I1, I2, NR, R1, R2) C ################################################################## REAL R1, R2 INTEGER NMES, NERR, LEVEL, NI, I1, I2, NR C CKS: changed to adapt to Fortran90 C CHARACTER*1 MSG(NMES) CHARACTER*(*) MSG C----------------------------------------------------------------------- C Subroutines XERRWV, XSETF, XSETUN, and the two function routines C MFLGSV and LUNSAV, as given here, constitute a simplified version of C the SLATEC error handling package. C Written by A. C. Hindmarsh and P. N. Brown at LLNL. C Version of 13 April, 1989. C This version is in single precision. C C All arguments are input arguments. C C MSG = The message (character array). C NMES = The length of MSG (number of characters). C NERR = The error number (not used). C LEVEL = The error level.. C 0 or 1 means recoverable (control returns to caller). C 2 means fatal (run is aborted--see note below). C NI = Number of integers (0, 1, or 2) to be printed with message. C I1,I2 = Integers to be printed, depending on NI. C NR = Number of reals (0, 1, or 2) to be printed with message. C R1,R2 = Reals to be printed, depending on NR. C C Note.. this routine is machine-dependent and specialized for use C in limited context, in the following ways.. C 1. The argument MSG is assumed to be of type CHARACTER, and C the message is printed with a format of (1X,80A1). C 2. The message is assumed to take only one line. C Multi-line messages are generated by repeated calls. C 3. If LEVEL = 2, control passes to the statement STOP C to abort the run. This statement may be machine-dependent. C 4. R1 and R2 are assumed to be in single precision and are printed C in E21.13 format. C C For a different default logical unit number, change the data C statement in function routine LUNSAV. C For a different run-abort command, change the statement following C statement 100 at the end. C----------------------------------------------------------------------- C Subroutines called by XERRWV.. None C Function routines called by XERRWV.. MFLGSV, LUNSAV C----------------------------------------------------------------------- C INTEGER I, LUNIT, LUNSAV, MESFLG, MFLGSV C C Get message print flag and logical unit number. ---------------------- MESFLG = MFLGSV (0,.FALSE.) LUNIT = LUNSAV (0,.FALSE.) IF (MESFLG .EQ. 0) GO TO 100 C Write the message. --------------------------------------------------- CKS: changed to adapt to Fortran90 C WRITE (LUNIT,10) (MSG(I),I=1,NMES) C10 FORMAT(1X,80A1) WRITE (LUNIT,'(A)') MSG IF (NI .EQ. 1) WRITE (LUNIT, 20) I1 20 FORMAT(6X,'In above message, I1 =',I10) IF (NI .EQ. 2) WRITE (LUNIT, 30) I1,I2 30 FORMAT(6X,'In above message, I1 =',I10,3X,'I2 =',I10) IF (NR .EQ. 1) WRITE (LUNIT, 40) R1 40 FORMAT(6X,'In above message, R1 =',E21.13) IF (NR .EQ. 2) WRITE (LUNIT, 50) R1,R2 50 FORMAT(6X,'In above, R1 =',E21.13,3X,'R2 =',E21.13) C Abort the run if LEVEL = 2. ------------------------------------------ 100 IF (LEVEL .NE. 2) RETURN C callabortstop CALL ABORT STOP END C####################### End of Subroutine XERRWV ###################### C CDECK XSETF C ######################## SUBROUTINE XSETF (MFLAG) C ######################## C----------------------------------------------------------------------- C This routine resets the print control flag MFLAG. C C Subroutines called by XSETF.. None C Function routines called by XSETF.. MFLGSV C----------------------------------------------------------------------- INTEGER MFLAG, JUNK, MFLGSV C IF (MFLAG .EQ. 0 .OR. MFLAG .EQ. 1) JUNK = MFLGSV (MFLAG,.TRUE.) RETURN END C####################### End of Subroutine XSETF ####################### C CDECK XSETUN C ####################### SUBROUTINE XSETUN (LUN) C ####################### C----------------------------------------------------------------------- C This routine resets the logical unit number for messages. C C Subroutines called by XSETUN.. None C Function routines called by XSETUN.. LUNSAV C----------------------------------------------------------------------- INTEGER LUN, JUNK, LUNSAV C IF (LUN .GT. 0) JUNK = LUNSAV (LUN,.TRUE.) RETURN C----------------------- End of Subroutine XSETUN ---------------------- END CDECK MFLGSV C ############################## FUNCTION MFLGSV (IVALUE, ISET) C ############################## INTEGER MFLGSV LOGICAL ISET INTEGER IVALUE C----------------------------------------------------------------------- C MFLGSV saves and recalls the parameter MESFLG which controls the C printing of the error messages. C C Saved local variable.. C C MESFLG = Print control flag.. C 1 means print all messages (the default). C 0 means no printing. C C On input.. C C IVALUE = The value to be set for the MESFLG parameter, C if ISET is .TRUE. . C C ISET = Logical flag to indicate whether to read or write. C If ISET=.TRUE., the MESFLG parameter will be given C the value IVALUE. If ISET=.FALSE., the MESFLG C parameter will be unchanged, and IVALUE is a dummy C parameter. C C On return.. C C The (old) value of the MESFLG parameter will be returned C in the function value, MFLGSV. C C This is a modification of the SLATEC library routine J4SAVE. C C Subroutines/functions called by MFLGSV.. None C----------------------------------------------------------------------- INTEGER MESFLG C----------------------------------------------------------------------- C The following Fortran-77 declaration is to cause the values of the C listed (local) variables to be saved between calls to this integrator. C----------------------------------------------------------------------- SAVE MESFLG DATA MESFLG/1/ C MFLGSV = MESFLG IF (ISET) MESFLG = IVALUE RETURN C----------------------- End of Function MFLGSV ------------------------ END CDECK LUNSAV C ############################## FUNCTION LUNSAV (IVALUE, ISET) C ############################## INTEGER LUNSAV LOGICAL ISET INTEGER IVALUE C----------------------------------------------------------------------- C LUNSAV saves and recalls the parameter LUNIT which is the logical C unit number to which error messages are printed. C C Saved local variable.. C C LUNIT = Logical unit number for messages. C The default is 6 (machine-dependent). C C On input.. C C IVALUE = The value to be set for the LUNIT parameter, C if ISET is .TRUE. . C C ISET = Logical flag to indicate whether to read or write. C If ISET=.TRUE., the LUNIT parameter will be given C the value IVALUE. If ISET=.FALSE., the LUNIT C parameter will be unchanged, and IVALUE is a dummy C parameter. C C On return.. C C The (old) value of the LUNIT parameter will be returned C in the function value, LUNSAV. C C This is a modification of the SLATEC library routine J4SAVE. C C Subroutines/functions called by LUNSAV.. None C----------------------------------------------------------------------- INTEGER LUNIT C----------------------------------------------------------------------- C The following Fortran-77 declaration is to cause the values of the C listed (local) variables to be saved between calls to this integrator. C----------------------------------------------------------------------- SAVE LUNIT DATA LUNIT/6/ C LUNSAV = LUNIT IF (ISET) LUNIT = IVALUE RETURN C----------------------- End of Function LUNSAV ------------------------ END subroutine ch_scopy(n,sx,incx,sy,incy) c c copies a vector, x, to a vector, y. c uses unrolled loops for increments equal to 1. c jack dongarra, linpack, 3/11/78. c modified 12/3/93, array(1) declarations changed to array(*) c modified 12/12/00 change name to avoid confusion with spline routine c real sx(*),sy(*) integer i,incx,incy,ix,iy,m,mp1,n c if(n.le.0)return if(incx.eq.1.and.incy.eq.1)go to 20 c c code for unequal increments or equal increments c not equal to 1 c ix = 1 iy = 1 if(incx.lt.0)ix = (-n+1)*incx + 1 if(incy.lt.0)iy = (-n+1)*incy + 1 do 10 i = 1,n sy(iy) = sx(ix) ix = ix + incx iy = iy + incy 10 continue return c c code for both increments equal to 1 c c c clean-up loop c 20 m = mod(n,7) if( m .eq. 0 ) go to 40 do 30 i = 1,m sy(i) = sx(i) 30 continue if( n .lt. 7 ) return 40 mp1 = m + 1 do 50 i = mp1,n,7 sy(i) = sx(i) sy(i + 1) = sx(i + 1) sy(i + 2) = sx(i + 2) sy(i + 3) = sx(i + 3) sy(i + 4) = sx(i + 4) sy(i + 5) = sx(i + 5) sy(i + 6) = sx(i + 6) 50 continue return end subroutine sscal(n,sa,sx,incx) c c scales a vector by a constant. c uses unrolled loops for increment equal to 1. c jack dongarra, linpack, 3/11/78. c modified 3/93 to return if incx .le. 0. c modified 12/3/93, array(1) declarations changed to array(*) c real sa,sx(*) integer i,incx,m,mp1,n,nincx c if( n.le.0 .or. incx.le.0 )return if(incx.eq.1)go to 20 c c code for increment not equal to 1 c nincx = n*incx do 10 i = 1,nincx,incx sx(i) = sa*sx(i) 10 continue return c c code for increment equal to 1 c c c clean-up loop c 20 m = mod(n,5) if( m .eq. 0 ) go to 40 do 30 i = 1,m sx(i) = sa*sx(i) 30 continue if( n .lt. 5 ) return 40 mp1 = m + 1 do 50 i = mp1,n,5 sx(i) = sa*sx(i) sx(i + 1) = sa*sx(i + 1) sx(i + 2) = sa*sx(i + 2) sx(i + 3) = sa*sx(i + 3) sx(i + 4) = sa*sx(i + 4) 50 continue return end subroutine sgefa(a,lda,n,ipvt,info) integer lda,n,ipvt(1),info real a(lda,1) c c sgefa factors a real matrix by gaussian elimination. c c sgefa is usually called by sgeco, but it can be called c directly with a saving in time if rcond is not needed. c (time for sgeco) = (1 + 9/n)*(time for sgefa) . c c on entry c c a real(lda, n) c the matrix to be factored. c c lda integer c the leading dimension of the array a . c c n integer c the order of the matrix a . c c on return c c a an upper triangular matrix and the multipliers c which were used to obtain it. c the factorization can be written a = l*u where c l is a product of permutation and unit lower c triangular matrices and u is upper triangular. c c ipvt integer(n) c an integer vector of pivot indices. c c info integer c = 0 normal value. c = k if u(k,k) .eq. 0.0 . this is not an error c condition for this subroutine, but it does c indicate that sgesl or sgedi will divide by zero c if called. use rcond in sgeco for a reliable c indication of singularity. c c linpack. this version dated 08/14/78 . c cleve moler, university of new mexico, argonne national lab. c c subroutines and functions c c blas saxpy,sscal,isamax c c internal variables c real t integer isamax,j,k,kp1,l,nm1 c c c gaussian elimination with partial pivoting c info = 0 nm1 = n - 1 if (nm1 .lt. 1) go to 70 do 60 k = 1, nm1 kp1 = k + 1 c c find l = pivot index c l = isamax(n-k+1,a(k,k),1) + k - 1 ipvt(k) = l c c zero pivot implies this column already triangularized c if (a(l,k) .eq. 0.0e0) go to 40 c c interchange if necessary c if (l .eq. k) go to 10 t = a(l,k) a(l,k) = a(k,k) a(k,k) = t 10 continue c c compute multipliers c t = -1.0e0/a(k,k) call sscal(n-k,t,a(k+1,k),1) c c row elimination with column indexing c do 30 j = kp1, n t = a(l,j) if (l .eq. k) go to 20 a(l,j) = a(k,j) a(k,j) = t 20 continue call saxpy(n-k,t,a(k+1,k),1,a(k+1,j),1) 30 continue go to 50 40 continue info = k 50 continue 60 continue 70 continue ipvt(n) = n if (a(n,n) .eq. 0.0e0) info = n return end subroutine sgbfa(abd,lda,n,ml,mu,ipvt,info) integer lda,n,ml,mu,ipvt(1),info real abd(lda,1) c c sgbfa factors a real band matrix by elimination. c c sgbfa is usually called by sgbco, but it can be called c directly with a saving in time if rcond is not needed. c c on entry c c abd real(lda, n) c contains the matrix in band storage. the columns c of the matrix are stored in the columns of abd and c the diagonals of the matrix are stored in rows c ml+1 through 2*ml+mu+1 of abd . c see the comments below for details. c c lda integer c the leading dimension of the array abd . c lda must be .ge. 2*ml + mu + 1 . c c n integer c the order of the original matrix. c c ml integer c number of diagonals below the main diagonal. c 0 .le. ml .lt. n . c c mu integer c number of diagonals above the main diagonal. c 0 .le. mu .lt. n . c more efficient if ml .le. mu . c on return c c abd an upper triangular matrix in band storage and c the multipliers which were used to obtain it. c the factorization can be written a = l*u where c l is a product of permutation and unit lower c triangular matrices and u is upper triangular. c c ipvt integer(n) c an integer vector of pivot indices. c c info integer c = 0 normal value. c = k if u(k,k) .eq. 0.0 . this is not an error c condition for this subroutine, but it does c indicate that sgbsl will divide by zero if c called. use rcond in sgbco for a reliable c indication of singularity. c c band storage c c if a is a band matrix, the following program segment c will set up the input. c c ml = (band width below the diagonal) c mu = (band width above the diagonal) c m = ml + mu + 1 c do 20 j = 1, n c i1 = max0(1, j-mu) c i2 = min0(n, j+ml) c do 10 i = i1, i2 c k = i - j + m c abd(k,j) = a(i,j) c 10 continue c 20 continue c c this uses rows ml+1 through 2*ml+mu+1 of abd . c in addition, the first ml rows in abd are used for c elements generated during the triangularization. c the total number of rows needed in abd is 2*ml+mu+1 . c the ml+mu by ml+mu upper left triangle and the c ml by ml lower right triangle are not referenced. c c linpack. this version dated 08/14/78 . c cleve moler, university of new mexico, argonne national lab. c c subroutines and functions c c blas saxpy,sscal,isamax c fortran max0,min0 c c internal variables c real t integer i,isamax,i0,j,ju,jz,j0,j1,k,kp1,l,lm,m,mm,nm1 c c m = ml + mu + 1 info = 0 c c zero initial fill-in columns c j0 = mu + 2 j1 = min0(n,m) - 1 if (j1 .lt. j0) go to 30 do 20 jz = j0, j1 i0 = m + 1 - jz do 10 i = i0, ml abd(i,jz) = 0.0e0 10 continue 20 continue 30 continue jz = j1 ju = 0 c c gaussian elimination with partial pivoting c nm1 = n - 1 if (nm1 .lt. 1) go to 130 do 120 k = 1, nm1 kp1 = k + 1 c c zero next fill-in column c jz = jz + 1 if (jz .gt. n) go to 50 if (ml .lt. 1) go to 50 do 40 i = 1, ml abd(i,jz) = 0.0e0 40 continue 50 continue c c find l = pivot index c lm = min0(ml,n-k) l = isamax(lm+1,abd(m,k),1) + m - 1 ipvt(k) = l + k - m c c zero pivot implies this column already triangularized c if (abd(l,k) .eq. 0.0e0) go to 100 c c interchange if necessary c if (l .eq. m) go to 60 t = abd(l,k) abd(l,k) = abd(m,k) abd(m,k) = t 60 continue c c compute multipliers c t = -1.0e0/abd(m,k) call sscal(lm,t,abd(m+1,k),1) c c row elimination with column indexing c ju = min0(max0(ju,mu+ipvt(k)),n) mm = m if (ju .lt. kp1) go to 90 do 80 j = kp1, ju l = l - 1 mm = mm - 1 t = abd(l,j) if (l .eq. mm) go to 70 abd(l,j) = abd(mm,j) abd(mm,j) = t 70 continue call saxpy(lm,t,abd(m+1,k),1,abd(mm+1,j),1) 80 continue 90 continue go to 110 100 continue info = k 110 continue 120 continue 130 continue ipvt(n) = n if (abd(m,n) .eq. 0.0e0) info = n return end subroutine sgbsl(abd,lda,n,ml,mu,ipvt,b,job) integer lda,n,ml,mu,ipvt(1),job real abd(lda,1),b(1) c c sgbsl solves the real band system c a * x = b or trans(a) * x = b c using the factors computed by sgbco or sgbfa. c c on entry c c abd real(lda, n) c the output from sgbco or sgbfa. c c lda integer c the leading dimension of the array abd . c c n integer c the order of the original matrix. c c ml integer c number of diagonals below the main diagonal. c c mu integer c number of diagonals above the main diagonal. c c ipvt integer(n) c the pivot vector from sgbco or sgbfa. c c b real(n) c the right hand side vector. c c job integer c = 0 to solve a*x = b , c = nonzero to solve trans(a)*x = b , where c trans(a) is the transpose. c c on return c c b the solution vector x . c c error condition c c a division by zero will occur if the input factor contains a c zero on the diagonal. technically this indicates singularity c but it is often caused by improper arguments or improper c setting of lda . it will not occur if the subroutines are c called correctly and if sgbco has set rcond .gt. 0.0 c or sgbfa has set info .eq. 0 . c c to compute inverse(a) * c where c is a matrix c with p columns c call sgbco(abd,lda,n,ml,mu,ipvt,rcond,z) c if (rcond is too small) go to ... c do 10 j = 1, p c call sgbsl(abd,lda,n,ml,mu,ipvt,c(1,j),0) c 10 continue c c linpack. this version dated 08/14/78 . c cleve moler, university of new mexico, argonne national lab. c c subroutines and functions c c blas saxpy,sdot c fortran min0 c c internal variables c real sdot,t integer k,kb,l,la,lb,lm,m,nm1 c m = mu + ml + 1 nm1 = n - 1 if (job .ne. 0) go to 50 c c job = 0 , solve a * x = b c first solve l*y = b c if (ml .eq. 0) go to 30 if (nm1 .lt. 1) go to 30 do 20 k = 1, nm1 lm = min0(ml,n-k) l = ipvt(k) t = b(l) if (l .eq. k) go to 10 b(l) = b(k) b(k) = t 10 continue call saxpy(lm,t,abd(m+1,k),1,b(k+1),1) 20 continue 30 continue c c now solve u*x = y c do 40 kb = 1, n k = n + 1 - kb b(k) = b(k)/abd(m,k) lm = min0(k,m) - 1 la = m - lm lb = k - lm t = -b(k) call saxpy(lm,t,abd(la,k),1,b(lb),1) 40 continue go to 100 50 continue c c job = nonzero, solve trans(a) * x = b c first solve trans(u)*y = b c do 60 k = 1, n lm = min0(k,m) - 1 la = m - lm lb = k - lm t = sdot(lm,abd(la,k),1,b(lb),1) b(k) = (b(k) - t)/abd(m,k) 60 continue c c now solve trans(l)*x = y c if (ml .eq. 0) go to 90 if (nm1 .lt. 1) go to 90 do 80 kb = 1, nm1 k = n - kb lm = min0(ml,n-k) b(k) = b(k) + sdot(lm,abd(m+1,k),1,b(k+1),1) l = ipvt(k) if (l .eq. k) go to 70 t = b(l) b(l) = b(k) b(k) = t 70 continue 80 continue 90 continue 100 continue return end function sdot(n,sx,incx,sy,incy) c c forms the dot product of two vectors. c uses unrolled loops for increments equal to one. c jack dongarra, linpack, 3/11/78. c modified 12/3/93, array(1) declarations changed to array(*) c real sdot real sx(*),sy(*),stemp integer i,incx,incy,ix,iy,m,mp1,n c stemp = 0.0e0 sdot = 0.0e0 if(n.le.0)return if(incx.eq.1.and.incy.eq.1)go to 20 c c code for unequal increments or equal increments c not equal to 1 c ix = 1 iy = 1 if(incx.lt.0)ix = (-n+1)*incx + 1 if(incy.lt.0)iy = (-n+1)*incy + 1 do 10 i = 1,n stemp = stemp + sx(ix)*sy(iy) ix = ix + incx iy = iy + incy 10 continue sdot = stemp return c c code for both increments equal to 1 c c c clean-up loop c 20 m = mod(n,5) if( m .eq. 0 ) go to 40 do 30 i = 1,m stemp = stemp + sx(i)*sy(i) 30 continue if( n .lt. 5 ) go to 60 40 mp1 = m + 1 do 50 i = mp1,n,5 stemp = stemp + sx(i)*sy(i) + sx(i + 1)*sy(i + 1) + * sx(i + 2)*sy(i + 2) + sx(i + 3)*sy(i + 3) + sx(i + 4)*sy(i + 4) 50 continue 60 sdot = stemp return end function isamax(n,sx,incx) c c finds the index of element having max. absolute value. c jack dongarra, linpack, 3/11/78. c modified 3/93 to return if incx .le. 0. c modified 12/3/93, array(1) declarations changed to array(*) c integer isamax real sx(*),smax integer i,incx,ix,n c isamax = 0 if( n.lt.1 .or. incx.le.0 ) return isamax = 1 if(n.eq.1)return if(incx.eq.1)go to 20 c c code for increment not equal to 1 c ix = 1 smax = abs(sx(1)) ix = ix + incx do 10 i = 2,n if(abs(sx(ix)).le.smax) go to 5 isamax = i smax = abs(sx(ix)) 5 ix = ix + incx 10 continue return c c code for increment equal to 1 c 20 smax = abs(sx(1)) do 30 i = 2,n if(abs(sx(i)).le.smax) go to 30 isamax = i smax = abs(sx(i)) 30 continue return end *======= BEGIN of TUV 5.3.1 =======* * M.LERICHE Update Feb. 2018 CCC FILE TUV.f *---------------------------------------------------------------------------- subroutine tuvmain (asza, idate, + albnew, dobnew, + nlevel, zin, lwc, + njout, jout, jlabelout, + kout ) *-----------------------------------------------------------------------------* *= Tropospheric Ultraviolet-Visible (TUV) radiation model =* *= Version 5.3 =* *= June 2016 =* *-----------------------------------------------------------------------------* *= Developed by Sasha Madronich with important contributions from: =* *= Chris Fischer, Siri Flocke, Julia Lee-Taylor, Bernhard Meyer, =* *= Irina Petropavlovskikh, Xuexi Tie, and Jun Zen. =* *= Special thanks to Knut Stamnes and co-workers for the development of the =* *= Discrete Ordinates code, and to Warren Wiscombe and co-workers for the =* *= development of the solar zenith angle subroutine. Citations for the many =* *= data bases (e.g. extraterrestrial irradiances, molecular spectra) may be =* *= found in the data files headers and/or in the subroutines that read them. =* *= To contact the author, write to: =* *= Sasha Madronich, NCAR/ACD, P.O.Box 3000, Boulder, CO, 80307-3000, USA or =* *= send email to: sasha@ucar.edu or tuv@acd.ucar.edu =* *-----------------------------------------------------------------------------* *= This program 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 2 of the license, or (at your =* *= option) any later version. =* *= The TUV package is distributed in the hope that it will be useful, but =* *= WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBI- =* *= LITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public =* *= License for more details. =* *= To obtain a copy of the GNU General Public License, write to: =* *= Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. =* *-----------------------------------------------------------------------------* *= Copyright (C) 1994-2016 by the University Corporation for Atmospheric =* *= Research, extending to all called subroutines, functions, and data unless =* *= another source is specified. =* *-----------------------------------------------------------------------------* *= Adapted to MesoNH : ONLY JVALUES are computed IMPLICIT NONE SAVE * Include parameter file c INCLUDE 'params' * * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) *_________________________________________________ * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * More physical constants: *_________________________________________________________________ * Na = 6.022142E23 mol-1 = Avogadro constant * kb = 1.38065E-23 J K-1 = Boltzmann constant * R = 8.31447 J mol-1 K-1 = molar gas constant * h = 6.626068E-34 J s = Planck constant * c = 2.99792458E8 m s-1 = speed of light in vacuum * G = 6.673E-11 m3 kg-1 s-2 = Netwonian constant of gravitation * sb = 5.67040E-8 W m-2 K-4 = Stefan-Boltzmann constant *_________________________________________________________________ * (1) From NIST Reference on Constants, Units, and Uncertainty * http://physics.nist.gov/cuu/index.html Oct. 2001. * (2) These constants are not assigned to variable names; in other * words this is not Fortran code, but only a text table for quick * reference. To use, you must declare a variable name/type and * assign the value to that variable. Or assign as parameter (see * example for pi above). * Wavelength grid: INTEGER nw, iw, nwint REAL wl(kw), wc(kw), wu(kw) REAL wstart, wstop * Altitude grid INTEGER nz, nzm1, iz, izout REAL z(kz), zstart, zstop, zout * Solar zenith angle and azimuth * slant pathlengths in spherical geometry REAL sza, zen INTEGER nid(0:kz) REAL dsdh(0:kz,kz) * Extra terrestrial solar flux and earth-Sun distance ^-2 REAL f(kw), etf(kw) REAL esfact * Ozone absorption cross section INTEGER mabs REAL o3xs(kz,kw) * O2 absorption cross section REAL o2xs(kz,kw), o2xs1(kw) * SO2 absorption cross section REAL so2xs(kw) * NO2 absorption cross section REAL no2xs(kz,kw) * Atmospheric optical parameters REAL tlev(kz), tlay(kz) REAL aircon(kz), aircol(kz), vcol(kz), scol(kz) REAL dtrl(kz,kw) REAL co3(kz) REAL dto3(kz,kw), dto2(kz,kw), dtso2(kz,kw), dtno2(kz,kw) REAL dtcld(kz,kw), omcld(kz,kw), gcld(kz,kw) REAL dtaer(kz,kw), omaer(kz,kw), gaer(kz,kw) REAL dtsnw(kz,kw), omsnw(kz,kw), gsnw(kz,kw) REAL albedo(kw) * Spectral irradiance and actinic flux (scalar irradiance) REAL edir(kz), edn(kz), eup(kz) REAL sirrad(kz,kw) REAL fdir(kz), fdn(kz), fup(kz) REAL saflux(kz,kw) * Photolysis coefficients (j-values) INTEGER nj, ij REAL sj(kj,kz,kw), valj(kj,kz) REAL djdw CHARACTER*50 jlabel(kj) INTEGER tpflag(kj) **** Re-scaling factors (can be read from input file) * New surface albedo and surface pressure (milli bar) * Total columns of O3, SO2, NO2 (Dobson Units) * Cloud optical depth, altitude of base and top * Aerosol optical depth at 550 nm, single scattering albedo, Angstrom alpha REAL alsurf, psurf REAL o3_tc, so2_tc, no2_tc REAL taucld, zbase, ztop REAL tauaer, ssaaer, alpha * Location: Lat and Lon (deg.), surface elev (km) * Altitude, temperature and pressure for specific outputs REAL lat, lon REAL zaird, ztemp * Time and/or solar zenith angle INTEGER iyear, imonth, iday INTEGER it, nt REAL t, tstart, tstop REAL tmzone LOGICAL lzenit * number of radiation streams INTEGER nstr * input/output control LOGICAL intrct CHARACTER*6 inpfil, outfil INTEGER iout REAL dirsun, difdn, difup CHARACTER*1 again * Save arrays for output: LOGICAL laflux, ljvals, lmmech INTEGER isfix, ijfix, itfix, izfix, iwfix, i INTEGER nmj, imj(kj) * Planetary boundary layer height and pollutant concentrations INTEGER ipbl REAL zpbl REAL o3pbl, so2pbl, no2pbl, aod330 * Other user-defined variables here: C method: C C on first call, all necessary data will be read from the files C in directories DATAE1, DATAJ1; C all variables are saved for future calls to TUV C REAL, INTENT(IN) :: asza INTEGER, INTENT(IN) :: idate INTEGER, INTENT(IN) :: nlevel REAL, INTENT(IN) :: dobnew, albnew REAL, INTENT(IN) :: zin(nlevel) REAL, INTENT(IN) :: lwc(nlevel) INTEGER, INTENT(IN) :: njout REAL, INTENT(OUT) :: jout(nlevel,njout) CHARACTER*40, INTENT(OUT) :: jlabelout(njout) C LOGICAL LFIRSTCALL DATA LFIRSTCALL /.TRUE./ C * --- END OF DECLARATIONS --------------------------------------------- * re-entry point 1000 CONTINUE * ___ SECTION 1: SIMPLE INPUT VARIABLES -------------------------------- * Input and output files: * inpfil = input file name * outfil = output file name * Radiative transfer scheme: * nstr = number of streams * If nstr < 2, will use 2-stream Delta Eddington * If nstr > 1, will use nstr-stream discrete ordinates nstr = 1 * Location (geographic): * lat = LATITUDE (degrees, North = positive) * lon = LONGITUDE (degrees, East = positive) * tmzone = Local time zone difference (hrs) from Universal Time (ut): * ut = timloc - tmzone * Date: * iyear = year (1950 to 2050) * imonth = month (1 to 12) * iday = day of month * Time of day grid: * tstart = starting time, local hours * tstop = stopping time, local hours * nt = number of time steps * lzenit = switch for solar zenith angle (sza) grid rather than time * grid. If lzenit = .TRUE. then * tstart = first sza in deg., * tstop = last sza in deg., * nt = number of sza steps. * esfact = 1. (Earth-sun distance = 1.000 AU) lzenit=.TRUE. * Vertical grid: * zstart = surface elevation above sea level, km * zstop = top of the atmosphere (exospheric), km * nz = number of vertical levels, equally spaced * (nz will increase by +1 if zout does not match altitude grid) * Wavlength grid: * wstart = starting wavelength, nm * wstop = final wavelength, nm * nwint = number of wavelength intervals, equally spaced * if nwint < 0, the standard atmospheric wavelength grid, not * equally spaced, from 120 to 735 nm, will be used. In this * case, wstart and wstop values are ignored. * Surface condition: * alsurf = surface albedo, wavelength independent * psurf = surface pressure, mbar. Set to negative value to use * US Standard Atmosphere, 1976 (USSA76) psurf = -1. * Column amounts of absorbers (in Dobson Units, from surface to space): * Vertical profile for O3 from USSA76. For SO2 and NO2, vertical * concentration profile is 2.69e10 molec cm-3 between 0 and * 1 km above sea level, very small residual (10/largest) above 1 km. * o3_tc = ozone (O3) * so2_tc = sulfur dioxide (SO2) * no2_tc = nitrogen dioxide (NO2) * Cloud, assumed horizontally uniform, total coverage, single scattering * albedo = 0.9999, asymmetry factor = 0.85, indep. of wavelength, * and also uniform vertically between zbase and ztop: * taucld = vertical optical depth, independent of wavelength * zbase = altitude of base, km above sea level * ztop = altitude of top, km above sea level * Aerosols, assumed vertical provile typical of continental regions from * Elterman (1968): * tauaer = aerosol vertical optical depth at 550 nm, from surface to space. * If negative, will default to Elterman's values (ca. 0.235 * at 550 nm). * ssaaer = single scattering albedo of aerosols, wavelength-independent. * alpha = Angstrom coefficient = exponent for wavelength dependence of * tauaer, so that tauaer1/tauaer2 = (w2/w1)**alpha. * Directional components of radiation, weighting factors: * dirsun = direct sun * difdn = down-welling diffuse * difup = up-welling diffuse * e.g. use: * dirsun = difdn = 1.0, difup = 0 for total down-welling irradiance * dirsun = difdn = difup = 1.0 for actinic flux from all directions * dirsun = difdn = 1.0, difup = -1 for net irradiance dirsun = 1.0 difdn = 1.0 difup = 1.0 * Output altitude: * zout = altitude, km, for desired output. * If not within 1 m of altitude grid, an additional * level will be inserted and nz will be increased by +1. * zaird = air density (molec. cm-3) at zout. Set to negative value for * default USSA76 value interpolated to zout. * ztemp = air temperature (K) at zout. Set to negative value for * default USSA76 value interpolated to zout. * Output options, logical switches: * laflux = output spectral actinic flux * lmmech = output for NCAR Master Mechanism use laflux =.FALSE. lmmech =.FALSE. * Output options, integer selections: * ijfix: if > 0, output j-values for reaction ij=ijfix, tabulated * for different times and altitudes. * iwfix: if > 0, output spectral irradiance and/or spectral actinic * flux at wavelength iw=iwfix, tabulated for different times * and altitudes. * itfix: if > 0, output spectral irradiance and/or spectral actinic * flux at time it=itfix, tabulated for different altitudes * and wavelengths. * izfix: if > 0, output spectral irradiance and/or spectral actinic * flux at altitude iz=izfix, tabulated for different times * and wavelengths. * nmj: number of j-values that will be reported. Selections must be * made interactively, or by editing input file. izfix = 1 IF (LFIRSTCALL) THEN WRITE(kout,*) 'running TUVMAIN, version 5.3.1' IF(nstr .LT. 2) THEN WRITE(kout,*) 'Delta-Eddington 2-stream radiative transfer' ELSE WRITE(kout,*) 'Discrete ordinates ', $ nstr, '-stream radiative transfer' ENDIF * ___ SECTION 2: SET GRIDS _________________________________________________ * altitudes (creates altitude grid, locates index for selected output, izout) CALL gridz(zin,nlevel, zstart, zstop, nz, z, zout, izout,kout) if(izfix .gt. 0) izout = izfix * time/zenith (creates time/zenith angle grid, starting at tstart) c CALL gridt(lat, lon, tmzone, c $ iyear, imonth, iday, c $ lzenit, tstart, tstop, c $ nt, t, sza, esfact) sza = asza * wavelength grid, user-set range and spacing. * NOTE: Wavelengths are in vacuum, and therefore independent of altitude. * To use wavelengths in air, see options in subroutine gridw CALL gridw(wstart, wstop, nwint, $ nw, wl, wc, wu, kout) * ___ SECTION 3: SET UP VERTICAL PROFILES OF TEMPERATURE, AIR DENSITY, and OZONE______ ***** Temperature vertical profile, Kelvin * can overwrite temperature at altitude z(izout) CALL vptmp(nz,z, tlev,tlay,kout) c IF(ztemp .GT. nzero) tlev(izout) = ztemp ***** Air density (molec cm-3) vertical profile * can overwrite air density at altitude z(izout) CALL vpair(psurf, nz, z, $ aircon, aircol, kout) c IF(zaird .GT. nzero) aircon(izout) = zaird ***** *! PBL pollutants will be added if zpbl > 0. * CAUTIONS: * 1. The top of the PBL, zpbl in km, should be on one of the z-grid altitudes. * 2. Concentrations, column increments, and optical depths * will be overwritten between surface and zpbl. * 3. Inserting PBL constituents may change their total column amount. * 4. Above pbl, the following are used: * for O3: USSA or other profile * for NO2 and SO2: set to zero. * for aerosols: Elterman * Turning on pbl will affect subroutines: * vpo3, setno2, setso2, and setaer. See there for details zpbl = -999. * locate z-index for top of pbl ipbl = 0 IF(zpbl. GT. 0.) THEN DO iz = 1, nz-1 IF(z(iz+1) .GT. z(1) + zpbl*1.00001) GO TO 19 ENDDO 19 CONTINUE ipbl = iz - 1 write(*,*) 'top of PBL index, height (km) ', ipbl, z(ipbl) * specify pbl concetrations, in parts per billion o3pbl = 100. so2pbl = 10. no2pbl = 50. * PBL aerosol optical depth at 330 nm * (to change ssa and g of pbl aerosols, go to subroutine setair.f) aod330 = 0.8 ENDIF ***** Ozone vertical profile o3_tc = dobnew CALL vpo3(ipbl, zpbl, o3pbl, $ o3_tc, nz, z, aircol, co3, kout ) * ___ SECTION 4: READ SPECTRAL DATA ____________________________ * read (and grid) extra terrestrial flux data: CALL rdetfl(nw,wl, f, kout ) * read cross section data for * O2 (will overwrite at Lyman-alpha and SRB wavelengths * see subroutine la_srb.f) * O3 (temperature-dependent) * SO2 * NO2 nzm1 = nz - 1 CALL rdo2xs(nw,wl, o2xs1,kout) mabs = 1 CALL rdo3xs(mabs,nzm1,tlay,nw,wl, o3xs,kout) CALL rdso2xs(nw,wl, so2xs,kout) CALL rdno2xs(nz,tlay,nw,wl, no2xs,kout) ****** Spectral weighting functions * (Some of these depend on temperature T and pressure P, and therefore * on altitude z. Therefore they are computed only after the T and P profiles * are set above with subroutines settmp and setair.) * Photo-chemical set in swchem.f (cross sections x quantum yields) * Chemical weighting functions (product of cross-section x quantum yield) * for many photolysis reactions are known to depend on temperature * and/or pressure, and therefore are functions of wavelength and altitude. * Output: * from swchem: sj(kj,kz,kw) - for each reaction jlabel(kj) * For swchem, need to know temperature and pressure profiles. CALL swchem(nw,wl,nz,tlev,aircon, nj,sj,jlabel,tpflag,kout) ****** * ___ SECTION 5: SET ATMOSPHERIC OPTICAL DEPTH INCREMENTS _____________________ * Rayleigh optical depth increments: CALL odrl(nz, z, nw, wl, aircol, dtrl,kout) * O2 vertical profile and O2 absorption optical depths * For now, O2 densitiy assumed as 20.95% of air density, can be changed * in subroutine. * Optical depths in Lyman-alpha and SRB will be over-written * in subroutine la_srb.f CALL seto2(nz,z,nw,wl,aircol,o2xs1, dto2, kout) * Ozone optical depths CALL odo3(nz,z,nw,wl,o3xs,co3, dto3,kout) * SO2 vertical profile and optical depths so2_tc = 0. CALL setso2(ipbl, zpbl, so2pbl, $ so2_tc, nz, z, nw, wl, so2xs, $ tlay, aircol, $ dtso2,kout) * NO2 vertical profile and optical depths no2_tc = 0. CALL setno2(ipbl, zpbl, no2pbl, $ no2_tc, nz, z, nw, wl, no2xs, $ tlay, aircol, $ dtno2,kout) * Aerosol vertical profile, optical depths, single scattering albedo, asymmetry factor tauaer = -1.0 alpha = 1.0 tauaer = 0.235 ssaaer = 0.990 CALL setaer(ipbl, zpbl, aod330, $ tauaer, ssaaer, alpha, $ nz, z, nw, wl, $ dtaer, omaer, gaer, kout ) * Snowpack physical and optical depths, single scattering albedo, asymmetry factor CALL setsnw( $ nz,z,nw,wl, $ dtsnw,omsnw,gsnw,kout) LFIRSTCALL = .FALSE. ENDIF C________________________________________________________________________ C END OF INITIALIZATION (only executed on firstcall of tuvmain) C________________________________________________________________________ * Surface albedo if (albnew .ge. 0.) then C WRITE(kout,*)'wavelength-independent albedo = ', albnew DO iw = 1, nw - 1 albedo(iw) = albnew enddo else CALL setalb(alsurf,nw,wl, $ albedo,kout) endif C cloud optical depth (may be modified at each call, so it has ben moved C outside the if(firstcall) section: * Cloud vertical profile, optical depths, single scattering albedo, asymmetry factor CALL setcld(nz,z,nw,wl, $ lwc,nlevel, $ dtcld,omcld,gcld,kout) * ___ SECTION 6: TIME/SZA LOOP _____________________________________ * Initialize any time-integrated quantities here zen = asza * Loop over time or solar zenith angle (zen): c DO 20, it = 1, nt c c zen = sza(it) c c WRITE(*,200) it, zen, esfact(it) c WRITE(kout,200) it, zen, esfact(it) c 200 FORMAT('step = ', I4,' sza = ', F9.3, c $ ' Earth-sun factor = ', F10.7) c * correction for earth-sun distance DO iw = 1, nw - 1 etf(iw) = f(iw) ENDDO * ____ SECTION 7: CALCULATE ZENITH ANGLE-DEPENDENT QUANTITIES __________ * slant path lengths for spherical geometry CALL sphers(nz,z,zen, dsdh,nid, kout) CALL airmas(nz, dsdh,nid, aircol,vcol,scol, kout) * Recalculate effective O2 optical depth and cross sections for Lyman-alpha * and Schumann-Runge bands, must know zenith angle * Then assign O2 cross section to sj(1,*,*) CALL la_srb(nz,z,tlev,nw,wl,vcol,scol,o2xs1, $ dto2,o2xs,kout) CALL sjo2(nz,nw,o2xs,1, sj,kout) * ____ SECTION 8: WAVELENGTH LOOP ______________________________________ * initialize for wavelength integration CALL zero2(valj,kj,kz) ***** Main wavelength loop: DO 10, iw = 1, nw-1 ** monochromatic radiative transfer. Outputs are: * normalized irradiances edir(iz), edn(iz), eup(iz) * normalized actinic fluxes fdir(iz), fdn(zi), fup(iz) * where * dir = direct beam, dn = down-welling diffuse, up = up-welling diffuse CALL rtlink(nstr, nz, $ iw, albedo(iw), zen, $ dsdh,nid, $ dtrl, $ dto3, $ dto2, $ dtso2, $ dtno2, $ dtcld, omcld, gcld, $ dtaer,omaer,gaer, $ dtsnw,omsnw,gsnw, $ edir, edn, eup, fdir, fdn, fup, $ kout) * Spectral actinic flux, quanta s-1 nm-1 cm-2, all directions: * units conversion: 1.e-4 * (wc*1e-9) / hc DO iz = 1, nz saflux(iz,iw) = etf(iw) * (1.e-13 * wc(iw) / hc) * $ (dirsun*fdir(iz) + difdn*fdn(iz) + difup*fup(iz)) ENDDO *** Accumulate weighted integrals over wavelength, at all altitudes: DO iz = 1, nz * Photolysis rate coefficients (J-values) s-1 DO ij = 1, nj djdw = saflux(iz,iw) * sj(ij,iz,iw) valj(ij,iz) = valj(ij,iz) + djdw * (wu(iw) - wl(iw)) ENDDO ENDDO 10 CONTINUE *^^^^^^^^^^^^^^^^ end wavelength loop * ____ SECTION 9: OUTPUT ______________________________________________ C copy labels into output array if (njout .ne. 42) then WRITE(kout,*) 'There should be 42 J-Values to be updated!' WRITE(kout,*) 'We better stop here ... in tuvmain.f' C callabortstop CALL ABORT STOP 1 endif DO ij = 1, njout jlabelout(ij) = jlabel(ij) ENDDO C C return J values on AZ grid C C for each individual J value do.. DO ij = 1, njout DO iz = 1, nlevel jout(iz,ij) = max(valj(ij,iz),1.E-36) ENDDO ENDDO C *_______________________________________________________________________ c IF(intrct) THEN c WRITE(*,*) 'do you want to do another calculation?' c WRITE(*,*) 'y = yes' c WRITE(*,*) 'any other key = no' c READ(*,1001) again c 1001 FORMAT(A1) c IF(again .EQ. 'y' .OR. again .EQ. 'Y') GO TO 1000 c ENDIF c CLOSE(iout) C CLOSE(kout) END CCC FILE functs.f * This file contains the following user-defined fortran functions: * fo3qy * fo3qy2 * fsum *=============================================================================* FUNCTION fo3qy(w,t) *-----------------------------------------------------------------------------* *= PURPOSE: =* * function to calculate the quantum yield O3 + hv -> O(1D) + O2, =* * according to JPL 2000 recommendation: =* *-----------------------------------------------------------------------------* IMPLICIT NONE REAL w, t, kt, fo3qy REAL a(3), w0(3), nu(3), om(3) DATA a/ 0.887, 2.35, 57./ DATA w0/ 302., 311.1, 313.9/ DATA nu/ 0., 820., 1190./ DATA om/ 7.9, 2.2, 7.4/ fo3qy = 0. kt = 0.695 * t IF(w .LE. 300.) THEN fo3qy = 0.95 ELSEIF(w .GT. 300. .AND. w .LE. 330.) THEN fo3qy = 0.06 + $ a(1) *EXP(-((w-w0(1))/om(1))**4)+ $ a(2)*(T/300.)**4*EXP(-nu(2)/kT)*EXP(-((w-w0(2))/om(2))**2)+ $ a(3) *EXP(-nu(3)/kT)*EXP(-((w-w0(3))/om(3))**2) ELSEIF(w .GT. 330. .AND. w .LE. 345.) THEN fo3qy = 0.06 ELSEIF(w .GT. 345.) THEN fo3qy = 0. ENDIF END FUNCTION fo3qy2(w,t) *-----------------------------------------------------------------------------* *= PURPOSE: =* * function to calculate the quantum yield O3 + hv -> O(1D) + O2, =* * according to: * Matsumi, Y., F. J. Comes, G. Hancock, A. Hofzumanhays, A. J. Hynes, * M. Kawasaki, and A. R. Ravishankara, QUantum yields for production of O(1D) * in the ultraviolet photolysis of ozone: Recommendation based on evaluation * of laboratory data, J. Geophys. Res., 107, 10.1029/2001JD000510, 2002. *-----------------------------------------------------------------------------* IMPLICIT NONE REAL w, t, kt, fo3qy2 REAL A(3), X(3), om(3) REAL q1, q2 DATA A/ 0.8036, 8.9061, 0.1192/ DATA X/ 304.225, 314.957, 310.737/ DATA om/ 5.576, 6.601, 2.187/ fo3qy2 = 0. kt = 0.695 * t q1 = 1. q2 = exp(-825.518/kt) IF(w .LE. 305.) THEN fo3qy2 = 0.90 ELSEIF(w .GT. 305. .AND. w .LE. 328.) THEN fo3qy2 = 0.0765 + $ a(1)* (q1/(q1+q2))*EXP(-((x(1)-w)/om(1))**4)+ $ a(2)*(T/300.)**2 *(q2/(q1+q2))*EXP(-((x(2)-w)/om(2))**2)+ $ a(3)*(T/300.)**1.5 *EXP(-((x(3)-w)/om(3))**2) ELSEIF(w .GT. 328. .AND. w .LE. 340.) THEN fo3qy2 = 0.08 ELSEIF(w .GT. 340.) THEN fo3qy2 = 0. ENDIF END *=============================================================================* FUNCTION fsum(n,x) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Compute the sum of the first N elements of a floating point vector. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= N - INTEGER, number of elements to sum (I)=* *= X - REAL, vector whose components are to be summed (I)=* *-----------------------------------------------------------------------------* IMPLICIT NONE * input: INTEGER n REAL x(n) * function value: REAL fsum * local: INTEGER i fsum = 0. DO 10, i = 1, n fsum=fsum+x(i) 10 CONTINUE RETURN END CCC FILE grids.f * This file contains the following subroutine, related to setting up * grids for numerical calculations: * gridw * gridz * buildz * gridt * gridck *=============================================================================* SUBROUTINE gridw(wstart, wstop, nwint, $ nw,wl,wc,wu,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Create the wavelength grid for all interpolations and radiative transfer =* *= calculations. Grid may be irregularly spaced. Wavelengths are in nm. =* *= No gaps are allowed within the wavelength grid. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of wavelength grid _points_ (O)=* *= WL - REAL, vector carrying the lower limit of each wavel. interval (O)=* *= WC - REAL, vector carrying the center wavel of each wavel. interval (O)=* *= (wc(i) = 0.5*(wl(i)+wu(i), i = 1..NW-1) =* *= WU - REAL, vector carrying the upper limit of each wavel. interval (O)=* *= *= MOPT- INTEGER OPTION for wave-length IF 3 good for JO2 (O)=* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input: REAL wstart, wstop INTEGER nwint * output: REAL wl(kw), wc(kw), wu(kw) INTEGER nw integer wn(kw) * local: INTEGER mopt REAL wincr INTEGER iw, i CHARACTER*40 fi CHARACTER*20 wlabel REAL airout INTEGER mrefr REAL dum LOGICAL ok *_______________________________________________________________________ **** chose wavelength grid * some pre-set options * mopt = 1 equal spacing * mopt = 2 grid defined in data table * mopt = 3 user-defined * mopt = 4 fast-TUV, troposheric wavelengths only * mopt = 5 high resolution grid for O3 isotopologue study * mopt = 6 create uniform grid in air-wavelength scale * mopt = 10 Landgraf and Crutzen, 1998 * mopt = 11 fastJ, Wild et al. 2000 * mopt = 12 fastJ2, Bian and Prather, 2002 * mopt = 13 UV-b, UV-a, Visible mopt = 2 IF(nwint .EQ. -156) mopt = 2 IF(nwint .EQ. -7) mopt = 4 IF(nwint .eq. -10) mopt = 10 IF(nwint .eq. -11) mopt = 11 IF(nwint .eq. -12) mopt = 12 IF(nwint .eq. -13) mopt = 13 IF (mopt .EQ. 1) GO TO 1 IF (mopt .EQ. 2) GO TO 2 IF (mopt .EQ. 3) GO TO 3 IF (mopt .EQ. 4) GO TO 4 IF (mopt .EQ. 5) GO TO 5 IF (mopt .EQ. 6) GO TO 6 IF (mopt .EQ. 10) GO TO 10 IF (mopt .EQ. 11) GO TO 11 IF (mopt .EQ. 12) GO TO 12 IF (mopt .EQ. 13) GO TO 13 *_______________________________________________________________________ 1 CONTINUE wlabel = 'equal spacing' nw = nwint + 1 wincr = (wstop - wstart) / FLOAT (nwint) DO iw = 1, nw-1 wl(iw) = wstart + wincr*FLOAT(iw-1) wu(iw) = wl(iw) + wincr wc(iw) = ( wl(iw) + wu(iw) )/2. ENDDO wl(nw) = wu(nw-1) GO TO 9 *_______________________________________________________________________ 2 CONTINUE * Input from table. In this example: * Wavelength grid will be read from a file. * First line of table is: nw = number of wavelengths (no. of intervals + 1) * Then, nw wavelengths are read in, and assigned to wl(iw) * Finally, wu(iw) and wc(iw) are computed from wl(iw) c wlabel = 'isaksen.grid' wlabel = 'combined.grid' fi = 'DATAE1/GRIDS/'//wlabel OPEN(newunit=ilu,file=fi,status='old') READ(ilu,*) nw DO iw = 1, nw READ(ilu,*) wl(iw) ENDDO CLOSE(ilu) DO iw = 1, nw-1 wu(iw) = wl(iw+1) wc(iw) = 0.5*(wl(iw) + wu(iw)) ENDDO GO TO 9 *_______________________________________________________________________ 3 CONTINUE * user-defined grid. In this example, a single calculation is used to * obtain results for two 1 nm wide intervals centered at 310 and 400 nm: * interval 1 : 1 nm wide, centered at 310 nm * interval 3 : 2 nm wide, centered at 400 nm * (inteval 2 : 310.5 - 399.5 nm, required to connect intervals 1 & 3) nw = 4 wl(1) = 309.5 wl(2) = 310.5 wl(3) = 399.5 wl(4) = 400.5 DO iw = 1, nw-1 wu(iw) = wl(iw+1) wc(iw) = 0.5*(wl(iw) + wu(iw)) ENDDO GO TO 9 *_______________________________________________________________________ 4 CONTINUE wlabel = 'fast-TUV tropospheric grid' fi = 'DATAE1/GRIDS/fast_tuv.grid' OPEN(NEWUNIT=ilu,FILE=fi,STATUS='old') DO iw = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO * skip wavelength shorter than 289.9 nm DO iw = 1, 10 READ(UNIT=ilu,FMT=*) ENDDO nw = 8 DO iw = 1, nw-1 READ(UNIT=ilu,FMT=*) dum, wl(iw), dum, dum ENDDO CLOSE(UNIT=ilu) wl(nw) = dum DO iw = 1, nw-1 wu(iw) = wl(iw+1) wc(iw) = 0.5*(wl(iw) + wu(iw)) ENDDO GO TO 9 *_______________________________________________________________________ 5 continue * use standard grid up to 205.8 nm * elsewhere, use 10 cm-1 grid to 1000 nm wlabel = 'combined.grid' fi = 'DATAE1/GRIDS/'//wlabel OPEN(newunit=ilu,file=fi,status='old') READ(ilu,*) DO iw = 1, 38 READ(ilu,*) wl(iw) ENDDO CLOSE(ilu) DO i = 1, 3859 iw = 3859 - i + 39 wn(iw) = 10000 + 10*(i-1) wl(iw) = 1.E7/float(wn(iw)) ENDDO nw = 3859 + 38 nwint = nw - 1 DO iw = 1, nwint wu(iw) = wl(iw+1) wc(iw) = (wl(iw) + wu(iw))/2. ENDDO GO TO 9 *_______________________________________________________________________ 6 CONTINUE ***** Correction for air-vacuum wavelength shift: * The TUV code assumes that all working wavelengths are strictly IN-VACUUM. This is for ALL * spectral data including extraterrestrial fluxes, ozone (and other) absorption cross sections, * and various weighting functons (action spectra, photolysis cross sections, instrument spectral * response functions). If the original data are specified in-air, conversion to in-vacuum must be * made when reading those data. * Occasionally, users may want their results to be given for wavelengths measured IN-AIR. * The shift between IN-VACUUM and IN-AIR wavelengths depends on the index of refraction * of air, which in turn depends on the local density of air, which in turn depends on * altitude, temperature, etc. * Here, we provide users with the option to use a wavelength grid IN-AIR, at the air density * corresponding to the selected altitude, airout. * The actual radiative transfer calculations will be done strictly with IN-VACUUM values. * create grid that will be nicely spaced in air wavelengths. wlabel = 'grid in air wavelengths' nw = nwint + 1 wincr = (wstop - wstart) / FLOAT (nwint) DO iw = 1, nw-1 wl(iw) = wstart + wincr*FLOAT(iw-1) wu(iw) = wl(iw) + wincr wc(iw) = ( wl(iw) + wu(iw) )/2. ENDDO wl(nw) = wu(nw-1) * shift by refractive index to vacuum wavelengths, for use in tuv airout = 2.45e19 mrefr = 1 CALL wshift(mrefr, nw, wl, airout, kout) CALL wshift(mrefr, nwint, wc, airout, kout) CALL wshift(mrefr, nwint, wu, airout, kout) GO TO 9 *_______________________________________________________________________ * Landgraf and Crutzen 1998 10 CONTINUE nw = 6 wl(1) = 289.0 wl(2) = 305.5 wl(3) = 313.5 wl(4) = 337.5 wl(5) = 422.5 wl(6) = 752.5 DO iw = 1, nw-1 wu(iw) = wl(iw+1) wc(iw) = 0.5*(wl(iw) + wu(iw)) ENDDO GO TO 9 *_______________________________________________________________________ * Wild 2000 11 CONTINUE nw = 8 wl(1) = 289.00 wl(2) = 298.25 wl(3) = 307.45 wl(4) = 312.45 wl(5) = 320.30 wl(6) = 345.0 wl(7) = 412.5 wl(8) = 850.0 DO iw = 1, nw-1 wu(iw) = wl(iw+1) wc(iw) = 0.5*(wl(iw) + wu(iw)) ENDDO GO TO 9 *_______________________________________________________________________ * Bian and Prather 2002 12 CONTINUE nw = 8 wl(1) = 291.0 wl(2) = 298.3 wl(3) = 307.5 wl(4) = 312.5 wl(5) = 320.3 wl(6) = 345.0 wl(7) = 412.5 wl(8) = 850.0 DO iw = 1, nw-1 wu(iw) = wl(iw+1) wc(iw) = 0.5*(wl(iw) + wu(iw)) ENDDO GO TO 9 *_______________________________________________________________________ *_______________________________________________________________________ * UV-b, UV-A, Vis 13 CONTINUE nw = 4 wl(1) = 280.0 wl(2) = 315.0 wl(3) = 400.0 wl(4) = 700.0 DO iw = 1, nw-1 wu(iw) = wl(iw+1) wc(iw) = 0.5*(wl(iw) + wu(iw)) ENDDO GO TO 9 *_______________________________________________________________________ 9 CONTINUE * check grid for assorted improprieties: CALL gridck(kw,nw,wl,ok,kout) IF (.NOT. ok) THEN WRITE(*,*)'STOP in GRIDW: The w-grid does not make sense' STOP ENDIF *_______________________________________________________________________ RETURN END *=============================================================================* SUBROUTINE gridz(zin,nlevel,zstart, zstop, nz, z, & zout, izout, kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Create the altitude grid for all interpolations and radiative transfer =* *= calculations. Grid may be irregularly spaced. All altitudes are in =* *= kilometers (km). The altitude at index 1 specifies the surface elevation=* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= nz - INTEGER, number of altitude points (levels) (O)=* *= z - REAL, vector of altitude levels (in km) (O)=* *-----------------------------------------------------------------------------* IMPLICIT NONE * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input REAL zstart, zstop, zout REAL zin(*) INTEGER nlevel * output: altitude working grid, index for output REAL z(kz) INTEGER nz INTEGER izout * local: REAL zincr INTEGER i, n, nlev LOGICAL ok *_______________________________________________________________________ * Set vertical grid of the atmosphere: atmospheric level altitudes * (in real km), including top-most level. * User specifies grid (surface at lowest km value), increasing * upwards: * - nz = total number of user levels * - z(I) = altitude in km for each level. * z(1) is the elevation of the surface (km asl), and can be specified either * here or in the main program. * Non-uniform spacing is possible: * - zincr = altitude increment between current and previous level (km) * - nlev = number of levels in current equally-spaced section * - n = index of top level of equally-spaced section * Note "levels" are vertical points * "layers" are vertical distances between levels * Grid selection options: * 1 = standard equally spaced grid, manual * 2 = standard equally spaced grid, auto generated * 3 = variable spacing grid, example for snow * 4 = mirage z-grid for Mexico City * 5 = arbitrary user-defined grid GO TO 5 *-----grid option 2: manual ----------------- * entire grid (nz levels) in increments zincr 1 CONTINUE WRITE(*,*) 'equally spaced z-grid' zincr = (zstop - zstart) / FLOAT(nz - 1) z(1) = zstart DO i = 2, nz z(i) = z(1) + zincr*FLOAT(i-1) ENDDO GOTO 10 *-----grid option 3: automatic ----------------- * entire grid (nz levels) in increments zincr 2 CONTINUE WRITE(*,*) 'equally spaced z-grid' zincr = (zstop - zstart) / FLOAT(nz - 1) nlev = nz-1 n = 1 CALL buildz(zincr, nlev, n, z) GOTO 10 *-----grid option 4: variable grid example---------------------- *-----copy & edit this section for non-uniform grid---- * the example provided below is high vertical resolution in * snow, with atmosphere above it. 3 CONTINUE WRITE(*,*) 'snow-atmosphere grid' * 0.-10. cm from ground, in 1 cm increments ( 1 cm = 1e-5 km): zincr = 1.e-5 nlev = 10 n = 1 CALL buildz(zincr,nlev,n,z) * 10-90 cm from ground, in 10 cm increments ( 1 cm = 1e-5 km): zincr = 1.e-4 nlev = 8 CALL buildz(zincr,nlev,n,z) * 90-95 cm from ground, in 1x 5 cm increment ( 1 cm = 1e-5 km): zincr = 5.e-5 nlev = 1 CALL buildz(zincr,nlev,n,z) * 95-99 cm from ground, in 4x 1 cm increments ( 1 cm = 1e-5 km): zincr = 1.e-5 nlev = 4 CALL buildz(zincr,nlev,n,z) * 99-99.5 cm from ground, in 1x 0.5 cm increment ( 1 cm = 1e-5 km): zincr = 5.e-6 nlev = 1 CALL buildz(zincr,nlev,n,z) * 99.5 centimeters - 1m, in 0.1 cm increments (1 cm = 1e-5 km): zincr = 1.e-6 nlev = 5 CALL buildz(zincr,nlev,n,z) *atmosphere * 1.-10. m in 1 m increments zincr = 1.e-3 nlev = 9 CALL buildz(zincr,nlev,n,z) * 10.-100 m in 10 m increments zincr = 1.e-2 nlev = 9 CALL buildz(zincr,nlev,n,z) * 100.- 1000. meters, in 100 m increments zincr = 1.e-1 nlev = 9 CALL buildz(zincr,nlev,n,z) * 1.-2. km in 1 km increments zincr = 1. nlev = 1 CALL buildz(zincr,nlev,n,z) * 2.-80. km in 2 km increments zincr = 2. nlev = 39 CALL buildz(zincr,nlev,n,z) GOTO 10 *-----grid option 4: grid for Mexico City 4 CONTINUE WRITE(*,*) 'mirage z-grid' * grid for mirage km: incr(range)i * 0.1(0-4) 2-41 * 0.2(4-8) 42-61 * 1(8-30) 62-83 * 2(30-50) 84-93 * 5(50-80) 94-99 nz = 99 z(1) = zstart DO i = 2, 41 z(i) = z(1) + 0.1*FLOAT(i-1) ENDDO DO i = 42, 61 z(i) = z(41) + 0.2*FLOAT(i-41) ENDDO DO i = 62, 83 z(i) = z(61) + 1.*FLOAT(i-61) ENDDO DO i = 84, 93 z(i) = z(83) + 2.*FLOAT(i-83) ENDDO DO i = 94, 99 z(i) = z(93) + 5.*FLOAT(i-93) ENDDO GOTO 10 *-----grid option 5: user defined 5 CONTINUE * insert your grid values here: * specify: * nz = total number of altitudes * Table: z(iz), where iz goes from 1 to nz C use model levels for vertical grid where available do 12, i = 1, nlevel z(i) = zin(i) *1E-3 12 continue nz = nlevel C fill up between model top and 50km with 1km grid spacing 20 continue if (z(nz) .ge. 50.) goto 30 nz = nz + 1 if (nz .gt. kz) stop "GRIDZ: not enough memory, increase kz" z(nz) = z(nz-1) + 1. goto 20 C 30 continue C GOTO 10 *-----end of user options. *-----grid option 6: high resolution window 6 CONTINUE * insert your grid values here: * specify: * nz = total number of altutudes * Table: z(iz), where iz goes from 1 to nz WRITE(*,*) 'user-defined grid, named...' goto 10 *-----end of user options. *------------------------------------------------ 10 CONTINUE * Insert additional altitude for selected outputs. c DO i = 1, nz c IF(ABS(z(i) - zout) .LT. 0.001) THEN c izout = i c GO TO 24 c ENDIF c ENDDO * locate index for new altitude c izout = 0 c DO i = 1, nz c IF(z(i) .GT. zout) THEN c izout = i c GO TO 22 c ENDIF c ENDDO c 22 CONTINUE c IF(izout .LE. 1) STOP 'zout not in range - ' c * shift overlying levels and insert new point c nz = nz + 1 c DO i = nz, izout + 1, -1 c z(i) = z(i-1) c ENDDO c z(izout) = zout c 24 CONTINUE * check grid for assorted improprieties: c 99 CONTINUE CALL gridck(kz,nz,z,ok,kout) IF (.NOT. ok) THEN WRITE(*,*)'STOP in GRIDZ: The z-grid does not make sense' STOP ENDIF *_______________________________________________________________________ RETURN END *=============================================================================* SUBROUTINE buildz(zincr,nlev,n,z) *-----------------------------------------------------------------------------* *= Purpose: to construct the altitude grid from parameters in gridz =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) REAL zincr ! i INTEGER nlev ! i INTEGER n ! i/o REAL z(kz) ! i/o INTEGER i, j ! internal j = 0 DO i = n + 1, n + nlev j = j + 1 z(i) = z(n) + FLOAT(j)*zincr ENDDO n = n + nlev RETURN END *=============================================================================* c SUBROUTINE gridt(lat, lon, tmzone, c $ iyear, imonth, iday, c $ lzenit, tstart, tstop, c $ nt, t, sza, esrm2) c c *-----------------------------------------------------------------------------* c *= Subroutine to create time (or solar zenith angle) grid =* c *= Also computes earth-sun distance (1/R**2) correction. =* c *-----------------------------------------------------------------------------* c c IMPLICIT NONE c c c INCLUDE 'params' c c * BROADLY USED PARAMETERS: c *_________________________________________________ c * i/o file unit numbers c INTEGER :: ilu c INTEGER kout c * output c PARAMETER(kout=6) c *_________________________________________________ c * altitude, wavelength, time (or solar zenith angle) grids c INTEGER kz, kw c * altitude c PARAMETER(kz=151) c * wavelength c PARAMETER(kw=157) c *_________________________________________________ c * number of weighting functions c INTEGER kj c * wavelength and altitude dependent c PARAMETER(kj=90) c c * delta for adding points at beginning or end of data grids c REAL deltax c PARAMETER (deltax = 1.E-5) c c * some constants... c c * pi: c REAL pi c PARAMETER(pi=3.1415926535898) c c * radius of the earth, km: c REAL radius c PARAMETER(radius=6.371E+3) c c * Planck constant x speed of light, J m c c REAL hc c PARAMETER(hc = 6.626068E-34 * 2.99792458E8) c c * largest number of the machine: c REAL largest c PARAMETER(largest=1.E+36) c c * small numbers (positive and negative) c REAL pzero, nzero c PARAMETER(pzero = +10./largest) c PARAMETER(nzero = -10./largest) c c * machine precision c c REAL precis c PARAMETER(precis = 1.e-7) c c * INPUTS c c REAL lat, lon, tmzone c INTEGER iyear, imonth, iday c LOGICAL lzenit c INTEGER nt c REAL tstart, tstop c c c * OUTPUTS c c REAL t, sza, esrm2 c c * INTERNAL c c INTEGER it c REAL ut, dt c c INTEGER jday, nday c LOGICAL oky, okm, okd c c REAL az, el, soldia, soldst c c * switch for refraction correction to solar zenith angle. Because c * this is only for the observed sza at the surface, do not use. c c LOGICAL lrefr c DATA lrefr /.FALSE./ c c *************** c c IF(nt .EQ. 1) THEN c dt = 0. c ELSE c dt = (tstop - tstart) / FLOAT(nt - 1) c ENDIF c c DO 10 it = 1, nt c t(it) = tstart + dt * FLOAT(it - 1) c c * solar zenith angle calculation: c * If lzenit = .TRUE., use selected solar zenith angles, also c * set Earth-Sun distance to 1 AU. c c IF (lzenit) THEN c sza(it) = t(it) c esrm2(it) = 1. c c * If lzenit = .FALSE., compute solar zenith angle for specified c * location, date, time of day. Assume no refraction (lrefr = .FALSE.) c * Also calculate corresponding c * Earth-Sun correcton factor. c c ELSE c CALL calend(iyear, imonth, iday, c $ jday, nday, oky, okm, okd) c IF( oky .AND. okm .AND. okd) THEN c c ut = t(it) - tmzone c CALL sunae(iyear, jday, ut, lat, lon, lrefr, c & az, el, soldia, soldst ) c sza(it) = 90. - el c esrm2(it) = 1./(soldst*soldst) c ELSE c WRITE(*,*) '**** incorrect date specification' c STOP ' in gridt ' c ENDIF c ENDIF c c 10 CONTINUE c RETURN c END *=============================================================================* SUBROUTINE gridck(k,n,x,ok, kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Check a grid X for various improperties. The values in X have to comply =* *= with the following rules: =* *= 1) Number of actual points cannot exceed declared length of X =* *= 2) Number of actual points has to be greater than or equal to 2 =* *= 3) X-values must be non-negative =* *= 4) X-values must be unique =* *= 5) X-values must be in ascending order =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= K - INTEGER, length of X as declared in the calling program (I)=* *= N - INTEGER, number of actual points in X (I)=* *= X - REAL, vector (grid) to be checked (I)=* *= OK - LOGICAL, .TRUE. -> X agrees with rules 1)-5) (O)=* *= .FALSE.-> X violates at least one of 1)-5) =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input: INTEGER k, n REAL x(k) * output: LOGICAL ok * local: INTEGER i *_______________________________________________________________________ ok = .TRUE. * check if dimension meaningful and within bounds IF (n .GT. k) THEN ok = .false. WRITE(kout,100) RETURN ENDIF 100 FORMAT('Number of data exceeds dimension') IF (n .LT. 2) THEN ok = .FALSE. WRITE(kout,101) RETURN ENDIF 101 FORMAT('Too few data, number of data points must be >= 2') * disallow negative grid values IF(x(1) .LT. 0.) THEN ok = .FALSE. WRITE(kout,105) RETURN ENDIF 105 FORMAT('Grid cannot start below zero') * check sorting DO 10, i = 2, n IF( x(i) .LE. x(i-1)) THEN ok = .FALSE. WRITE(kout,110) RETURN ENDIF 10 CONTINUE 110 FORMAT('Grid is not sorted or contains multiple values') *_______________________________________________________________________ RETURN END CCC FILE la_srb.f * This file contains the following subroutines, related to the calculation * of radiation at Lyman-alpha and Schumann-Runge wavelengths: * la_srb * lymana * schum * effxs * calc_params * init_xs * sjo2 * and the following functions * chebev *=============================================================================* SUBROUTINE la_srb(nz,z,tlev,nw,wl,vcol,scol,o2xs1,dto2,o2xs,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Compute equivalent optical depths for O2 absorption, and O2 effective =* *= absorption cross sections, parameterized in the Lyman-alpha and SR bands =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NZ - INTEGER, number of specified altitude levels in the working (I)=* *= grid =* *= Z - REAL, specified altitude working grid (km) (I)=* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lxower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= CZ - REAL, number of air molecules per cm^2 at each specified (I)=* *= altitude layer =* *= ZEN - REAL, solar zenith angle (I)=* *= =* *= O2XS1 - REAL, O2 cross section from rdo2xs (I)=* *= =* *= DTO2 - REAL, optical depth due to O2 absorption at each specified (O)=* *= vertical layer at each specified wavelength =* *= O2XS - REAL, molecular absorption cross section in SR bands at (O)=* *= each specified altitude and wavelength. Includes Herzberg =* *= continuum. =* *-----------------------------------------------------------------------------* IMPLICIT NONE c c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) REAL wl(kw) REAL z(kz) INTEGER nz, nw, iz, iw REAL vcol(kz), scol(kz) REAL o2col(kz) REAL o2xs1(kw) REAL dto2(kz,kw), o2xs(kz,kw) REAL secchi(kz) REAL tlev(kz) * Lyman-alpha variables * O2 optical depth and equivalent cross section in the Lyman-alpha region INTEGER ila, nla, kla PARAMETER (kla = 2) REAL wlla(kla) REAL dto2la(kz, kla-1), o2xsla(kz, kla-1) SAVE ila * grid on which Koppers' parameterization is defined * O2 optical depth and equivalent cross section on Koppers' grid INTEGER isrb, nsrb, ksrb PARAMETER(ksrb = 18) REAL wlsrb(ksrb) REAL dto2k(kz, ksrb-1), o2xsk(kz, ksrb-1) SAVE isrb INTEGER i LOGICAL call1 DATA call1/.TRUE./ SAVE call1 * Wavelengths for Lyman alpha and SRB parameterizations: DATA nla /1/ DATA wlla/ 121.4, 121.9/ DATA nsrb /17/ DATA wlsrb/174.4, 177.0, 178.6, 180.2, 181.8, 183.5, 185.2, 186.9, $ 188.7, 190.5, 192.3, 194.2, 196.1, 198.0, 200.0, 202.0, $ 204.1, 205.8/ *---------------------------------------------------------------------- * initalize O2 cross sections *---------------------------------------------------------------------- DO iz = 1, nz DO iw =1, nw - 1 o2xs(iz,iw) = o2xs1(iw) ENDDO ENDDO IF(wl(1) .GT. wlsrb(nsrb)) RETURN *---------------------------------------------------------------------- * Slant O2 column and x-sections. *---------------------------------------------------------------------- DO iz = 1, nz o2col(iz) = 0.2095 * scol(iz) ENDDO *---------------------------------------------------------------------- * On first call, check that the user wavelength grid, WL(IW), is compatible * with the wavelengths for the parameterizations of the Lyman-alpha and SRB. * Also compute and save corresponding grid indices (ILA, ISRB) *---------------------------------------------------------------------- IF (call1) THEN ** locate Lyman-alpha wavelengths on grid ila = 0 DO iw = 1, nw IF(ABS(wl(iw) - wlla(1)) .LT. 10.*precis) THEN ila = iw GO TO 5 ENDIF ENDDO 5 CONTINUE * check IF(ila .EQ. 0) THEN WRITE(*,*) 'For wavelengths below 205.8 nm, only the' WRITE(*,*) 'pre-specified wavelength grid is permitted' WRITE(*,*) 'Use nwint=-156, or edit subroutine gridw.f' STOP ' Lyman alpha grid mis-match - 1' ENDIF DO i = 2, nla + 1 IF(ABS(wl(ila + i - 1) - wlla(i)) .GT. 10.*precis) THEN WRITE(*,*) 'Lyman alpha grid mis-match - 2' STOP ENDIF ENDDO ** locate Schumann-Runge wavelengths on grid isrb = 0 DO iw = 1, nw IF(ABS(wl(iw) - wlsrb(1)) .LT. 10.*precis) THEN isrb = iw GO TO 6 ENDIF ENDDO 6 CONTINUE * check IF(isrb .EQ. 0) THEN WRITE(*,*) 'For wavelengths below 205.8 nm, only the' WRITE(*,*) 'pre-specified wavelength grid is permitted' WRITE(*,*) 'Use nwint=-156, or edit subroutine gridw.f' STOP ' SRB grid mis-match - 1' ENDIF DO i = 2, nsrb + 1 IF(ABS(wl(isrb + i - 1) - wlsrb(i)) .GT. 10.* precis) THEN WRITE(*,*) ' SRB grid mismatch - w' STOP ENDIF ENDDO IF (call1) call1 = .FALSE. ENDIF *---------------------------------------------------------------------- * Effective secant of solar zenith angle. * Use 2.0 if no direct sun (value for isotropic radiation) * For nz, use value at nz-1 *---------------------------------------------------------------------- DO i = 1, nz - 1 secchi(i) = scol(i)/vcol(i) IF(scol(i) .GT. largest/10.) secchi(i) = 2. ENDDO secchi(nz) = secchi(nz-1) *--------------------------------------------------------------------- * Lyman-Alpha parameterization, output values of O2 optical depth * and O2 effective (equivalent) cross section *---------------------------------------------------------------------- CALL lymana(nz,o2col,secchi,dto2la,o2xsla,kout) DO iw = ila, ila + nla - 1 DO iz = 1, nz dto2(iz,iw) = dto2la(iz, iw - ila + 1) o2xs(iz,iw) = o2xsla(iz, iw - ila + 1) ENDDO ENDDO *------------------------------------------------------------------------------ * Koppers' parameterization of the SR bands, output values of O2 * optical depth and O2 equivalent cross section *------------------------------------------------------------------------------ CALL schum(nz,o2col,tlev,secchi,dto2k,o2xsk,kout) DO iw = isrb, isrb + nsrb - 1 DO iz = 1, nz dto2(iz,iw) = dto2k(iz, iw - isrb + 1) o2xs(iz,iw) = o2xsk(iz, iw - isrb + 1) ENDDO ENDDO RETURN END *=============================================================================* SUBROUTINE lymana(nz,o2col,secchi,dto2la,o2xsla,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Calculate the effective absorption cross section of O2 in the Lyman-Alpha=* *= bands and an effective O2 optical depth at all altitudes. Parameterized =* *= after: Chabrillat, S., and G. Kockarts, Simple parameterization of the =* *= absorption of the solar Lyman-Alpha line, Geophysical Research Letters, =* *= Vol.24, No.21, pp 2659-2662, 1997. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NZ - INTEGER, number of specified altitude levels in the working (I)=* *= grid =* *= O2COL - REAL, slant overhead O2 column (molec/cc) at each specified (I)=* *= altitude =* *= DTO2LA - REAL, optical depth due to O2 absorption at each specified (O)=* *= vertical layer =* *= O2XSLA - REAL, molecular absorption cross section in LA bands (O)=* *-----------------------------------------------------------------------------* IMPLICIT NONE * input: c c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input: INTEGER nz REAL o2col(kz) REAL secchi(kz) * output REAL dto2la(kz,*), o2xsla(kz,*) * local variables REAL(kind(0.0d0)) :: rm(kz), ro2(kz) REAL(kind(0.0d0)) :: b(3), c(3), d(3), e(3) DATA b/ 6.8431D-01, 2.29841D-01, 8.65412D-02/, > c/8.22114D-21, 1.77556D-20, 8.22112D-21/, > d/ 6.0073D-21, 4.28569D-21, 1.28059D-20/, > e/8.21666D-21, 1.63296D-20, 4.85121D-17/ INTEGER iz, i REAL xsmin *------------------------------------------------------------------------------* *sm: set minimum cross section xsmin = 1.e-20 * calculate reduction factors at every altitude DO iz = 1, nz rm(iz) = 0.D+00 ro2(iz) = 0.D+00 DO i = 1, 3 rm(iz) = rm(iz) + b(i) * EXP(-c(i) * DBLE(o2col(iz))) ro2(iz) = ro2(iz) + d(i) * EXP(-e(i) * DBLE(o2col(iz))) ENDDO ENDDO * calculate effective O2 optical depths and effective O2 cross sections DO iz = 1, nz-1 IF (rm(iz) .GT. 1.0D-100) THEN IF (ro2(iz) .GT. 1.D-100) THEN o2xsla(iz,1) = ro2(iz)/rm(iz) ELSE o2xsla(iz,1) = xsmin ENDIF IF (rm(iz+1) .GT. 0.) THEN dto2la(iz,1) = LOG(rm(iz+1)) / secchi(iz+1) $ - LOG(rm(iz)) / secchi(iz) ELSE dto2la(iz,1) = 1000. ENDIF ELSE dto2la(iz,1) = 1000. o2xsla(iz,1) = xsmin ENDIF ENDDO * do top layer separately dto2la(nz,1) = 0. IF(rm(nz) .GT. 1.D-100) THEN o2xsla(nz,1) = ro2(nz)/rm(nz) ELSE o2xsla(nz,1) = xsmin ENDIF *----------------------------------------------------------------------------* END *=============================================================================* SUBROUTINE schum(nz, o2col, tlev, secchi, dto2, o2xsk,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Calculate the equivalent absorption cross section of O2 in the SR bands. =* *= The algorithm is based on parameterization of G.A. Koppers, and =* *= D.P. Murtagh [ref. Ann.Geophys., 14 68-79, 1996] =* *= Final values do include effects from the Herzberg continuum. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NZ - INTEGER, number of specified altitude levels in the working (I)=* *= grid =* *= O2COL - REAL, slant overhead O2 column (molec/cc) at each specified (I)=* *= altitude =* *= TLEV - tmeperature at each level (I)=* *= SECCHI - ratio of slant to vertical o2 columns (I)=* *= DTO2 - REAL, optical depth due to O2 absorption at each specified (O)=* *= vertical layer at each specified wavelength =* *= O2XSK - REAL, molecular absorption cross section in SR bands at (O)=* *= each specified wavelength. Includes Herzberg continuum =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) *---------- INTEGER nz REAL o2col(kz), o2col1(kz) REAL tlev(kz), secchi(kz) REAL dto2(kz,17), o2xsk(kz,17) INTEGER i, k, ktop, ktop1, kbot REAL XS(17), X REAL xslod(17) LOGICAL firstcall SAVE firstcall DATA firstcall /.TRUE./ DATA xslod /6.2180730E-21, 5.8473627E-22, 5.6996334E-22, $ 4.5627094E-22, 1.7668250E-22, 1.1178808E-22, $ 1.2040544E-22, 4.0994668E-23, 1.8450616E-23, $ 1.5639540E-23, 8.7961075E-24, 7.6475608E-24, $ 7.6260556E-24, 7.5565696E-24, 7.6334338E-24, $ 7.4371992E-24, 7.3642966E-24/ c------------------------------------------ *sm Initialize cross sections to values *sm at large optical depth c------------------------------------------ DO k = 1, nz DO i = 1, 17 o2xsk(k,i) = xslod(i) ENDDO ENDDO c------------------------------------------ c Loads Chebyshev polynomial Coeff. c------------------------------------------ IF (firstcall) THEN CALL INIT_XS firstcall = .FALSE. ENDIF c------------------------------------------ c Calculate cross sections *sm: Set smallest O2col = exp(38.) molec cm-2 *sm to stay in range of parameterization *sm given by Koppers et al. at top of atm. c------------------------------------------ ktop = 121 kbot = 0 DO k=1,nz !! loop for alt o2col1(k) = MAX(o2col(k),EXP(38.)) x = ALOG(o2col1(k)) IF (x .LT. 38.0) THEN ktop1 = k-1 ktop = MIN(ktop1,ktop) ELSE IF (x .GT. 56.0) THEN kbot = k ELSE CALL effxs( x, tlev(k), xs ) DO i=1,17 o2xsk(k,i) = xs(i) END DO ENDIF END DO !! finish loop for alt c------------------------------------------ c fill in cross section where X is out of range c by repeating edge table values c------------------------------------------ *sm do not allow kbot = nz to avoid division by zero in * no light case. IF(kbot .EQ. nz) kbot = nz - 1 DO k=1,kbot DO i=1,17 o2xsk(k,i) = o2xsk(kbot+1,i) END DO END DO DO k=ktop+1,nz DO i=1,17 o2xsk(k,i) = o2xsk(ktop,i) END DO END DO c------------------------------------------ c Calculate incremental optical depths c------------------------------------------ DO i=1,17 ! loop over wavelength DO k=1,nz-1 ! loop for alt c... calculate an optical depth weighted by density *sm: put in mean value estimate, if in shade IF (ABS(1. - o2col1(k+1)/o2col1(k)) .LE. 2.*precis) THEN dto2(k,i) = o2xsk(k+1,i)*o2col1(k+1)/(nz-1) ELSE dto2(k,i) = ABS( $ ( o2xsk(k+1,i)*o2col1(k+1) - o2xsk(k,i)*o2col1(k) ) $ / ( 1. + ALOG(o2xsk(k+1,i)/o2xsk(k,i)) $ / ALOG(o2col1(k+1)/o2col1(k)) ) ) c... change to vertical optical depth dto2(k,i) = 2. * dto2(k,i) / (secchi(k)+secchi(k+1)) ENDIF END DO dto2(nz,i) = 0.0 ! set optical depth to zero at top END DO RETURN END *=============================================================================* SUBROUTINE EFFXS( X, T, XS ) C Subroutine for evaluating the effective cross section C of O2 in the Schumann-Runge bands using parameterization C of G.A. Koppers, and D.P. Murtagh [ref. Ann.Geophys., 14 C 68-79, 1996] C C method: C ln(xs) = A(X)[T-220]+B(X) C X = log of slant column of O2 C A,B calculated from Chebyshev polynomial coeffs C AC and BC using NR routine chebev. Assume interval C is 38<ln(NO2)<56. C C Revision History: C C drm 2/97 initial coding C C------------------------------------------------------------- IMPLICIT NONE REAL NO2, T, X REAL XS(17) REAL A(17), B(17) INTEGER I CALL CALC_PARAMS( X, A, B ) DO I = 1,17 XS(I) = EXP( A(I)*( T - 220.) + B(I) ) ENDDO RETURN END *=============================================================================* SUBROUTINE CALC_PARAMS( X, A, B ) C------------------------------------------------------------- C C calculates coefficients (A,B), used in calculating the C effective cross section, for 17 wavelength intervals C as a function of log O2 column density (X) C Wavelength intervals are defined in WMO1985 C C------------------------------------------------------------- IMPLICIT NONE REAL X REAL A(17), B(17) REAL CHEBEV REAL(kind(0.0d0)) :: AC(20,17) REAL(kind(0.0d0)) :: BC(20,17) ! Chebyshev polynomial coeffs REAL WAVE_NUM(17) COMMON /XS_COEFFS/ AC, BC, WAVE_NUM INTEGER I C call Chebyshev Evaluation routine to calc A and B from C set of 20 coeficients for each wavelength DO I=1,17 A(I) = CHEBEV(38.0 , 56.0, AC(1,I), 20, X) B(I) = CHEBEV(38.0 , 56.0, BC(1,I), 20, X) ENDDO RETURN END *=============================================================================* SUBROUTINE INIT_XS C------------------------------------------------------------- C loads COMMON block XS_COEFFS containing the Chebyshev C polynomial coeffs necessary to calculate O2 effective C cross-sections C C------------------------------------------------------------- REAL(kind(0.0d0)) :: AC(20,17) REAL(kind(0.0d0)) :: BC(20,17) ! Chebyshev polynomial coeffs REAL WAVE_NUM(17) COMMON /XS_COEFFS/ AC, BC, WAVE_NUM C locals INTEGER IN_LUN ! file unit number INTEGER IOST ! i/o status INTEGER I, J IN_LUN = -1 OPEN (NEWUNIT=IN_LUN, FILE= $ 'DATAE1/O2/effxstex.txt',FORM='FORMATTED') READ( IN_LUN, 901 ) DO I = 1,20 READ( IN_LUN, 903 ) ( AC(I,J), J=1,17 ) ENDDO READ( IN_LUN, 901 ) DO I = 1,20 READ( IN_LUN, 903 ) ( BC(I,J), J=1,17 ) ENDDO 901 FORMAT( / ) 903 FORMAT( 17(E23.14,1x)) 998 CLOSE (IN_LUN) DO I=1,17 WAVE_NUM(18-I) = 48250. + (500.*I) ENDDO END *=============================================================================* FUNCTION chebev(a,b,c,m,x) C------------------------------------------------------------- C C Chebyshev evaluation algorithm C See Numerical recipes p193 C C------------------------------------------------------------- INTEGER M REAL CHEBEV,A,B,X REAL(kind(0.0d0)) :: C(M) INTEGER J REAL D,DD,SV,Y,Y2 IF ((X-A)*(X-B).GT.0.) THEN c WRITE(6,*) 'X NOT IN RANGE IN CHEBEV', X CHEBEV = 0.0 RETURN ENDIF D=0. DD=0. Y=(2.*X-A-B)/(B-A) Y2=2.*Y DO 11 J=M,2,-1 SV=D D=Y2*D-DD+C(J) DD=SV 11 CONTINUE CHEBEV=Y*D-DD+0.5*C(1) RETURN END *=============================================================================* SUBROUTINE sjo2(nz,nw,xso2,nj,sq,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Update the weighting function (cross section x quantum yield) for O2 =* *= photolysis. The strong spectral variations in the O2 cross sections are =* *= parameterized into a few bands for Lyman-alpha (121.4-121.9 nm, one band)=* *= and Schumann-Runge (174.4-205.8, 17 bands) regions. The parameterizations=* *= depend on the overhead O2 column, and therefore on altitude and solar =* *= zenith angle, so they need to be updated at each time/zenith step. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= XSO2 - REAL, molecular absorption cross section in SR bands at (I)=* *= each specified altitude and wavelength. Includes Herzberg =* *= continuum. =* *= NJ - INTEGER, index of O2 photolysis in array SQ (I)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction, at each wavelength and each altitude level =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * calling parameters INTEGER nz, nw, nj REAL xso2(kz,kw) REAL sq(kj,kz,kw) * local INTEGER iw, iz *______________________________________________________________________________ * O2 + hv -> O + O * quantum yield assumed to be unity * assign cross section values at all wavelengths and at all altitudes * qy = 1. DO iw = 1, nw-1 DO iz = 1, nz sq(nj,iz,iw) = xso2(iz,iw) ENDDO ENDDO *______________________________________________________________________________ RETURN END CCC FILE numer.f * This file contains the following subroutines, related to interpolations * of input data, addition of points to arrays, and zeroing of arrays: * inter1 * inter2 * inter3 * inter4 * addpnt * zero1 * zero2 *=============================================================================* SUBROUTINE inter1(ng,xg,yg, n,x,y) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Map input data given on single, discrete points, onto a discrete target =* *= grid. =* *= The original input data are given on single, discrete points of an =* *= arbitrary grid and are being linearly interpolated onto a specified =* *= discrete target grid. A typical example would be the re-gridding of a =* *= given data set for the vertical temperature profile to match the speci- =* *= fied altitude grid. =* *= Some caution should be used near the end points of the grids. If the =* *= input data set does not span the range of the target grid, the remaining =* *= points will be set to zero, as extrapolation is not permitted. =* *= If the input data does not encompass the target grid, use ADDPNT to =* *= expand the input array. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NG - INTEGER, number of points in the target grid (I)=* *= XG - REAL, target grid (e.g. altitude grid) (I)=* *= YG - REAL, y-data re-gridded onto XG (O)=* *= N - INTEGER, number of points in the input data set (I)=* *= X - REAL, grid on which input data are defined (I)=* *= Y - REAL, input y-data (I)=* *-----------------------------------------------------------------------------* IMPLICIT NONE * input: INTEGER n, ng REAL xg(ng) REAL x(n), y(n) * output: REAL yg(ng) * local: REAL slope INTEGER jsave, i, j *_______________________________________________________________________ jsave = 1 DO 20, i = 1, ng yg(i) = 0. j = jsave 10 CONTINUE IF ((x(j) .GT. xg(i)) .OR. (xg(i) .GE. x(j+1))) THEN j = j+1 IF (j .LE. n-1) GOTO 10 * ---- end of loop 10 ---- ELSE slope = (y(j+1)-y(j)) / (x(j+1)-x(j)) yg(i) = y(j) + slope * (xg(i) - x(j)) jsave = j ENDIF 20 CONTINUE *_______________________________________________________________________ RETURN END *=============================================================================* SUBROUTINE inter2(ng,xg,yg,n,x,y,ierr) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Map input data given on single, discrete points onto a set of target =* *= bins. =* *= The original input data are given on single, discrete points of an =* *= arbitrary grid and are being linearly interpolated onto a specified set =* *= of target bins. In general, this is the case for most of the weighting =* *= functions (action spectra, molecular cross section, and quantum yield =* *= data), which have to be matched onto the specified wavelength intervals. =* *= The average value in each target bin is found by averaging the trapezoi- =* *= dal area underneath the input data curve (constructed by linearly connec-=* *= ting the discrete input values). =* *= Some caution should be used near the endpoints of the grids. If the =* *= input data set does not span the range of the target grid, an error =* *= message is printed and the execution is stopped, as extrapolation of the =* *= data is not permitted. =* *= If the input data does not encompass the target grid, use ADDPNT to =* *= expand the input array. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NG - INTEGER, number of bins + 1 in the target grid (I)=* *= XG - REAL, target grid (e.g., wavelength grid); bin i is defined (I)=* *= as [XG(i),XG(i+1)] (i = 1..NG-1) =* *= YG - REAL, y-data re-gridded onto XG, YG(i) specifies the value for (O)=* *= bin i (i = 1..NG-1) =* *= N - INTEGER, number of points in input grid (I)=* *= X - REAL, grid on which input data are defined (I)=* *= Y - REAL, input y-data (I)=* *-----------------------------------------------------------------------------* IMPLICIT NONE * input: INTEGER ng, n REAL x(n), y(n), xg(ng) * output: REAL yg(ng) * local: REAL area, xgl, xgu REAL darea, slope REAL a1, a2, b1, b2 INTEGER ngintv INTEGER i, k, jstart INTEGER ierr *_______________________________________________________________________ ierr = 0 * test for correct ordering of data, by increasing value of x DO 10, i = 2, n IF (x(i) .LE. x(i-1)) THEN ierr = 1 WRITE(*,*)'data not sorted' RETURN ENDIF 10 CONTINUE DO i = 2, ng IF (xg(i) .LE. xg(i-1)) THEN ierr = 2 WRITE(0,*) '>>> ERROR (inter2) <<< xg-grid not sorted!' RETURN ENDIF ENDDO * check for xg-values outside the x-range IF ( (x(1) .GT. xg(1)) .OR. (x(n) .LT. xg(ng)) ) THEN WRITE(0,*) '>>> ERROR (inter2) <<< Data do not span '// > 'grid. ' WRITE(0,*) ' Use ADDPNT to '// > 'expand data and re-run.' STOP ENDIF * find the integral of each grid interval and use this to * calculate the average y value for the interval * xgl and xgu are the lower and upper limits of the grid interval jstart = 1 ngintv = ng - 1 DO 50, i = 1,ngintv * initalize: area = 0.0 xgl = xg(i) xgu = xg(i+1) * discard data before the first grid interval and after the * last grid interval * for internal grid intervals, start calculating area by interpolating * between the last point which lies in the previous interval and the * first point inside the current interval k = jstart IF (k .LE. n-1) THEN * if both points are before the first grid, go to the next point 30 CONTINUE IF (x(k+1) .LE. xgl) THEN jstart = k - 1 k = k+1 IF (k .LE. n-1) GO TO 30 ENDIF * if the last point is beyond the end of the grid, complete and go to the next * grid 40 CONTINUE IF ((k .LE. n-1) .AND. (x(k) .LT. xgu)) THEN jstart = k-1 * compute x-coordinates of increment a1 = MAX(x(k),xgl) a2 = MIN(x(k+1),xgu) * if points coincide, contribution is zero IF (x(k+1).EQ.x(k)) THEN darea = 0.e0 ELSE slope = (y(k+1) - y(k))/(x(k+1) - x(k)) b1 = y(k) + slope*(a1 - x(k)) b2 = y(k) + slope*(a2 - x(k)) darea = (a2 - a1)*(b2 + b1)/2. ENDIF * find the area under the trapezoid from a1 to a2 area = area + darea * go to next point k = k+1 GO TO 40 ENDIF ENDIF * calculate the average y after summing the areas in the interval yg(i) = area/(xgu - xgl) 50 CONTINUE *_______________________________________________________________________ RETURN END *=============================================================================* SUBROUTINE inter3(ng,xg,yg, n,x,y, FoldIn) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Map input data given on a set of bins onto a different set of target =* *= bins. =* *= The input data are given on a set of bins (representing the integral =* *= of the input quantity over the range of each bin) and are being matched =* *= onto another set of bins (target grid). A typical example would be an =* *= input data set spcifying the extra-terrestrial flux on wavelength inter- =* *= vals, that has to be matched onto the working wavelength grid. =* *= The resulting area in a given bin of the target grid is calculated by =* *= simply adding all fractional areas of the input data that cover that =* *= particular target bin. =* *= Some caution should be used near the endpoints of the grids. If the =* *= input data do not span the full range of the target grid, the area in =* *= the "missing" bins will be assumed to be zero. If the input data extend =* *= beyond the upper limit of the target grid, the user has the option to =* *= integrate the "overhang" data and fold the remaining area back into the =* *= last target bin. Using this option is recommended when re-gridding =* *= vertical profiles that directly affect the total optical depth of the =* *= model atmosphere. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NG - INTEGER, number of bins + 1 in the target grid (I)=* *= XG - REAL, target grid (e.g. working wavelength grid); bin i (I)=* *= is defined as [XG(i),XG(i+1)] (i = 1..NG-1) =* *= YG - REAL, y-data re-gridded onto XG; YG(i) specifies the (O)=* *= y-value for bin i (i = 1..NG-1) =* *= N - INTEGER, number of bins + 1 in the input grid (I)=* *= X - REAL, input grid (e.g. data wavelength grid); bin i is (I)=* *= defined as [X(i),X(i+1)] (i = 1..N-1) =* *= Y - REAL, input y-data on grid X; Y(i) specifies the (I)=* *= y-value for bin i (i = 1..N-1) =* *= FoldIn - Switch for folding option of "overhang" data (I)=* *= FoldIn = 0 -> No folding of "overhang" data =* *= FoldIn = 1 -> Integerate "overhang" data and fold back into =* *= last target bin =* *-----------------------------------------------------------------------------* IMPLICIT NONE * input: INTEGER n, ng REAL xg(ng) REAL x(n), y(n) INTEGER FoldIn * output: REAL yg(ng) * local: REAL a1, a2, sum REAL tail INTEGER jstart, i, j, k *_______________________________________________________________________ * check whether flag given is legal IF ((FoldIn .NE. 0) .AND. (FoldIn .NE. 1)) THEN WRITE(0,*) '>>> ERROR (inter3) <<< Value for FOLDIN invalid. ' WRITE(0,*) ' Must be 0 or 1' STOP ENDIF * do interpolation jstart = 1 DO 30, i = 1, ng - 1 yg(i) = 0. sum = 0. j = jstart IF (j .LE. n-1) THEN 20 CONTINUE IF (x(j+1) .LT. xg(i)) THEN jstart = j j = j+1 IF (j .LE. n-1) GO TO 20 ENDIF 25 CONTINUE IF ((x(j) .LE. xg(i+1)) .AND. (j .LE. n-1)) THEN a1 = AMAX1(x(j),xg(i)) a2 = AMIN1(x(j+1),xg(i+1)) sum = sum + y(j) * (a2-a1)/(x(j+1)-x(j)) j = j+1 GO TO 25 ENDIF yg(i) = sum ENDIF 30 CONTINUE * if wanted, integrate data "overhang" and fold back into last bin IF (FoldIn .EQ. 1) THEN j = j-1 a1 = xg(ng) ! upper limit of last interpolated bin a2 = x(j+1) ! upper limit of last input bin considered * do folding only if grids don't match up and there is more input IF ((a2 .GT. a1) .OR. (j+1 .LT. n)) THEN tail = y(j) * (a2-a1)/(x(j+1)-x(j)) DO k = j+1, n-1 tail = tail + y(k) * (x(k+1)-x(k)) ENDDO yg(ng-1) = yg(ng-1) + tail ENDIF ENDIF *_______________________________________________________________________ RETURN END *=============================================================================* SUBROUTINE inter4(ng,xg,yg, n,x,y, FoldIn) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Map input data given on a set of bins onto a different set of target =* *= bins. =* *= The input data are given on a set of bins (representing the integral =* *= of the input quantity over the range of each bin) and are being matched =* *= onto another set of bins (target grid). A typical example would be an =* *= input data set spcifying the extra-terrestrial flux on wavelength inter- =* *= vals, that has to be matched onto the working wavelength grid. =* *= The resulting area in a given bin of the target grid is calculated by =* *= simply adding all fractional areas of the input data that cover that =* *= particular target bin. =* *= Some caution should be used near the endpoints of the grids. If the =* *= input data do not span the full range of the target grid, the area in =* *= the "missing" bins will be assumed to be zero. If the input data extend =* *= beyond the upper limit of the target grid, the user has the option to =* *= integrate the "overhang" data and fold the remaining area back into the =* *= last target bin. Using this option is recommended when re-gridding =* *= vertical profiles that directly affect the total optical depth of the =* *= model atmosphere. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NG - INTEGER, number of bins + 1 in the target grid (I)=* *= XG - REAL, target grid (e.g. working wavelength grid); bin i (I)=* *= is defined as [XG(i),XG(i+1)] (i = 1..NG-1) =* *= YG - REAL, y-data re-gridded onto XG; YG(i) specifies the (O)=* *= y-value for bin i (i = 1..NG-1) =* *= N - INTEGER, number of bins + 1 in the input grid (I)=* *= X - REAL, input grid (e.g. data wavelength grid); bin i is (I)=* *= defined as [X(i),X(i+1)] (i = 1..N-1) =* *= Y - REAL, input y-data on grid X; Y(i) specifies the (I)=* *= y-value for bin i (i = 1..N-1) =* *= FoldIn - Switch for folding option of "overhang" data (I)=* *= FoldIn = 0 -> No folding of "overhang" data =* *= FoldIn = 1 -> Integerate "overhang" data and fold back into =* *= last target bin =* *-----------------------------------------------------------------------------* IMPLICIT NONE * input: INTEGER n, ng REAL xg(ng) REAL x(n), y(n) INTEGER FoldIn * output: REAL yg(ng) * local: REAL a1, a2, sum REAL tail INTEGER jstart, i, j, k *_______________________________________________________________________ * check whether flag given is legal IF ((FoldIn .NE. 0) .AND. (FoldIn .NE. 1)) THEN WRITE(0,*) '>>> ERROR (inter3) <<< Value for FOLDIN invalid. ' WRITE(0,*) ' Must be 0 or 1' STOP ENDIF * do interpolation jstart = 1 DO 30, i = 1, ng - 1 yg(i) = 0. sum = 0. j = jstart IF (j .LE. n-1) THEN 20 CONTINUE IF (x(j+1) .LT. xg(i)) THEN jstart = j j = j+1 IF (j .LE. n-1) GO TO 20 ENDIF 25 CONTINUE IF ((x(j) .LE. xg(i+1)) .AND. (j .LE. n-1)) THEN a1 = AMAX1(x(j),xg(i)) a2 = AMIN1(x(j+1),xg(i+1)) sum = sum + y(j) * (a2-a1) j = j+1 GO TO 25 ENDIF yg(i) = sum /(xg(i+1)-xg(i)) ENDIF 30 CONTINUE * if wanted, integrate data "overhang" and fold back into last bin IF (FoldIn .EQ. 1) THEN j = j-1 a1 = xg(ng) ! upper limit of last interpolated bin a2 = x(j+1) ! upper limit of last input bin considered * do folding only if grids don't match up and there is more input IF ((a2 .GT. a1) .OR. (j+1 .LT. n)) THEN tail = y(j) * (a2-a1)/(x(j+1)-x(j)) DO k = j+1, n-1 tail = tail + y(k) * (x(k+1)-x(k)) ENDDO yg(ng-1) = yg(ng-1) + tail ENDIF ENDIF *_______________________________________________________________________ RETURN END *=============================================================================* SUBROUTINE addpnt ( x, y, ld, n, xnew, ynew ) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Add a point <xnew,ynew> to a set of data pairs <x,y>. x must be in =* *= ascending order =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= X - REAL vector of length LD, x-coordinates (IO)=* *= Y - REAL vector of length LD, y-values (IO)=* *= LD - INTEGER, dimension of X, Y exactly as declared in the calling (I)=* *= program =* *= N - INTEGER, number of elements in X, Y. On entry, it must be: (IO)=* *= N < LD. On exit, N is incremented by 1. =* *= XNEW - REAL, x-coordinate at which point is to be added (I)=* *= YNEW - REAL, y-value of point to be added (I)=* *-----------------------------------------------------------------------------* IMPLICIT NONE * calling parameters INTEGER ld, n REAL x(ld), y(ld) REAL xnew, ynew * local variables INTEGER insert INTEGER i *----------------------------------------------------------------------- * check n<ld to make sure x will hold another point IF (n .GE. ld) THEN WRITE(0,*) '>>> ERROR (ADDPNT) <<< Cannot expand array ' WRITE(0,*) ' All elements used.' STOP ENDIF insert = 1 i = 2 * check, whether x is already sorted. * also, use this loop to find the point at which xnew needs to be inserted * into vector x, if x is sorted. 10 CONTINUE IF (i .LT. n) THEN IF (x(i) .LT. x(i-1)) THEN WRITE(0,*) '>>> ERROR (ADDPNT) <<< x-data must be '// > 'in ascending order!' STOP ELSE IF (xnew .GT. x(i)) insert = i + 1 ENDIF i = i+1 GOTO 10 ENDIF * if <xnew,ynew> needs to be appended at the end, just do so, * otherwise, insert <xnew,ynew> at position INSERT IF ( xnew .GT. x(n) ) THEN x(n+1) = xnew y(n+1) = ynew ELSE * shift all existing points one index up DO i = n, insert, -1 x(i+1) = x(i) y(i+1) = y(i) ENDDO * insert new point x(insert) = xnew y(insert) = ynew ENDIF * increase total number of elements in x, y n = n+1 END *=============================================================================* SUBROUTINE zero1(x,m) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Initialize all elements of a floating point vector with zero. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= X - REAL, vector to be initialized (O)=* *= M - INTEGER, number of elements in X (I)=* *-----------------------------------------------------------------------------* IMPLICIT NONE INTEGER i, m REAL x(m) DO 1 i = 1, m x(i) = 0. 1 CONTINUE RETURN END *=============================================================================* SUBROUTINE zero2(x,m,n) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Initialize all elements of a 2D floating point array with zero. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= X - REAL, array to be initialized (O)=* *= M - INTEGER, number of elements along the first dimension of X, (I)=* *= exactly as specified in the calling program =* *= N - INTEGER, number of elements along the second dimension of X, (I)=* *= exactly as specified in the calling program =* *-----------------------------------------------------------------------------* IMPLICIT none * m,n : dimensions of x, exactly as specified in the calling program INTEGER i, j, m, n REAL x(m,n) DO 1 j = 1, n DO 2 i = 1, m x(i,j) = 0. 2 CONTINUE 1 CONTINUE RETURN END CCC FILE odo3.f *=============================================================================* SUBROUTINE odo3(nz,z,nw,wl,o3xs,c, dto3,kout) *-----------------------------------------------------------------------------* *= NAME: Optical Depths of O3 *= PURPOSE: =* *= Compute ozone optical depths as a function of altitude and wavelength +* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NZ - INTEGER, number of specified altitude levels in the working (I)=* *= grid =* *= Z - REAL, specified altitude working grid (km) (I)=* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= O3XS - REAL, molecular absoprtion cross section (cm^2) of O3 at (I)=* *= each specified wavelength and altitude =* *= C - REAL, ozone vertical column increments, molec cm-2, for each (I)=* *= layer =* *= DTO3 - REAL, optical depth due to ozone absorption at each (O)=* *= specified altitude at each specified wavelength =* *-----------------------------------------------------------------------------* IMPLICIT NONE c c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) ******** * input: ******** * grids: INTEGER nw INTEGER nz REAL wl(kw) REAL z(kz) * ozone absorption cross section, functions of wavelength and altitude REAL o3xs(kz,kw) * ozone vertical column increments REAL c(kz) ******** * output: ******** REAL dto3(kz,kw) ******** * internal: ******** INTEGER iw, iz *_______________________________________________________________________ * calculate ozone optical depth for each layer, with temperature * correction. Output, dto3(kz,kw) DO 20, iw = 1, nw-1 DO 10, iz = 1, nz - 1 dto3(iz,iw) = c(iz) * o3xs(iz,iw) 10 CONTINUE 20 CONTINUE *_______________________________________________________________________ RETURN END CCC FILE odrl.f *=============================================================================* SUBROUTINE odrl(nz,z,nw,wl, c, $ dtrl,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Compute Rayleigh optical depths as a function of altitude and wavelength =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NZ - INTEGER, number of specified altitude levels in the working (I)=* *= grid =* *= Z - REAL, specified altitude working grid (km) (I)=* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= C - REAL, number of air molecules per cm^2 at each specified (O)=* *= altitude layer =* *= DTRL - REAL, Rayleigh optical depth at each specified altitude (O)=* *= and each specified wavelength =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input: INTEGER nw, nz REAL wl(kw), z(kz) REAL c(kz) * output: * Rayleigh optical depths REAL dtrl(kz,kw) * other: REAL srayl, wc, wmicrn, xx INTEGER iz, iw *_______________________________________________________________________ * compute Rayleigh cross sections and depths: DO 10, iw = 1, nw - 1 wc = (wl(iw) + wl(iw+1))/2. * Rayleigh scattering cross section from WMO 1985 (originally from * Nicolet, M., On the molecular scattering in the terrestrial atmosphere: * An empirical formula for its calculation in the homoshpere, Planet. * Space Sci., 32, 1467-1468, 1984. wmicrn = wc/1.E3 IF( wmicrn .LE. 0.55) THEN xx = 3.6772 + 0.389*wmicrn + 0.09426/wmicrn ELSE xx = 4. + 0.04 ENDIF srayl = 4.02e-28/(wmicrn)**xx * alternate (older) expression from * Frohlich and Shaw, Appl.Opt. v.11, p.1773 (1980). C xx = 3.916 + 0.074*wmicrn + 0.050/wmicrn C srayl(iw) = 3.90e-28/(wmicrn)**xx DO 20, iz = 1, nz - 1 dtrl(iz,iw) = c(iz)*srayl 20 CONTINUE 10 CONTINUE *_______________________________________________________________________ RETURN END CCC FILE orbit.f * This file contains the following subroutines, related to the orbit and * rotation of the Earth: * calend * sunae *=============================================================================* c SUBROUTINE calend(iyear, imonth, iday, c $ jday, nday, oky, okm, okd) c c*-----------------------------------------------------------------------------* c*= calculates julian day corresponding to specified year, month, day =* c*= also checks validity of date =* c*-----------------------------------------------------------------------------* c c IMPLICIT NONE c c* input: c c INTEGER iyear, imonth, iday c c* output: c c INTEGER jday, nday c LOGICAL oky, okm, okd c c* internal c c INTEGER mday, month, imn(12) c DATA imn/31,28,31,30,31,30,31,31,30,31,30,31/ c c oky = .TRUE. c okm = .TRUE. c okd = .TRUE. c c IF(iyear .LT. 1950 .OR. iyear .GT. 2050) THEN c WRITE(*,*) 'Year must be between 1950 and 2050)' c oky = .FALSE. c ENDIF c c IF(imonth .LT. 1 .OR. imonth .GT. 12) THEN c WRITE(*,*) 'Month must be between 1 and 12' c okm = .FALSE. c ENDIF c c IF ( MOD(iyear,4) .EQ. 0) THEN c imn(2) = 29 c ELSE c imn(2) = 28 c ENDIF c c IF (iday. GT. imn(imonth)) THEN c WRITE(*,*) 'Day in date exceeds days in month' c WRITE(*,*) 'month = ', imonth c WRITE(*,*) 'day = ', iday c okd = .FALSE. c ENDIF c c mday = 0 c DO 12, month = 1, imonth-1 c mday = mday + imn(month) c 12 CONTINUE c jday = mday + iday c c nday = 365 c IF(imn(2) .EQ. 29) nday = 366 c c RETURN c END c c ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ c c SUBROUTINE SUNAE( YEAR, DAY, HOUR, LAT, LONG, lrefr, c & AZ, EL, SOLDIA, SOLDST ) c c Calculates the local solar azimuth and elevation angles, and c the distance to and angle subtended by the Sun, at a specific c location and time using approximate formulas in The Astronomical c Almanac. Accuracy of angles is 0.01 deg or better (the angular c width of the Sun is about 0.5 deg, so 0.01 deg is more than c sufficient for most applications). c c Unlike many GCM (and other) sun angle routines, this c one gives slightly different sun angles depending on c the year. The difference is usually down in the 4th c significant digit but can slowly creep up to the 3rd c significant digit after several decades to a century. c c A refraction correction appropriate for the "US Standard c Atmosphere" is added, so that the returned sun position is c the APPARENT one. The correction is below 0.1 deg for solar c elevations above 9 deg. To remove it, comment out the code c block where variable REFRAC is set, and replace it with c REFRAC = 0.0. c c References: c c Michalsky, J., 1988: The Astronomical Almanac's algorithm for c approximate solar position (1950-2050), Solar Energy 40, c 227-235 (but the version of this program in the Appendix c contains errors and should not be used) c c The Astronomical Almanac, U.S. Gov't Printing Office, Washington, c D.C. (published every year): the formulas used from the 1995 c version are as follows: c p. A12: approximation to sunrise/set times c p. B61: solar elevation ("altitude") and azimuth c p. B62: refraction correction c p. C24: mean longitude, mean anomaly, ecliptic longitude, c obliquity of ecliptic, right ascension, declination, c Earth-Sun distance, angular diameter of Sun c p. L2: Greenwich mean sidereal time (ignoring T^2, T^3 terms) c c c Authors: Dr. Joe Michalsky (joe@asrc.albany.edu) c Dr. Lee Harrison (lee@asrc.albany.edu) c Atmospheric Sciences Research Center c State University of New York c Albany, New York c c Modified by: Dr. Warren Wiscombe (wiscombe@climate.gsfc.nasa.gov) c NASA Goddard Space Flight Center c Code 913 c Greenbelt, MD 20771 c c c WARNING: Do not use this routine outside the year range c 1950-2050. The approximations become increasingly c worse, and the calculation of Julian date becomes c more involved. c c Input: c c YEAR year (INTEGER; range 1950 to 2050) c c DAY day of year at LAT-LONG location (INTEGER; range 1-366) c c HOUR hour of DAY [GMT or UT] (REAL; range -13.0 to 36.0) c = (local hour) + (time zone number) c + (Daylight Savings Time correction; -1 or 0) C where (local hour) range is 0 to 24, c (time zone number) range is -12 to +12, and c (Daylight Time correction) is -1 if on Daylight Time c (summer half of year), 0 otherwise; c Example: 8:30 am Eastern Daylight Time would be c c HOUR = 8.5 + 5 - 1 = 12.5 c c LAT latitude [degrees] c (REAL; range -90.0 to 90.0; north is positive) c c LONG longitude [degrees] c (REAL; range -180.0 to 180.0; east is positive) c c c Output: c c AZ solar azimuth angle (measured east from north, c 0 to 360 degs) c c EL solar elevation angle [-90 to 90 degs]; c solar zenith angle = 90 - EL c c SOLDIA solar diameter [degs] c c SOLDST distance to sun [Astronomical Units, AU] c (1 AU = mean Earth-sun distance = 1.49597871E+11 m c in IAU 1976 System of Astronomical Constants) c c c Local Variables: c c DEC Declination (radians) c c ECLONG Ecliptic longitude (radians) c c GMST Greenwich mean sidereal time (hours) c c HA Hour angle (radians, -pi to pi) c c JD Modified Julian date (number of days, including c fractions thereof, from Julian year J2000.0); c actual Julian date is JD + 2451545.0 c c LMST Local mean sidereal time (radians) c c MNANOM Mean anomaly (radians, normalized to 0 to 2*pi) c c MNLONG Mean longitude of Sun, corrected for aberration c (deg; normalized to 0-360) c c OBLQEC Obliquity of the ecliptic (radians) c c RA Right ascension (radians) c c REFRAC Refraction correction for US Standard Atmosphere (degs) c c -------------------------------------------------------------------- c Uses double precision for safety and because Julian dates can c have a large number of digits in their full form (but in practice c this version seems to work fine in single precision if you only c need about 3 significant digits and aren't doing precise climate c change or solar tracking work). c -------------------------------------------------------------------- c c Why does this routine require time input as Greenwich Mean Time c (GMT; also called Universal Time, UT) rather than "local time"? c Because "local time" (e.g. Eastern Standard Time) can be off by c up to half an hour from the actual local time (called "local mean c solar time"). For society's convenience, "local time" is held c constant across each of 24 time zones (each technically 15 longitude c degrees wide although some are distorted, again for societal c convenience). Local mean solar time varies continuously around a c longitude belt; it is not a step function with 24 steps. c Thus it is far simpler to calculate local mean solar time from GMT, c by adding 4 min for each degree of longitude the location is c east of the Greenwich meridian or subtracting 4 min for each degree c west of it. c c -------------------------------------------------------------------- c c TIME c c The measurement of time has become a complicated topic. A few c basic facts are: c c (1) The Gregorian calendar was introduced in 1582 to replace c Julian calendar; in it, every year divisible by four is a leap c year just as in the Julian calendar except for centurial years c which must be exactly divisible by 400 to be leap years. Thus c 2000 is a leap year, but not 1900 or 2100. c c (2) The Julian day begins at Greenwich noon whereas the calendar c day begins at the preceding midnight; and Julian years begin on c "Jan 0" which is really Greenwich noon on Dec 31. True Julian c dates are a continous count of day numbers beginning with JD 0 on c 1 Jan 4713 B.C. The term "Julian date" is widely misused and few c people understand it; it is best avoided unless you want to study c the Astronomical Almanac and learn to use it correctly. c c (3) Universal Time (UT), the basis of civil timekeeping, is c defined by a formula relating UT to GMST (Greenwich mean sidereal c time). UTC (Coordinated Universal Time) is the time scale c distributed by most broadcast time services. UT, UTC, and other c related time measures are within a few sec of each other and are c frequently used interchangeably. c c (4) Beginning in 1984, the "standard epoch" of the astronomical c coordinate system is Jan 1, 2000, 12 hr TDB (Julian date c 2,451,545.0, denoted J2000.0). The fact that this routine uses c 1949 as a point of reference is merely for numerical convenience. c -------------------------------------------------------------------- c c .. Scalar Arguments .. c c LOGICAL lrefr c c c INTEGER YEAR, DAY c REAL AZ, EL, HOUR, LAT, LONG, SOLDIA, SOLDST c .. c .. Local Scalars .. c c LOGICAL PASS1 c INTEGER DELTA, LEAP c REAL DEC, DEN, ECLONG, GMST, HA, JD, LMST, c & MNANOM, MNLONG, NUM, OBLQEC, PI, RA, c & RPD, REFRAC, TIME, TWOPI c .. c .. Intrinsic Functions .. c c INTRINSIC AINT, ASIN, ATAN, COS, MOD, SIN, TAN c .. c .. Data statements .. c c SAVE PASS1, PI, TWOPI, RPD c DATA PASS1 /.True./ c .. c c IF( YEAR.LT.1950 .OR. YEAR.GT.2050 ) c & STOP 'SUNAE--bad input variable YEAR' c IF( DAY.LT.1 .OR. DAY.GT.366 ) c & STOP 'SUNAE--bad input variable DAY' c IF( HOUR.LT.-13.0 .OR. HOUR.GT.36.0 ) c & STOP 'SUNAE--bad input variable HOUR' c IF( LAT.LT.-90.0 .OR. LAT.GT.90.0 ) c & STOP 'SUNAE--bad input variable LAT' c IF( LONG.LT.-180.0 .OR. LONG.GT.180.0 ) c & STOP 'SUNAE--bad input variable LONG' c c IF(PASS1) THEN c PI = 2.*ASIN( 1.0 ) c TWOPI = 2.*PI c RPD = PI / 180. c PASS1 = .False. c ENDIF c c ** current Julian date (actually add 2,400,000 c ** for true JD); LEAP = leap days since 1949; c ** 32916.5 is midnite 0 jan 1949 minus 2.4e6 c c DELTA = YEAR - 1949 c LEAP = DELTA / 4 c JD = 32916.5 + (DELTA*365 + LEAP + DAY) + HOUR / 24. c c ** last yr of century not leap yr unless divisible c ** by 400 (not executed for the allowed YEAR range, c ** but left in so our successors can adapt this for c ** the following 100 years) c c IF( MOD( YEAR, 100 ).EQ.0 .AND. c & MOD( YEAR, 400 ).NE.0 ) JD = JD - 1. c c ** ecliptic coordinates c ** 51545.0 + 2.4e6 = noon 1 jan 2000 c c TIME = JD - 51545.0 c c ** force mean longitude between 0 and 360 degs c c MNLONG = 280.460 + 0.9856474*TIME c MNLONG = MOD( MNLONG, 360.D0 ) c IF( MNLONG.LT.0. ) MNLONG = MNLONG + 360. c c ** mean anomaly in radians between 0 and 2*pi c c MNANOM = 357.528 + 0.9856003*TIME c MNANOM = MOD( MNANOM, 360.D0 ) c IF( MNANOM.LT.0.) MNANOM = MNANOM + 360. c c MNANOM = MNANOM*RPD c c ** ecliptic longitude and obliquity c ** of ecliptic in radians c c ECLONG = MNLONG + 1.915*SIN( MNANOM ) + 0.020*SIN( 2.*MNANOM ) c ECLONG = MOD( ECLONG, 360.D0 ) c IF( ECLONG.LT.0. ) ECLONG = ECLONG + 360. c c OBLQEC = 23.439 - 0.0000004*TIME c ECLONG = ECLONG*RPD c OBLQEC = OBLQEC*RPD c c ** right ascension c c NUM = COS( OBLQEC )*SIN( ECLONG ) c DEN = COS( ECLONG ) c RA = ATAN( NUM / DEN ) c c ** Force right ascension between 0 and 2*pi c c IF( DEN.LT.0.0 ) THEN c RA = RA + PI c ELSE IF( NUM.LT.0.0 ) THEN c RA = RA + TWOPI c END IF c c ** declination c c DEC = ASIN( SIN( OBLQEC )*SIN( ECLONG ) ) c c ** Greenwich mean sidereal time in hours c c GMST = 6.697375 + 0.0657098242*TIME + HOUR c c ** Hour not changed to sidereal time since c ** 'time' includes the fractional day c c GMST = MOD( GMST, 24.D0) c IF( GMST.LT.0. ) GMST = GMST + 24. c c ** local mean sidereal time in radians c c LMST = GMST + LONG / 15. c LMST = MOD( LMST, 24.D0 ) c IF( LMST.LT.0. ) LMST = LMST + 24. c c LMST = LMST*15.*RPD c c ** hour angle in radians between -pi and pi c c HA = LMST - RA c c IF( HA.LT.- PI ) HA = HA + TWOPI c IF( HA.GT.PI ) HA = HA - TWOPI c c ** solar azimuth and elevation c c EL = ASIN( SIN( DEC )*SIN( LAT*RPD ) + c & COS( DEC )*COS( LAT*RPD )*COS( HA ) ) c c AZ = ASIN( - COS( DEC )*SIN( HA ) / COS( EL ) ) c c ** Put azimuth between 0 and 2*pi radians c c IF( SIN( DEC ) - SIN( EL )*SIN( LAT*RPD ).GE.0. ) THEN c c IF( SIN(AZ).LT.0.) AZ = AZ + TWOPI c c ELSE c c AZ = PI - AZ c c END IF c c ** Convert elevation and azimuth to degrees c EL = EL / RPD c AZ = AZ / RPD c c ======== Refraction correction for U.S. Standard Atmos. ========== c (assumes elevation in degs) (3.51823=1013.25 mb/288 K) c c IF( EL.GE.19.225 ) THEN c c REFRAC = 0.00452*3.51823 / TAN( EL*RPD ) c c ELSE IF( EL.GT.-0.766 .AND. EL.LT.19.225 ) THEN c c REFRAC = 3.51823 * ( 0.1594 + EL*(0.0196 + 0.00002*EL) ) / c & ( 1. + EL*(0.505 + 0.0845*EL) ) c c ELSE IF( EL.LE.-0.766 ) THEN c c REFRAC = 0.0 c c END IF c c* sm: switch off refraction: c c IF(lrefr) THEN c EL = EL + REFRAC c ENDIF c cc =================================================================== c c ** distance to sun in A.U. & diameter in degs c c SOLDST = 1.00014 - 0.01671*COS(MNANOM) - 0.00014*COS( 2.*MNANOM ) c SOLDIA = 0.5332 / SOLDST c c IF( EL.LT.-90.0 .OR. EL.GT.90.0 ) c & STOP 'SUNAE--output argument EL out of range' c IF( AZ.LT.0.0 .OR. AZ.GT.360.0 ) c & STOP 'SUNAE--output argument AZ out of range' c c RETURN c c END c CCC FILE qys.f * This file contains subroutines used for calculation of quantum yields for * various photoreactions: * qyacet - q.y. for acetone, based on Blitz et al. (2004) ******************************************************************************** SUBROUTINE qyacet(w, T, M, fco, fac) * Compute acetone quantum yields according to the parameterization of: * Blitz, M. A., D. E. Heard, M. J. Pilling, S. R. Arnold, and M. P. Chipperfield * (2004), Pressure and temperature-dependent quantum yields for the * photodissociation of acetone between 279 and 327.5 nm, Geophys. * Res. Lett., 31, L06111, doi:10.1029/2003GL018793. IMPLICIT NONE * input: * w = wavelength, nm * T = temperature, K * m = air number density, molec. cm-3 REAL w, T, M * internal: REAL a0, a1, a2, a3, a4 REAL b0, b1, b2, b3, b4 REAL c3 REAL cA0, cA1, cA2, cA3, cA4 real dumexp * output * fco = quantum yield for product CO * fac = quantum yield for product CH3CO (acetyl radical) REAL fco, fac *** set out-of-range values: * use low pressure limits for shorter wavelengths * set to zero beyound 327.5 IF(w .LT. 279.) THEN fco = 0.05 fac = 0.95 RETURN ENDIF IF(w .GT. 327.5 ) THEN fco = 0. fac = 0. RETURN ENDIF *** CO (carbon monoxide) quantum yields: a0 = 0.350 * (T/295.)**(-1.28) b0 = 0.068 * (T/295.)**(-2.65) **SM: prevent exponent overflow in rare cases: dumexp = b0*(w - 248.) if (dumexp .gt. 80.) then cA0 = 5.e34 else cA0 = exp(dumexp) * a0 / (1. - a0) endif fco = 1. / (1. + cA0) *** CH3CO (acetyl radical) quantum yields: IF(w .GE. 279. .AND. w .LT. 302.) THEN a1 = 1.600E-19 * (T/295.)**(-2.38) b1 = 0.55E-3 * (T/295.)**(-3.19) cA1 = a1 * EXP(-b1*((1.e7/w) - 33113.)) fac = (1. - fco) / (1 + cA1 * M) ENDIF IF(w .GE. 302. .AND. w .LT. 327.5) THEN a2 = 1.62E-17 * (T/295.)**(-10.03) b2 = 1.79E-3 * (T/295.)**(-1.364) cA2 = a2 * EXP(-b2*((1.e7/w) - 30488.)) a3 = 26.29 * (T/295.)**(-6.59) b3 = 5.72E-7 * (T/295.)**(-2.93) c3 = 30006 * (T/295.)**(-0.064) ca3 = a3 * EXP(-b3*((1.e7/w) - c3)**2) a4 = 1.67E-15 * (T/295.)**(-7.25) b4 = 2.08E-3 * (T/295.)**(-1.16) cA4 = a4 * EXP(-b4*((1.e7/w) - 30488.)) fac = (1. - fco) * (1. + cA3 + cA4 * M) / $ ((1. + cA3 + cA2 * M)*(1. + cA4 * M)) ENDIF RETURN END ******************************************************************************** * This file contains the following subroutines, related to reading the * extraterrestrial spectral irradiances: * rdetfl * read1 * read2 *=============================================================================* SUBROUTINE rdetfl(nw,wl,f, kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Read and re-grid extra-terrestrial flux data. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= F - REAL, spectral irradiance at the top of the atmosphere at (O)=* *= each specified wavelength =* *-----------------------------------------------------------------------------* *-----------------------------------------------------------------------------* *= This program 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 2 of the license, or (at your =* *= option) any later version. =* *= The TUV package is distributed in the hope that it will be useful, but =* *= WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBI- =* *= LITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public =* *= License for more details. =* *= To obtain a copy of the GNU General Public License, write to: =* *= Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. =* *-----------------------------------------------------------------------------* *= To contact the authors, please mail to: =* *= Sasha Madronich, NCAR/ACD, P.O.Box 3000, Boulder, CO, 80307-3000, USA or =* *= send email to: sasha@ucar.edu =* *-----------------------------------------------------------------------------* IMPLICIT NONE c c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) integer kdata parameter(kdata=900000) * input: (wavelength grid) INTEGER nw REAL wl(kw) INTEGER iw * output: (extra terrestrial solar flux) REAL f(kw) * INTERNAL: * work arrays for input data files: CHARACTER*40 fil REAL x1(kdata) REAL y1(kdata) INTEGER nhead, n, i, ierr REAL dum * data gridded onto wl(kw) grid: REAL yg1(kw) REAL yg2(kw) REAL yg3(kw) REAL yg4(kw) INTEGER msun *_______________________________________________________________________ * select desired extra-terrestrial solar irradiance, using msun: * 1 = extsol.flx: De Luisi, JGR 80, 345-354, 1975 * 280-400 nm, 1 nm steps. * 2 = lowsun3.flx: Lowtran (John Bahr, priv. comm.) * 173.974-500000 nm, ca. 0.1 nm steps in UV-B * 3 = modtran1.flx: Modtran (Gail Anderson, priv. comm.) * 200.55-949.40, 0.05 nm steps * 4 = nicolarv.flx: wvl<300 nm from Nicolet, Plan. Sp. Sci., 29, 951-974, 1981. * wvl>300 nm supplied by Thekaekera, Arvesen Applied Optics 8, * 11, 2215-2232, 1969 (also see Thekaekera, Applied Optics, 13, * 3, 518, 1974) but with corrections recommended by: * Nicolet, Plan. Sp. Sci., 37, 1249-1289, 1989. * 270.0-299.0 nm in 0.5 nm steps * 299.6-340.0 nm in ca. 0.4 nm steps * 340.0-380.0 nm in ca. 0.2 nm steps * 380.0-470.0 nm in ca. 0.1 nm steps * 5 = solstice.flx: From: MX%"ROTTMAN@virgo.hao.ucar.edu" 12-OCT-1994 13:03:01.62 * Original data gave Wavelength in vacuum * (Converted to wavelength in air using Pendorf, 1967, J. Opt. Soc. Am.) * 279.5 to 420 nm, 0.24 nm spectral resolution, approx 0.07 nm steps * 6 = suntoms.flx: (from TOMS CD-ROM). 280-340 nm, 0.05 nm steps. * 7 = neckel.flx: H.Neckel and D.Labs, "The Solar Radiation Between 3300 and 12500 A", * Solar Physics v.90, pp.205-258 (1984). * 1 nm between 330.5 and 529.5 nm * 2 nm between 631.0 and 709.0 nm * 5 nm between 872.5 and 1247.4 nm * Units: must convert to W m-2 nm-1 from photons cm-2 s-1 nm-1 * 8 = atlas3.flx: ATLAS3-SUSIM 13 Nov 94 high resolution (0.15 nm FWHM) * available by ftp from susim.nrl.navy.mil * atlas3_1994_317_a.dat, downloaded 30 Sept 98. * 150-407.95 nm, in 0.05 nm steps * (old version from Dianne Prinz through Jim Slusser) * orig wavelengths in vac, correct here to air. * 9 = solstice.flx: solstice 1991-1996, average * 119.5-420.5 nm in 1 nm steps * 10 = susim_hi.flx: SUSIM SL2 high resolution * 120.5-400.0 in 0.05 nm intervals (0.15 nm resolution) * 11 = wmo85.flx: from WMO 1985 Atmospheric Ozone (report no. 16) * on variable-size bins. Original values are per bin, not * per nm. * 12 = combine susim_hi.flx for .lt. 350 nm, neckel.flx for .gt. 350 nm. * * 13 = combine * for wl(iw) .lt. 150.01 susim_hi.flx * for wl(iw) .ge. 150.01 and wl(iw) .le. 400 atlas3.flx * for wl(iw) .gt. 400 Neckel & Labs * * 14 = combine * for wl(iw) .le. 350 susim_hi.flx * for wl(iw) .gt. 350 Neckel & Labs * * 15 = combine * for wl(iw) .lt. 150.01 susim_hi.flx * for wl(iw) .ge. 150.01 .and. wl(iw) .lt. 200.07 atlas3.flx * for wl(iw) .ge. 200.07 .and. wl(iw) .le. 1000.99 Chance and Kurucz 2010 * for wl(iw) .gt. 1000.99 Neckel & Labs msun = 14 * simple files are read and interpolated here in-line. Reading of * more complex files may be done with longer code in a read#.f subroutine. IF (msun .EQ. 1) THEN fil = 'DATAE1/SUN/extsol.flx' write(kout,*) fil OPEN(NEWUNIT=ilu,FILE=fil,STATUS='old') nhead = 3 n =121 DO i = 1, nhead READ(ilu,*) ENDDO DO i = 1, n READ(ilu,*) x1(i), y1(i) ENDDO CLOSE (ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg1,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, fil STOP ENDIF DO iw = 1, nw-1 f(iw) = yg1(iw) ENDDO ELSEIF (msun .EQ. 2) THEN fil = 'DATAE1/SUN/lowsun3.flx' write(kout,*) fil OPEN(NEWUNIT=ilu,FILE=fil,STATUS='old') nhead = 3 n = 4327 DO i = 1, nhead READ(ilu,*) ENDDO DO i = 1, n READ(ilu,*) x1(i), y1(i) ENDDO CLOSE (ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg1,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, fil STOP ENDIF DO iw = 1, nw-1 f(iw) = yg1(iw) ENDDO ELSEIF (msun .EQ. 3) THEN fil = 'DATAE1/SUN/modtran1.flx' write(kout,*) fil OPEN(NEWUNIT=ilu,FILE=fil,STATUS='old') nhead = 6 n = 14980 DO i = 1, nhead READ(ilu,*) ENDDO DO i = 1, n READ(ilu,*) x1(i), y1(i) ENDDO CLOSE (ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg1,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, fil STOP ENDIF DO iw = 1, nw-1 f(iw) = yg1(iw) ENDDO ELSEIF (msun .EQ. 4) THEN fil = 'DATAE1/SUN/nicolarv.flx' write(kout,*) fil OPEN(NEWUNIT=ilu,FILE=fil,STATUS='old') nhead = 8 n = 1260 DO i = 1, nhead READ(ilu,*) ENDDO DO i = 1, n READ(ilu,*) x1(i), y1(i) ENDDO CLOSE (ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg1,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, fil STOP ENDIF DO iw = 1, nw-1 f(iw) = yg1(iw) ENDDO ELSEIF (msun .EQ. 5) THEN * unofficial - do not use fil = 'DATAE2/SUN/solstice.flx' write(kout,*) fil OPEN(NEWUNIT=ilu,FILE=fil,STATUS='old') nhead = 11 n = 2047 DO i = 1, nhead READ(ilu,*) ENDDO DO i = 1, n READ(ilu,*) x1(i), y1(i) ENDDO CLOSE (ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg1,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, fil STOP ENDIF DO iw = 1, nw-1 f(iw) = yg1(iw) ENDDO ELSEIF (msun .EQ. 6) THEN * unofficial - do not use fil = 'DATAE2/SUN/suntoms.flx' write(kout,*) fil OPEN(NEWUNIT=ilu,FILE=fil,STATUS='old') nhead = 3 n = 1200 DO i = 1, nhead READ(ilu,*) ENDDO DO i = 1, n READ(ilu,*) x1(i), y1(i) y1(i) = y1(i)* 1.e-3 ENDDO CLOSE (ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg1,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, fil STOP ENDIF DO iw = 1, nw-1 f(iw) = yg1(iw) ENDDO ELSEIF (msun .EQ. 7) THEN fil = 'DATAE1/SUN/neckel.flx' write(kout,*) fil OPEN(NEWUNIT=ilu,FILE=fil,STATUS='old') nhead = 11 n = 496 DO i = 1, nhead READ(ilu,*) ENDDO DO i = 1, n READ(ilu,*) dum, y1(i) if (dum .lt. 630.0) x1(i) = dum - 0.5 if (dum .gt. 630.0 .and. dum .lt. 870.0) x1(i) = dum - 1.0 if (dum .gt. 870.0) x1(i) = dum - 2.5 y1(i) = y1(i) * 1.E4 * hc / (dum * 1.E-9) ENDDO CLOSE (ilu) x1(n+1) = x1(n) + 2.5 do i = 1, n y1(i) = y1(i) * (x1(i+1)-x1(i)) enddo call inter3(nw,wl,yg2,n+1,x1,y1,0) do iw = 1, nw-1 yg1(iw) = yg1(iw) / (wl(iw+1)-wl(iw)) enddo DO iw = 1, nw-1 f(iw) = yg1(iw) ENDDO ELSEIF (msun .EQ. 8) THEN nhead = 5 fil = 'DATAE1/SUN/atlas3_1994_317_a.dat' write(kout,*) fil OPEN(NEWUNIT=ilu,FILE=fil,STATUS='old') nhead = 13 n = 5160 DO i = 1, nhead READ(ilu,*) ENDDO DO i = 1, n READ(ilu,*) x1(i), y1(i) y1(i) = y1(i) * 1.E-3 ENDDO CLOSE (ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg1,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, fil STOP ENDIF DO iw = 1, nw-1 f(iw) = yg1(iw) ENDDO ELSEIF (msun .EQ. 9) THEN fil = 'DATAE1/SUN/solstice.flx' write(kout,*) fil OPEN(NEWUNIT=ilu,FILE=fil,STATUS='old') nhead = 2 n = 302 DO i = 1, nhead READ(ilu,*) ENDDO DO i = 1, n READ(ilu,*) x1(i), y1(i) ENDDO CLOSE (ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg1,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, fil STOP ENDIF DO iw = 1, nw-1 f(iw) = yg1(iw) ENDDO ELSEIF (msun .EQ. 10) THEN WRITE(kout,*) 'DATAE1/SUN/susim_hi.flx' CALL read1(nw,wl,yg1,kout) DO iw = 1, nw-1 f(iw) = yg1(iw) ENDDO ELSEIF (msun .EQ. 11) THEN WRITE(kout,*) 'DATAE1/SUN/wmo85.flx' CALL read2(nw,wl,yg1,kout) DO iw = 1, nw-1 f(iw) = yg1(iw) ENDDO ELSEIF (msun .EQ. 12) THEN WRITE(kout,*) 'DATAE1/SUN/susim_hi.flx' CALL read1(nw,wl,yg1,kout) fil = 'DATAE1/SUN/neckel.flx' write(kout,*) fil OPEN(NEWUNIT=ilu,FILE=fil,STATUS='old') nhead = 11 n = 496 DO i = 1, nhead READ(ilu,*) ENDDO DO i = 1, n READ(ilu,*) dum, y1(i) if (dum .lt. 630.0) x1(i) = dum - 0.5 if (dum .gt. 630.0 .and. dum .lt. 870.0) x1(i) = dum - 1.0 if (dum .gt. 870.0) x1(i) = dum - 2.5 y1(i) = y1(i) * 1.E4 * hc / (dum * 1.E-9) ENDDO CLOSE (ilu) x1(n+1) = x1(n) + 2.5 do i = 1, n y1(i) = y1(i) * (x1(i+1)-x1(i)) enddo call inter3(nw,wl,yg2,n+1,x1,y1,0) do iw = 1, nw-1 yg2(iw) = yg2(iw) / (wl(iw+1)-wl(iw)) enddo DO iw = 1, nw-1 IF (wl(iw) .GT. 350.) THEN f(iw) = yg2(iw) ELSE f(iw) = yg1(iw) ENDIF ENDDO ELSEIF (msun .EQ. 13) THEN WRITE(kout,*) 'DATAE1/SUN/susim_hi.flx' CALL read1(nw,wl,yg1,kout) nhead = 5 fil = 'DATAE1/SUN/atlas3_1994_317_a.dat' write(kout,*) fil OPEN(NEWUNIT=ilu,FILE=fil,STATUS='old') n = 5160 DO i = 1, nhead READ(ilu,*) ENDDO DO i = 1, n READ(ilu,*) x1(i), y1(i) y1(i) = y1(i) * 1.E-3 ENDDO CLOSE (ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg2,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, fil STOP ENDIF fil = 'DATAE1/SUN/neckel.flx' write(kout,*) fil OPEN(NEWUNIT=ilu,FILE=fil,STATUS='old') nhead = 11 n = 496 DO i = 1, nhead READ(ilu,*) ENDDO DO i = 1, n READ(ilu,*) dum, y1(i) if (dum .lt. 630.0) x1(i) = dum - 0.5 if (dum .gt. 630.0 .and. dum .lt. 870.0) x1(i) = dum - 1.0 if (dum .gt. 870.0) x1(i) = dum - 2.5 y1(i) = y1(i) * 1.E4 * hc / (dum * 1.E-9) ENDDO CLOSE (ilu) x1(n+1) = x1(n) + 2.5 call inter4(nw,wl,yg3,n+1,x1,y1,0) DO iw = 1, nw-1 IF (wl(iw) .LT. 150.01) THEN f(iw) = yg1(iw) ELSE IF ((wl(iw) .GE. 150.01) .AND. wl(iw) .LE. 400.) THEN f(iw) = yg2(iw) ELSE IF (wl(iw) .GT. 400.) THEN f(iw) = yg3(iw) ENDIF ENDDO ELSEIF (msun .EQ. 14) THEN WRITE(kout,*) 'DATAE1/SUN/susim_hi.flx' CALL read1(nw,wl,yg1,kout) fil = 'DATAE1/SUN/neckel.flx' write(kout,*) fil OPEN(NEWUNIT=ilu,FILE=fil,STATUS='old') nhead = 11 n = 496 DO i = 1, nhead READ(ilu,*) ENDDO DO i = 1, n READ(ilu,*) dum, y1(i) if (dum .lt. 630.0) x1(i) = dum - 0.5 if (dum .gt. 630.0 .and. dum .lt. 870.0) x1(i) = dum - 1.0 if (dum .gt. 870.0) x1(i) = dum - 2.5 y1(i) = y1(i) * 1.E4 * hc / (dum * 1.E-9) ENDDO CLOSE (ilu) x1(n+1) = x1(n) + 2.5 call inter4(nw,wl,yg3,n+1,x1,y1,0) DO iw = 1, nw-1 IF (wl(iw) .LE. 350.) THEN f(iw) = yg1(iw) ELSE f(iw) = yg3(iw) ENDIF ENDDO ELSEIF (msun .EQ. 15) THEN WRITE(kout,*) 'DATAE1/SUN/susim_hi.flx' CALL read1(nw,wl,yg1,kout) nhead = 5 fil = 'DATAE1/SUN/atlas3_1994_317_a.dat' write(kout,*) fil OPEN(NEWUNIT=ilu,FILE=fil,STATUS='old') n = 5160 DO i = 1, nhead READ(ilu,*) ENDDO DO i = 1, n READ(ilu,*) x1(i), y1(i) y1(i) = y1(i) * 1.E-3 ENDDO CLOSE (ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg2,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, fil STOP ENDIF fil = 'DATAE1/SUN/neckel.flx' write(kout,*) fil OPEN(NEWUNIT=ilu,FILE=fil,STATUS='old') nhead = 11 n = 496 DO i = 1, nhead READ(ilu,*) ENDDO DO i = 1, n READ(ilu,*) dum, y1(i) if (dum .lt. 630.0) x1(i) = dum - 0.5 if (dum .gt. 630.0 .and. dum .lt. 870.0) x1(i) = dum - 1.0 if (dum .gt. 870.0) x1(i) = dum - 2.5 y1(i) = y1(i) * 1.E4 * hc / (dum * 1.E-9) ENDDO CLOSE (ilu) x1(n+1) = x1(n) + 2.5 call inter4(nw,wl,yg3,n+1,x1,y1,0) nhead = 8 fil = 'DATAE1/SUN/sao2010.solref.converted' write(kout,*) fil OPEN(NEWUNIT=ilu,FILE=fil,STATUS='old') n = 80099 - nhead DO i = 1, nhead READ(ilu,*) ENDDO DO i = 1, n READ(ilu,*) x1(i), dum, y1(i), dum c y1(i) = y1(i) * 1.E4 * hc / (x1(i) * 1.E-9) ENDDO CLOSE (ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg4,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, fil STOP ENDIF * for wl(iw) .lt. 150.01 susim_hi.flx * for wl(iw) .ge. 150.01 .and. wl(iw) .lt. 200.07 atlas3.flx * for wl(iw) .ge. 200.07 .and. wl(iw) .le. 1000.99 Chance and Kurucz 2010 * for wl(iw) .gt. 1000.99 Neckel & Labs DO iw = 1, nw-1 IF (wl(iw) .LT. 150.01) THEN f(iw) = yg1(iw) ELSE IF ((wl(iw) .GE. 150.01) .AND. wl(iw) .LT. 200.07) THEN f(iw) = yg2(iw) ELSE IF ((wl(iw) .GE. 200.07) .AND. wl(iw) .LT. 1000.99)THEN f(iw) = yg4(iw) ELSE IF (wl(iw) .GT. 1000.99) THEN f(iw) = yg3(iw) ENDIF ENDDO ENDIF RETURN END *=============================================================================* SUBROUTINE read1(nw,wl,f,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Read extra-terrestrial flux data. Re-grid data to match specified =* *= working wavelength grid. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= F - REAL, spectral irradiance at the top of the atmosphere at (O)=* *= each specified wavelength =* *-----------------------------------------------------------------------------* IMPLICIT NONE c c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input: (wavelength grid) INTEGER nw REAL wl(kw) * output: (extra terrestrial solar flux) REAL f(kw) * local: REAL lambda_hi(10000),irrad_hi(10000) REAL lambda INTEGER ierr INTEGER i, j, n CHARACTER*40 FIL *_______________________________________________________________________ ******* SUSIM irradiance *_______________________________________________________________________ * VanHoosier, M. E., J.-D. F. Bartoe, G. E. Brueckner, and * D. K. Prinz, Absolute solar spectral irradiance 120 nm - * 400 nm (Results from the Solar Ultraviolet Spectral Irradiance * Monitor - SUSIM- Experiment on board Spacelab 2), * Astro. Lett. and Communications, 1988, vol. 27, pp. 163-168. * SUSIM SL2 high resolution (0.15nm) Solar Irridance data. * Irradiance values are given in milliwatts/m^2/nanomenters * and are listed at 0.05nm intervals. The wavelength given is * the center wavelength of the 0.15nm triangular bandpass. * Normalized to 1 astronomical unit. * DATA for wavelengths > 350 nm are unreliable * (Van Hoosier, personal communication, 1994). *_______________________________________________________________________ ** high resolution fil = 'DATAE1/SUN/susim_hi.flx' OPEN(NEWUNIT=ilu,FILE=fil,STATUS='old') DO 11, i = 1, 7 READ(ilu,*) 11 CONTINUE DO 12, i = 1, 559 READ(ilu,*)lambda,(irrad_hi(10*(i-1)+j), j=1, 10) 12 CONTINUE CLOSE (ilu) * compute wavelengths, convert from mW to W n = 559*10 DO 13, i = 1, n lambda_hi(i)=120.5 + FLOAT(i-1)*.05 irrad_hi(i) = irrad_hi(i) / 1000. 13 CONTINUE *_______________________________________________________________________ CALL addpnt(lambda_hi,irrad_hi,10000,n, > lambda_hi(1)*(1.-deltax),0.) CALL addpnt(lambda_hi,irrad_hi,10000,n, 0.,0.) CALL addpnt(lambda_hi,irrad_hi,10000,n, > lambda_hi(n)*(1.+deltax),0.) CALL addpnt(lambda_hi,irrad_hi,10000,n, 1.e38,0.) CALL inter2(nw,wl,f,n,lambda_hi,irrad_hi,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, fil STOP ENDIF RETURN END *=============================================================================* SUBROUTINE read2(nw,wl,f,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Read extra-terrestrial flux data. Re-grid data to match specified =* *= working wavelength grid. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= F - REAL, spectral irradiance at the top of the atmosphere at (O)=* *= each specified wavelength =* *-----------------------------------------------------------------------------* IMPLICIT NONE c c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input: (wavelength grid) INTEGER nw REAL wl(kw) REAL yg(kw) * INTEGER iw * output: (extra terrestrial solar flux) REAL f(kw) * local: REAL x1(1000), y1(1000) REAL x2(1000) REAL x3(1000) INTEGER i, n REAL DUM INTEGER IDUM *_______________________________________________________________________ *********WMO 85 irradiance OPEN(NEWUNIT=ilu,FILE='DATAE1/SUN/wmo85.flx',STATUS='old') DO 11, i = 1, 3 READ(ilu,*) 11 CONTINUE n = 158 DO 12, i = 1, n READ(ilu,*) idum, x1(i),x2(i),y1(i), dum, dum, dum x3(i) = 0.5 * (x1(i) + x2(i)) C average value needs to be calculated only if inter2 is C used to interpolate onto wavelength grid (see below) C y1(i) = y1(i) / (x2(i) - x1(i)) 12 CONTINUE CLOSE (ilu) x1(n+1) = x2(n) C inter2: INPUT : average value in each bin C OUTPUT: average value in each bin C inter3: INPUT : total area in each bin C OUTPUT: total area in each bin CALL inter3(nw,wl,yg, n+1,x1,y1,0) C CALL inter2(nw,wl,yg,n,x3,y1,ierr) DO 10, iw = 1, nw-1 * from quanta s-1 cm-2 bin-1 to watts m-2 nm-1 * 1.e4 * ([hc =] 6.62E-34 * 2.998E8)/(wc*1e-9) C the scaling by bin width needs to be done only if C inter3 is used for interpolation yg(iw) = yg(iw) / (wl(iw+1)-wl(iw)) f(iw) = yg(iw) * 1.e4 * (6.62E-34 * 2.998E8) / $ ( 0.5 * (wl(iw+1)+wl(iw)) * 1.e-9) 10 CONTINUE RETURN END CCC FILE rdxs.f * This file contains subroutines related to reading the * absorption cross sections of gases that contribute to atmospheric transmission: * Some of these subroutines are also called from rxn.f when loading photolysis cross sections * for these same gases. It is possible to have different cross sections for * transmission and for photolysis, e.g. for ozone, Bass et al. could be used * for transmission while Molina and Molina could be used for photolysis. * This flexibility can be useful but users should be aware. * For xsections that are temperature dependent, caution should be used in passing the proper * temperature to the data routines. Usually, transmission is for layers, TLAY(NZ-1), while * photolysis is at levels, T(NZ). * The following subroutines are her: * rdo3xs * o3_mol * o3_rei * o3_bas * o3_wmo * o3_jpl * rdo2xs * rdno2xs * no2xs_d * no2xs_jpl94 * no2xs_har * rdso2xs *=============================================================================* SUBROUTINE rdo3xs(mabs, nz,t,nw,wl, xs, kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Read ozone molecular absorption cross section. Re-grid data to match =* *= specified wavelength working grid. Interpolate in temperature as needed =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= MABS - INTEGER, option for splicing different combinations of (I)=* *= absorption cross secttions =* *= NZ - INTEGER, number of altitude levels or layers (I)=* *= T - REAL, temperature of levels or layers (I)=* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid. In vacuum, nm =* *= XS - REAL, molecular absoprtion cross section (cm^2) of O3 at (O)=* *= each specified wavelength (WMO value at 273) =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input: (altitude working grid) INTEGER iw, nw REAL wl(kw) INTEGER iz, nz REAL t(kz) * internal INTEGER mabs REAL tc * output: * ozone absorption cross sections interpolated to * working wavelength grid (iw) * working altitude grid (iz) for temperature of layer or level (specified in call) * Units are cm2 molecule-1 in vacuum REAL xs(kz,kw) * wavelength-interpolated values from different O3 data sources * also values of significant wavelengths, converted to vacuum REAL rei218(kw), rei228(kw), rei243(kw), rei295(kw) REAL v195, v345, v830 REAL wmo203(kw), wmo273(kw) REAL v176, v850 REAL jpl295(kw), jpl218(kw) REAL v186, v825 REAL mol226(kw), mol263(kw), mol298(kw) REAL v185, v240, v350 REAL c0(kw), c1(kw), c2(kw) REAL vb245, vb342 *_______________________________________________________________________ * read data from different sources * rei = Reims group (Malicet et al., Brion et al.) * jpl = JPL 2006 evaluation * wmo = WMO 1985 O3 assessment * mol = Molina and Molina * bas = Bass et al. CALL o3_rei(nw,wl, rei218,rei228,rei243,rei295, $ v195,v345,v830,kout) CALL o3_jpl(nw,wl, jpl218,jpl295, v186,v825,kout) CALL o3_wmo(nw,wl, wmo203,wmo273, v176,v850,kout) CALL o3_mol(nw,wl, mol226,mol263,mol298, v185,v240, $ v350,kout) CALL o3_bas(nw,wl, c0,c1,c2, vb245,vb342,kout) ****** option 1: IF(mabs. EQ. 1) THEN * assign according to wavelength range: * 175.439 - 185.185 1985WMO (203, 273 K) * 185.185 - 195.00 2006JPL_O3 (218, 295 K) * 195.00 - 345.00 Reims group (218, 228, 243, 295 K) * 345.00 - 830.00 Reims group (295 K) * no extrapolations in temperature allowed DO 10 iw = 1, nw-1 DO 20 iz = 1, nz IF(wl(iw) .LT. v185) THEN xs(iz,iw) = wmo203(iw) + $ (wmo273(iw) - wmo203(iw))*(t(iz) - 203.)/(273. - 203.) IF (t(iz) .LE. 203.) xs(iz,iw) = wmo203(iw) IF (t(iz) .GE. 273.) xs(iz,iw) = wmo273(iw) ENDIF IF(wl(iw) .GE. v185 .AND. wl(iw) .LE. v195) THEN xs(iz,iw) = jpl218(iw) + $ (jpl295(iw) - jpl218(iw))*(t(iz) - 218.)/(295. - 218.) IF (t(iz) .LE. 218.) xs(iz,iw) = jpl218(iw) IF (t(iz) .GE. 295.) xs(iz,iw) = jpl295(iw) ENDIF IF(wl(iw) .GE. v195 .AND. wl(iw) .LT. v345) THEN IF (t(iz) .GE. 218. .AND. t(iz) .LT. 228.) THEN xs(iz,iw) = rei218(iw) + $ (t(iz)-218.)*(rei228(iw)-rei218(iw))/(228.-218.) ELSEIF (t(iz) .GE. 228. .AND. t(iz) .LT. 243.) THEN xs(iz,iw) = rei228(iw) + $ (t(iz)-228.)*(rei243(iw)-rei228(iw))/(243.-228.) ELSEIF (t(iz) .GE. 243. .AND. t(iz) .LT. 295.) THEN xs(iz,iw) = rei243(iw) + $ (t(iz)-243.)*(rei295(iw)-rei243(iw))/(295.-243.) ENDIF IF (t(iz) .LT. 218.) xs(iz,iw) = rei218(iw) IF (t(iz) .GE. 295.) xs(iz,iw) = rei295(iw) ENDIF IF(wl(iw) .GE. v345) THEN xs(iz,iw) = rei295(iw) ENDIF 20 CONTINUE 10 CONTINUE ELSEIF(mabs .EQ. 2) THEN * use exclusively JPL-2006 DO iw = 1, nw-1 DO iz = 1, nz xs(iz,iw) = jpl218(iw) + $ (jpl295(iw) - jpl218(iw))*(t(iz) - 218.)/(295. - 218.) IF (t(iz) .LE. 218.) xs(iz,iw) = jpl218(iw) IF (t(iz) .GE. 295.) xs(iz,iw) = jpl295(iw) ENDDO ENDDO ELSEIF(mabs .EQ. 3) THEN * use exclusively Molina and Molina DO iw = 1, nw-1 DO iz = 1, nz IF(wl(iw) .LT. v240) THEN xs(iz,iw) = mol226(iw) + $ (t(iz)-226.)*(mol298(iw)-mol226(iw))/(298.-226.) ELSE IF(t(iz) .LT. 263.) THEN xs(iz,iw) = mol226(iw) + $ (t(iz)-226.)*(mol263(iw)-mol226(iw))/(263.-226.) ELSE xs(iz,iw) = mol263(iw) + $ (t(iz)-263.)*(mol298(iw)-mol263(iw))/(298.-263.) ENDIF ENDIF IF (t(iz) .LE. 226.) xs(iz,iw) = mol226(iw) IF (t(iz) .GE. 298.) xs(iz,iw) = mol298(iw) ENDDO ENDDO ELSEIF(mabs .EQ. 4) THEN * use exclusively Bass et al. * note limited wavelength range 245-342 DO iw = 1, nw-1 DO iz = 1, nz tc = t(iz) - 273.15 xs(iz,iw) = c0(iw) + c1(iw)*tc + c2(iw)*tc*tc ENDDO ENDDO ELSE STOP 'mabs not set in rdxs.f' ENDIF RETURN END *=============================================================================* SUBROUTINE o3_rei(nw,wl, $ rei218,rei228,rei243,rei295, v195,v345,v830,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Read and interpolate the O3 cross section from Reims group =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= REI218 - REAL, cross section (cm^2) for O3 at 218K (O)=* *= REI228 - REAL, cross section (cm^2) for O3 at 218K (O)=* *= REI243 - REAL, cross section (cm^2) for O3 at 218K (O)=* *= REI295 - REAL, cross section (cm^2) for O3 at 218K (O)=* *= V195 - REAL, exact wavelength in vacuum for data breaks (O)=* *= e.g. start, stop, or other change =* *= V345 - REAL, exact wavelength in vacuum for data breaks (O)=* *= V830 - REAL, exact wavelength in vacuum for data breaks (O)=* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw, iw REAL wl(kw) ** internal INTEGER kdata PARAMETER (kdata = 70000) INTEGER n1, n2, n3, n4 REAL x1(kdata), x2(kdata), x3(kdata), x4(kdata) REAL y1(kdata), y2(kdata), y3(kdata), y4(kdata) INTEGER i INTEGER ierr * used for air-to-vacuum wavelength conversion REAL refrac, ri(kdata) EXTERNAL refrac * output: REAL rei218(kw), rei228(kw), rei243(kw), rei295(kw) REAL v195, v345, v830 * data from the Reims group: *= For Hartley and Huggins bands, use temperature-dependent values from =* *= Malicet et al., J. Atmos. Chem. v.21, pp.263-273, 1995. =* *= over 345.01 - 830.00, use values from Brion, room temperature only OPEN(NEWUNIT=ilu,FILE='DATAE1/O3/1995Malicet_O3.txt',STATUS='old') DO i = 1, 2 READ(ilu,*) ENDDO n1 = 15001 n2 = 15001 n3 = 15001 n4 = 15001 DO i = 1, n1 READ(ilu,*) x1(i), y1(i), y2(i), y3(i), y4(i) x2(i) = x1(i) x3(i) = x1(i) x4(i) = x1(i) ENDDO CLOSE (ilu) *= over 345.01 - 830.00, use values from Brion, room temperature only * skip datum at 345.00 because already read in from 1995Malicet OPEN(NEWUNIT=ilu,FILE='DATAE1/O3/1998Brion_295.txt',STATUS='old') DO i = 1, 15 READ(ilu,*) ENDDO DO i = 1, 48515-15 n1 = n1 + 1 READ(ilu,*) x1(n1), y1(n1) ENDDO CLOSE (ilu) DO i = 1, n1 ri(i) = refrac(x1(i), 2.45E19) ENDDO DO i = 1, n1 x1(i) = x1(i) * ri(i) ENDDO CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,rei295,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, 'O3 xsect - Reims 295K' STOP ENDIF DO i = 1, n2 ri(i) = refrac(x2(i), 2.45E19) ENDDO DO i = 1, n2 x2(i) = x2(i) * ri(i) x3(i) = x2(i) x4(i) = x2(i) ENDDO CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1.e+38,0.) CALL inter2(nw,wl,rei243,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, 'O3 xsect - Reims 243K' STOP ENDIF CALL addpnt(x3,y3,kdata,n3,x3(1)*(1.-deltax),0.) CALL addpnt(x3,y3,kdata,n3, 0.,0.) CALL addpnt(x3,y3,kdata,n3,x3(n3)*(1.+deltax),0.) CALL addpnt(x3,y3,kdata,n3, 1.e+38,0.) CALL inter2(nw,wl,rei228,n3,x3,y3,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, 'O3 xsect - Reims 228K' STOP ENDIF CALL addpnt(x4,y4,kdata,n4,x4(1)*(1.-deltax),0.) CALL addpnt(x4,y4,kdata,n4, 0.,0.) CALL addpnt(x4,y4,kdata,n4,x4(n4)*(1.+deltax),0.) CALL addpnt(x4,y4,kdata,n4, 1.e+38,0.) CALL inter2(nw,wl,rei218,n4,x4,y4,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, 'O3 xsect - Reims 218K' STOP ENDIF * wavelength breaks must be converted to vacuum: v195 = 195.00 * refrac(195.00, 2.45E19) v345 = 345.00 * refrac(345.00, 2.45E19) v830 = 830.00 * refrac(830.00, 2.45E19) RETURN END *=============================================================================* SUBROUTINE o3_wmo(nw,wl, wmo203,wmo273, v176,v850,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Read and interpolate the O3 cross section =* *= data from WMO 85 Ozone Assessment =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WMO203 - REAL, cross section (cm^2) for O3 at 203K (O)=* *= WMO273 - REAL, cross section (cm^2) for O3 at 273K (O)=* *= V176 - REAL, exact wavelength in vacuum for data breaks (O)=* *= e.g. start, stop, or other change =* *= V850 - REAL, exact wavelength in vacuum for data breaks (O)=* *-----------------------------------------------------------------------------* IMPLICIT NONE c c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw, iw REAL wl(kw) * internal INTEGER kdata PARAMETER (kdata = 200) INTEGER n1, n2 REAL x1(kdata), x2(kdata) REAL y1(kdata), y2(kdata) INTEGER i, idum REAL a1, a2, dum INTEGER ierr * used for air-to-vacuum wavelength conversion REAL refrac, ri(kdata) EXTERNAL refrac * output REAL wmo203(kw), wmo273(kw) REAL v176, v850 *---------------------------------------------------------- * cross sections from WMO 1985 Ozone Assessment * from 175.439 to 847.500 nm OPEN(NEWUNIT=ilu,FILE='DATAE1/wmo85',STATUS='old') DO i = 1, 3 read(UNIT=ilu,FMT=*) ENDDO n1 = 158 n2 = 158 DO i = 1, n1 READ(UNIT=ilu,FMT=*) idum, a1, a2, dum, dum, dum, y1(i), y2(i) x1(i) = (a1+a2)/2. x2(i) = (a1+a2)/2. ENDDO CLOSE (UNIT=ilu) * convert wavelengths to vacuum DO i = 1, n1 ri(i) = refrac(x1(i), 2.45E19) ENDDO DO i = 1, n1 x1(i) = x1(i) * ri(i) x2(i) = x2(i) * ri(i) ENDDO CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,wmo203,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, 'O3 cross section - WMO - 203K' STOP ENDIF CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1.e+38,0.) CALL inter2(nw,wl,wmo273,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, 'O3 cross section - WMO - 273K' STOP ENDIF * wavelength breaks must be converted to vacuum: a1 = (175.438 + 176.991) / 2. v176 = a1 * refrac(a1,2.45E19) a1 = (847.5 + 852.5) / 2. v850 = a1 * refrac(a1, 2.45E19) RETURN END *=============================================================================* SUBROUTINE o3_jpl(nw,wl, jpl218,jpl295, v186,v825,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Read and interpolate the O3 cross section from JPL 2006 =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= JPL218 - REAL, cross section (cm^2) for O3 at 218K (O)=* *= JPL295 - REAL, cross section (cm^2) for O3 at 295K (O)=* *= V186 - REAL, exact wavelength in vacuum for data breaks (O)=* *= e.g. start, stop, or other change =* *= V825 - REAL, exact wavelength in vacuum for data breaks (O)=* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw, iw REAL wl(kw) * internal INTEGER kdata PARAMETER (kdata = 200) INTEGER n1, n2 REAL x1(kdata), x2(kdata) REAL y1(kdata), y2(kdata) INTEGER i REAL dum INTEGER ierr * used for air-to-vacuum wavelength conversion REAL refrac, ri(kdata) EXTERNAL refrac * output REAL jpl295(kw), jpl218(kw) REAL v186, v825 *********** OPEN(NEWUNIT=ilu,FILE='DATAE1/O3/2006JPL_O3.txt',STATUS='old') DO i = 1, 2 read(ilu,*) ENDDO n1 = 167 n2 = 167 DO i = 1, n1 READ(ilu,*) dum, dum, x1(i), y1(i), y2(i) y1(i) = y1(i) * 1.e-20 y2(i) = y2(i) * 1.e-20 ENDDO CLOSE (ilu) * convert wavelengths to vacuum DO i = 1, n1 ri(i) = refrac(x1(i), 2.45E19) ENDDO DO i = 1, n1 x1(i) = x1(i) * ri(i) x2(i) = x1(i) ENDDO CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,jpl295,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, 'O3 cross section - WMO - 295K' STOP ENDIF CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1.e+38,0.) CALL inter2(nw,wl,jpl218,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, 'O3 cross section - WMO - 218K' STOP ENDIF * wavelength breaks must be converted to vacuum: v186 = 186.051 * refrac(186.051, 2.45E19) v825 = 825. * refrac(825. , 2.45E19) RETURN END *=============================================================================* SUBROUTINE o3_mol(nw,wl, mol226,mol263,mol298, & v185,v240,v350,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Read and interpolate the O3 cross section from Molina and Molina 1986 =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= MOL226 - REAL, cross section (cm^2) for O3 at 226 K (O)=* *= MOL263 - REAL, cross section (cm^2) for O3 at 263 K (O)=* *= MOL298 - REAL, cross section (cm^2) for O3 at 298 K (O)=* *= V185 - REAL, exact wavelength in vacuum for data breaks (O)=* *= e.g. start, stop, or other change =* *= V240 - REAL, exact wavelength in vacuum for data breaks (O)=* *= V350 - REAL, exact wavelength in vacuum for data breaks (O)=* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw, iw REAL wl(kw) * internal INTEGER i INTEGER ierr INTEGER kdata PARAMETER (kdata = 335) INTEGER n1, n2, n3 REAL x1(kdata), x2(kdata), x3(kdata) REAL y1(kdata), y2(kdata), y3(kdata) * used for air-to-vacuum wavelength conversion REAL refrac, ri(kdata) EXTERNAL refrac * output REAL mol226(kw), mol263(kw), mol298(kw) REAL v185, v240, v350 *---------------------------------------------------------- OPEN(NEWUNIT=ilu,FILE='DATAE1/O3/1986Molina.txt',STATUS='old') DO i = 1, 10 READ(ilu,*) ENDDO n1 = 0 n2 = 0 n3 = 0 DO i = 1, 121-10 n1 = n1 + 1 n3 = n3 + 1 READ(ilu,*) x1(n1), y1(n1), y3(n3) x3(n3) = x1(n1) ENDDO DO i = 1, 341-122 n1 = n1 + 1 n2 = n2 + 1 n3 = n3 + 1 READ(ilu,*) x1(n1), y1(n1), y2(n2), y3(n3) x2(n2) = x1(n1) x3(n3) = x1(n1) ENDDO CLOSE (ilu) * convert all wavelengths from air to vacuum DO i = 1, n1 ri(i) = refrac(x1(i), 2.45E19) ENDDO DO i = 1, n1 x1(i) = x1(i) * ri(i) ENDDO DO i = 1, n2 ri(i) = refrac(x2(i), 2.45E19) ENDDO DO i = 1, n2 x2(i) = x2(i) * ri(i) ENDDO DO i = 1, n3 ri(i) = refrac(x3(i), 2.45E19) ENDDO DO i = 1, n3 x3(i) = x3(i) * ri(i) ENDDO * convert wavelength breaks from air to vacuum v185 = 185. * refrac(185. , 2.45E19) v240 = 240.5 * refrac(240.5, 2.45E19) v350 = 350. * refrac(350. , 2.45E19) * interpolate to working grid CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,mol226,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, 'O3 xsect - 226K Molina' STOP ENDIF CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1.e+38,0.) CALL inter2(nw,wl,mol263,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, 'O3 xsect - 263K Molina' STOP ENDIF CALL addpnt(x3,y3,kdata,n3,x3(1)*(1.-deltax),0.) CALL addpnt(x3,y3,kdata,n3, 0.,0.) CALL addpnt(x3,y3,kdata,n3,x3(n3)*(1.+deltax),0.) CALL addpnt(x3,y3,kdata,n3, 1.e+38,0.) CALL inter2(nw,wl,mol298,n3,x3,y3,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, 'O3 xsect - 298K Molina' STOP ENDIF RETURN END *=============================================================================* SUBROUTINE o3_bas(nw,wl, c0,c1,c2, vb245,vb342,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Read and interpolate the O3 cross section from Bass 1985 =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= c0 - REAL, coefficint for polynomial fit to cross section (cm^2) (O)=* *= c1 - REAL, coefficint for polynomial fit to cross section (cm^2) (O)=* *= c2 - REAL, coefficint for polynomial fit to cross section (cm^2) (O)=* *= Vb245 - REAL, exact wavelength in vacuum for data breaks (O)=* *= e.g. start, stop, or other change =* *= Vb342 - REAL, exact wavelength in vacuum for data breaks (O)=* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input: INTEGER nw, iw REAL wl(kw) * internal: INTEGER kdata PARAMETER (kdata = 2000) INTEGER i INTEGER ierr INTEGER n1, n2, n3 REAL x1(kdata), x2(kdata), x3(kdata) REAL y1(kdata), y2(kdata), y3(kdata) * used for air-to-vacuum wavelength conversion REAL refrac, ri(kdata) EXTERNAL refrac * output: REAL c0(kw), c1(kw), c2(kw) REAL vb245, vb342 ******************* OPEN(NEWUNIT=ilu,FILE='DATAE1/O3/1985Bass_O3.txt',STATUS='old') DO i = 1, 8 READ(UNIT=ilu,FMT=*) ENDDO n1 = 1915 n2 = 1915 n3 = 1915 DO i = 1, n1 READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i), y3(i) y1(i) = 1.e-20 * y1(i) y2(i) = 1.e-20 * y2(i) y3(i) = 1.e-20 * y3(i) ENDDO CLOSE (UNIT=ilu) * convert all wavelengths from air to vacuum DO i = 1, n1 ri(i) = refrac(x1(i), 2.45E19) ENDDO DO i = 1, n1 x1(i) = x1(i) * ri(i) x2(i) = x1(i) x3(i) = x1(i) ENDDO * convert wavelength breaks to vacuum vb245 = 245.018 * refrac(245.018, 2.45E19) vb342 = 341.981 * refrac(341.981, 2.45E19) * interpolate to working grid CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,c0,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, 'O3 xsect - c0 Bass' STOP ENDIF CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1.e+38,0.) CALL inter2(nw,wl,c1,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, 'O3 xsect - c1 Bass' STOP ENDIF CALL addpnt(x3,y3,kdata,n3,x3(1)*(1.-deltax),0.) CALL addpnt(x3,y3,kdata,n3, 0.,0.) CALL addpnt(x3,y3,kdata,n3,x3(n3)*(1.+deltax),0.) CALL addpnt(x3,y3,kdata,n3, 1.e+38,0.) CALL inter2(nw,wl,c2,n3,x3,y3,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, 'O3 xsect - c2 Bass' STOP ENDIF RETURN END *=============================================================================* SUBROUTINE rdo2xs(nw,wl,o2xs1,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Compute equivalent O2 cross section, except =* *= the SR bands and the Lyman-alpha line. =* *-----------------------------------------------------------------------------* *= PARAMETERS: *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid *= vertical layer at each specified wavelength =* *= O2XS1 - REAL, O2 molecular absorption cross section =* *= *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * Input INTEGER nw REAL wl(kw) * Output O2 xsect, temporary, will be over-written in Lyman-alpha and * Schumann-Runge wavelength bands. REAL o2xs1(kw) * Internal INTEGER i, n, kdata PARAMETER (kdata = 200) REAL x1(kdata), y1(kdata) REAL x, y INTEGER ierr *----------------------------------------------------- * Read O2 absorption cross section data: * 116.65 to 203.05 nm = from Brasseur and Solomon 1986 * 205 to 240 nm = Yoshino et al. 1988 * Note that subroutine la_srb.f will over-write values in the spectral regions * corresponding to: * - Lyman-alpha (LA: 121.4-121.9 nm, Chabrillat and Kockarts parameterization) * - Schumann-Runge bands (SRB: 174.4-205.8 nm, Koppers parameteriaztion) n = 0 OPEN(NEWUNIT=ilu,FILE='DATAE1/O2/O2_brasseur.abs') DO i = 1, 7 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, 78 READ(UNIT=ilu,FMT=*) x, y IF (x .LE. 204.) THEN n = n + 1 x1(n) = x y1(n) = y ENDIF ENDDO CLOSE(UNIT=ilu) OPEN(NEWUNIT=ilu,FILE='DATAE1/O2/O2_yoshino.abs',STATUS='old') DO i = 1, 8 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, 36 n = n + 1 READ(UNIT=ilu,FMT=*) x, y y1(n) = y*1.E-24 x1(n) = x END DO CLOSE (UNIT=ilu) * Add termination points and interpolate onto the * user grid (set in subroutine gridw): CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),y1(1)) CALL addpnt(x1,y1,kdata,n,0. ,y1(1)) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.E+38,0.) CALL inter2(nw,wl,o2xs1, n,x1,y1, ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, 'O2 -> O + O' STOP ENDIF *------------------------------------------------------ RETURN END *=============================================================================* SUBROUTINE rdno2xs(nz,tlay,nw,wl,no2xs,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Read NO2 molecular absorption cross section. Re-grid data to match =* *= specified wavelength working grid. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= NO2XS - REAL, molecular absoprtion cross section (cm^2) of NO2 at (O)=* *= each specified wavelength =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input: (altitude working grid) INTEGER nz REAL tlay(kz) INTEGER nw REAL wl(kw) INTEGER mabs * output: REAL no2xs(kz,kw) *_______________________________________________________________________ * options for NO2 cross section: * 1 = Davidson et al. (1988), indepedent of T * 2 = JPL 1994 (same as JPL 1997, JPL 2002) * 3 = Harder et al. * 4 = JPL 2006, interpolating between midpoints of bins * 5 = JPL 2006, bin-to-bin interpolation mabs = 4 IF (mabs. EQ. 1) CALL no2xs_d(nz,tlay,nw,wl, no2xs,kout) IF (mabs .EQ. 2) CALL no2xs_jpl94(nz,tlay,nw,wl, no2xs,kout) IF (mabs .EQ. 3) CALL no2xs_har(nz,tlay,nw,wl, no2xs,kout) IF (mabs .EQ. 4) CALL no2xs_jpl06a(nz,tlay,nw,wl, no2xs,kout) IF (mabs .EQ. 5) CALL no2xs_jpl06b(nz,tlay,nw,wl, no2xs,kout) *_______________________________________________________________________ RETURN END *=============================================================================* SUBROUTINE no2xs_d(nz,t,nw,wl, no2xs,kout) IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * read and interpolate NO2 xs from Davidson et al. (1988). * input: INTEGER nz, iz REAL t(nz) INTEGER nw, iw REAL wl(nw) * output: REAL no2xs(kz,kw) * local: INTEGER kdata PARAMETER (kdata=1000) REAL x1(kdata) REAL y1(kdata) REAL yg(kw) REAL dum INTEGER ierr INTEGER i, n, idum CHARACTER*40 fil ************* NO2 absorption cross sections * measurements by: * Davidson, J. A., C. A. Cantrell, A. H. McDaniel, R. E. Shetter, * S. Madronich, and J. G. Calvert, Visible-ultraviolet absorption * cross sections for NO2 as a function of temperature, J. Geophys. * Res., 93, 7105-7112, 1988. * Values at 273K from 263.8 to 648.8 nm in approximately 0.5 nm intervals fil = 'DATAE1/NO2/NO2_ncar_00.abs' OPEN(NEWUNIT=ilu,FILE=fil,STATUS='old') n = 750 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i), dum, dum, idum ENDDO CLOSE(UNIT=ilu) * interpolate to wavelength grid CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, fil STOP ENDIF * assign, same at all altitudes (no temperature effect) DO iz = 1, nz DO iw = 1, nw-1 no2xs(iz,iw) = yg(iw) ENDDO ENDDO *_______________________________________________________________________ RETURN END *=============================================================================* SUBROUTINE no2xs_jpl94(nz,t,nw,wl, no2xs,kout) IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * read and interpolate NO2 xs from JPL 1994 * input: INTEGER nz, iz REAL t(nz) INTEGER nw, iw REAL wl(nw) * output: REAL no2xs(kz,kw) * local: INTEGER kdata PARAMETER (kdata=100) INTEGER i, idum, n, n1 REAL x1(kdata), x2(kdata), x3(kdata) REAL y1(kdata), y2(kdata), y3(kdata) REAL dum REAL yg1(nw), yg2(nw) * cross section data from JPL 94 recommendation * JPL 97 and JPL 2002 recommendations are identical OPEN(NEWUNIT=ilu,FILE='DATAE1/NO2/NO2_jpl94.abs',STATUS='old') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO * read in wavelength bins, cross section at T0 and temperature correction * coefficient a; see input file for details. * data need to be scaled to total area per bin so that they can be used with * inter3 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), x3(i), y1(i), dum, y2(i) y1(i) = (x3(i)-x1(i)) * y1(i)*1.E-20 y2(i) = (x3(i)-x1(i)) * y2(i)*1.E-22 x2(i) = x1(i) ENDDO CLOSE(UNIT=ilu) x1(n+1) = x3(n) x2(n+1) = x3(n) n = n+1 n1 = n CALL inter3(nw,wl,yg1,n,x1,y1,0) CALL inter3(nw,wl,yg2,n1,x2,y2,0) * yg1, yg2 are per nm, so rescale by bin widths DO iw = 1, nw-1 yg1(iw) = yg1(iw)/(wl(iw+1)-wl(iw)) yg2(iw) = yg2(iw)/(wl(iw+1)-wl(iw)) ENDDO DO iw = 1, nw-1 DO iz = 1, nz no2xs(iz,iw) = yg1(iw) + yg2(iw)*(t(iz)-273.15) ENDDO ENDDO RETURN END *=============================================================================* SUBROUTINE no2xs_har(nz,t,nw,wl, no2xs,kout) IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * read and interpolate NO2 xs from Harder et al. * input: INTEGER nz, iz REAL t(nz) INTEGER nw, iw REAL wl(nw) * output: REAL no2xs(kz,kw) * local: INTEGER kdata PARAMETER (kdata=150) INTEGER i, n, idum, ierr REAL x1(kdata), y1(kdata) REAL yg1(kw) *** OPEN(NEWUNIT=ilu,FILE='DATAE1/NO2/NO2_Har.abs',status='old') DO i = 1, 9 READ(UNIT=ilu,FMT=*) ENDDO n = 135 DO i = 1, n READ(UNIT=ilu,FMT=*) idum, y1(i) x1(i) = FLOAT(idum) ENDDO CLOSe(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),y1(1)) CALL addpnt(x1,y1,kdata,n, 0.,y1(1)) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax), 0.) CALL addpnt(x1,y1,kdata,n, 1.e+38, 0.) CALL inter2(nw,wl,yg1,n,x1,y1,ierr) DO iw = 1, nw-1 DO i = 1, nz no2xs(i,iw) = yg1(iw) ENDDO ENDDO RETURN END *=============================================================================* SUBROUTINE no2xs_jpl06a(nz,t,nw,wl, no2xs,kout) * read and interpolate NO2 xs from JPL2006 IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input: INTEGER nz, iz REAL t(nz) INTEGER nw, iw REAL wl(nw) * output: REAL no2xs(kz,kw) * local INTEGER kdata PARAMETER (kdata=80) INTEGER i, n1, n2, ierr REAL x1(kdata), x2(kdata), y1(kdata), y2(kdata) REAL dum1, dum2 REAL yg1(kw), yg2(kw) * NO2 absorption cross section from JPL2006 * with interpolation of bin midpoints OPEN(NEWUNIT=ilu,FILE='DATAE1/NO2/NO2_jpl2006.abs',STATUS='old') DO i = 1, 3 READ(UNIT=ilu,FMT=*) ENDDO n1 = 73 DO i = 1, n1 READ(UNIT=ilu,FMT=*) dum1, dum2, y1(i), y2(i) x1(i) = 0.5 * (dum1 + dum2) x2(i) = x1(i) y1(i) = y1(i)*1.E-20 y2(i) = y2(i)*1.E-20 ENDDO CLOSE(UNIT=ilu) n2 = n1 CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax), 0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38, 0.) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax), 0.) CALL addpnt(x2,y2,kdata,n2, 1.e+38, 0.) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) DO iw = 1, nw-1 DO iz = 1, nz no2xs(iz,iw) = yg1(iw) + $ (yg2(iw)-yg1(iw))*(t(iz)-220.)/74. ENDDO ENDDO RETURN END *=============================================================================* SUBROUTINE no2xs_jpl06b(nz,t,nw,wl, no2xs,kout) * read and interpolate NO2 xs from Harder et al. IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input: INTEGER nz, iz REAL t(nz) INTEGER nw, iw REAL wl(nw) * output: REAL no2xs(kz,kw) * local INTEGER kdata PARAMETER (kdata=100) INTEGER i, n, n1, n2, ierr REAL x1(kdata), x2(kdata), y1(kdata), y2(kdata) REAL x3(kdata), y3(kdata) REAL dum1, dum2 REAL yg1(kw), yg2(kw) OPEN(NEWUNIT=ilu,FILE='DATAE1/NO2/NO2_jpl2006.abs',STATUS='old') DO i = 1, 3 READ(UNIT=ilu,FMT=*) ENDDO n = 81 do i = 1, n read(UNIT=ilu,FMT=*) x1(i), x3(i), y1(i), y2(i) y1(i) = (x3(i)-x1(i)) * y1(i)*1.E-20 y2(i) = (x3(i)-x1(i)) * y2(i)*1.E-20 x2(i) = x1(i) ENDDO CLOSE(UNIT=ilu) x1(n+1) = x3(n) x2(n+1) = x3(n) n = n+1 n1 = n CALL inter3(nw,wl,yg1,n,x1,y1,0) CALL inter3(nw,wl,yg2,n1,x2,y2,0) * yg1, yg2 are per nm, so rescale by bin widths DO iw = 1, nw-1 yg1(iw) = yg1(iw)/(wl(iw+1)-wl(iw)) yg2(iw) = yg2(iw)/(wl(iw+1)-wl(iw)) ENDDO DO iw = 1, nw-1 DO iz = 1, nz no2xs(iz,iw) = yg1(iw) + $ (yg2(iw)-yg1(iw))*(t(iz)-220.)/74. ENDDO ENDDO RETURN END *=============================================================================* SUBROUTINE rdso2xs(nw,wl,so2xs,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Read SO2 molecular absorption cross section. Re-grid data to match =* *= specified wavelength working grid. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= SO2XS - REAL, molecular absoprtion cross section (cm^2) of SO2 at (O)=* *= each specified wavelength =* *-----------------------------------------------------------------------------* *= EDIT HISTORY: =* *= 02/97 Changed offset for grid-end interpolation to relative number =* *= (x * (1 +- deltax) =* *-----------------------------------------------------------------------------* *= This program 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 2 of the license, or (at your =* *= option) any later version. =* *= The TUV package is distributed in the hope that it will be useful, but =* *= WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBI- =* *= LITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public =* *= License for more details. =* *= To obtain a copy of the GNU General Public License, write to: =* *= Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. =* *-----------------------------------------------------------------------------* *= To contact the authors, please mail to: =* *= Sasha Madronich, NCAR/ACD, P.O.Box 3000, Boulder, CO, 80307-3000, USA or =* *= send email to: sasha@ucar.edu =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) INTEGER kdata PARAMETER(kdata=1000) * input: (altitude working grid) INTEGER nw REAL wl(kw) * output: REAL so2xs(kw) * local: REAL x1(kdata) REAL y1(kdata) REAL yg(kw) REAL dum INTEGER ierr INTEGER i, l, n, idum CHARACTER*40 fil *_______________________________________________________________________ ************* absorption cross sections: * SO2 absorption cross sections from J. Quant. Spectrosc. Radiat. Transfer * 37, 165-182, 1987, T. J. McGee and J. Burris Jr. * Angstrom vs. cm2/molecule, value at 221 K fil = 'DATA/McGee87' OPEN(NEWUNIT=ilu,FILE='DATAE1/SO2/SO2xs.all',STATUS='old') DO 11, i = 1,3 read(UNIT=ilu,FMT=*) 11 CONTINUE c n = 681 n = 704 DO 12, i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) x1(i) = x1(i)/10. 12 CONTINUE CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, fil STOP ENDIF DO 13, l = 1, nw-1 so2xs(l) = yg(l) 13 CONTINUE *_______________________________________________________________________ RETURN END *=============================================================================* CCC FILE rtrans.f * This file contains the following subroutines, related to the solution of * the equation of radiative transfer in multiple homogeneous layers. * rtlink * ps2str * tridag * psndo * asymtx * chekin * fluxes * lepoly * pravin * prtinp * prtint * qgausn * setdis * setmtx * soleig * solve0 * surfac * solvec * upbeam * zeroal * zeroit * errmsg * sgbco * sgbfa * sgbsl * sgeco * sgefa * sgesl * saxpy * sscal * sswap * t665d * t665r * and the functions * dref * ratio * wrtbad * wrtdim * tstbad * sasum * sdot * isamax * d1mach * r1mach *=============================================================================* SUBROUTINE rtlink(nstr, nz, $ iw, ag, zen, $ dsdh, nid, $ dtrl, $ dto3, $ dto2, $ dtso2, $ dtno2, $ dtcld, omcld, gcld, $ dtaer, omaer, gaer, $ dtsnw, omsnw, gsnw, $ edir, edn, eup, fdir, fdn, fup, $ kout) IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nstr INTEGER nz, iw REAL ag REAL zen REAL dsdh(0:kz,kz) INTEGER nid(0:kz) REAL dtrl(kz,kw) REAL dto3(kz,kw), dto2(kz,kw), dtso2(kz,kw), dtno2(kz,kw) REAL dtcld(kz,kw), omcld(kz,kw), gcld(kz,kw) REAL dtaer(kz,kw), omaer(kz,kw), gaer(kz,kw) REAL dtsnw(kz,kw), omsnw(kz,kw), gsnw(kz,kw) * output REAL edir(kz), edn(kz), eup(kz) REAL fdir(kz), fdn(kz), fup(kz) * program constants: REAL dr PARAMETER (dr = pi/180.) * local: REAL dt(kz), om(kz), g(kz) REAL dtabs,dtsct,dscld,dsaer,dssnw,dacld,daaer,dasnw INTEGER i, ii * specific two ps2str REAL ediri(kz), edni(kz), eupi(kz) REAL fdiri(kz), fdni(kz), fupi(kz) LOGICAL delta DATA delta /.true./ * specific to psndo: REAL pmcld, pmray, pmaer, pmsnw REAL om1 INTEGER istr, iu INTEGER MAXCLY, MAXULV, MAXUMU, MAXCMU, MAXPHI PARAMETER(MAXCLY=151,MAXULV=151) PARAMETER(MAXUMU=32,MAXCMU=32) PARAMETER(MAXPHI=3) INTEGER NLYR, NUMU REAL ALBEDO, DTAUC( MAXCLY ), $ PMOM( 0:MAXCMU, MAXCLY ), $ SSALB( MAXCLY ), $ UMU( MAXUMU ), CWT( MAXUMU ), UMU0 REAL RFLDIR( MAXULV ), RFLDN( MAXULV ), FLUP( MAXULV ), $ U0U( MAXUMU, MAXULV ), $ uavgso( maxulv ), uavgup( maxulv ), uavgdn( maxulv ), $ sindir( maxulv ), sinup( maxulv ), sindn( maxulv ) *bm added array LDIF for convenience (sky radiance) *bm sine weighted intensity REAL irrad REAL ldif(MAXUMU, kz) REAL sdir(kz), sdn(kz), sup(kz) *_______________________________________________________________________ * initialize: DO 5 i = 1, nz fdir(i) = 0. fup(i) = 0. fdn(i) = 0. edir(i) = 0. eup(i) = 0. edn(i) = 0. sdir(i) = 0. sup(i) = 0. sdn(i) = 0. 5 CONTINUE UMU0 = cos(zen*dr) NLYR = nz - 1 ALBEDO = ag DO 10 i = 1, nz - 1 dscld = dtcld(i,iw)*omcld(i,iw) dacld = dtcld(i,iw)*(1.-omcld(i,iw)) dsaer = dtaer(i,iw)*omaer(i,iw) daaer = dtaer(i,iw)*(1.-omaer(i,iw)) dssnw = dtsnw(i,iw)*omsnw(i,iw) dasnw = dtsnw(i,iw)*(1.-omsnw(i,iw)) dtsct = dtrl(i,iw) + dscld + dsaer + dssnw dtabs = dtso2(i,iw) + dto2(i,iw) + dto3 (i,iw) + > dtno2(i,iw) + dacld + daaer + dasnw dtabs = amax1(dtabs,1./largest) dtsct = amax1(dtsct,1./largest) * invert z-coordinate: ii = nz - i dt(ii) = dtsct + dtabs om(ii) = dtsct/(dtsct + dtabs) IF(dtsct .EQ. 1./largest) om(ii) = 1./largest g(ii) = (gcld(i,iw)*dscld + $ gsnw(i,iw)*dssnw + $ gaer(i,iw)*dsaer)/dtsct IF(nstr .LT. 2) GO TO 10 * DISORD parameters OM1 = AMIN1(OM(ii),1.-PRECIS) SSALB( II ) = AMAX1(OM1,PRECIS) DTAUC( II ) = AMAX1(DT(ii),PRECIS) * phase function - assume Henyey-Greenstein for cloud and aerosol * and Rayleigh for molecular scattering PMOM(0,II) = 1.0 DO 15 ISTR = 1, NSTR PMCLD = GCLD(i,iw)**(ISTR) PMAER = GAER(i,iw)**(ISTR) PMSNW = GSNW(i,iw)**(ISTR) IF(ISTR .EQ. 2) THEN PMRAY = 0.1 ELSE PMRAY = 0. ENDIF PMOM(ISTR,II) = (PMCLD*DSCLD + $ PMAER*DSAER + $ PMSNW*DSSNW + $ PMRAY*DTRL(i,iw)) / DTSCT 15 CONTINUE 10 CONTINUE * call rt routine: IF( nstr .LT. 2 ) THEN CALL ps2str(nz,zen,ag,dt,om,g, $ dsdh, nid, delta, $ fdiri, fupi, fdni, ediri, eupi, edni, $ kout) ELSE CALL PSNDO( dsdh, nid, $ NLYR, DTAUC, SSALB, PMOM, $ ALBEDO, NSTR, $ NUMU, UMU, CWT, UMU0, $ MAXCLY, MAXULV, MAXUMU, MAXCMU, MAXPHI, $ RFLDIR,RFLDN, FLUP, U0U, $ uavgso, uavgup, uavgdn, $ sindir, sinup, sindn, $ kout) ENDIF * output (invert z-coordinate) DO 20 i = 1, nz ii = nz - i + 1 IF( nstr .LT. 2 ) THEN fdir(i) = fdiri(ii) fup(i) = fupi(ii) fdn(i) = fdni(ii) edir(i) = ediri(ii) eup(i) = eupi(ii) edn(i) = edni(ii) ELSE edir(i) = RFLDIR(II) edn(i) = RFLDN(II) eup(i) = FLUP(II) fdir(i) = 4.* pi * uavgso(ii) fdn(i) = 4.* pi * uavgdn(ii) fup(i) = 4.* pi * uavgup(ii) sdir(i) = sindir(ii) sdn(i) = sindn(ii) sup(i) = sinup(ii) *bm azimutally averaged radiances at computational angles: *bm ldif(iu,i) is the radiance at level i and cosine of polar angle UMU(iu); *bm the polar angle is measured from the upward direction, implying that *bm positive mu is upwelling and negative mu down-welling radiation. DO iu = 1, numu ldif(iu,i) = u0u (iu, ii) ENDDO ENDIF 20 CONTINUE *bm example output: c DO iu = 1, numu c WRITE (*,*) 'rad',iu,umu(iu),ldif(iu,1) c ENDDO *bm example for an integral, irradiance c irrad = 0. c DO iu = 1, NUMU/2 c irrad = irrad + ldif(iu,1)*cwt(iu)*umu(iu) c ENDDO c irrad = irrad * 2. * pi c WRITE (*,*) edn(1),' = ',irrad,' ?' RETURN END *=============================================================================* SUBROUTINE ps2str(nlevel,zen,rsfc,tauu,omu,gu, $ dsdh, nid, delta, $ fdr, fup, fdn, edr, eup, edn, $ kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Solve two-stream equations for multiple layers. The subroutine is based =* *= on equations from: Toon et al., J.Geophys.Res., v94 (D13), Nov 20, 1989.=* *= It contains 9 two-stream methods to choose from. A pseudo-spherical =* *= correction has also been added. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NLEVEL - INTEGER, number of specified altitude levels in the working (I)=* *= grid =* *= ZEN - REAL, solar zenith angle (degrees) (I)=* *= RSFC - REAL, surface albedo at current wavelength (I)=* *= TAUU - REAL, unscaled optical depth of each layer (I)=* *= OMU - REAL, unscaled single scattering albedo of each layer (I)=* *= GU - REAL, unscaled asymmetry parameter of each layer (I)=* *= DSDH - REAL, slant path of direct beam through each layer crossed (I)=* *= when travelling from the top of the atmosphere to layer i; =* *= DSDH(i,j), i = 0..NZ-1, j = 1..NZ-1 =* *= NID - INTEGER, number of layers crossed by the direct beam when (I)=* *= travelling from the top of the atmosphere to layer i; =* *= NID(i), i = 0..NZ-1 =* *= DELTA - LOGICAL, switch to use delta-scaling (I)=* *= .TRUE. -> apply delta-scaling =* *= .FALSE.-> do not apply delta-scaling =* *= FDR - REAL, contribution of the direct component to the total (O)=* *= actinic flux at each altitude level =* *= FUP - REAL, contribution of the diffuse upwelling component to (O)=* *= the total actinic flux at each altitude level =* *= FDN - REAL, contribution of the diffuse downwelling component to (O)=* *= the total actinic flux at each altitude level =* *= EDR - REAL, contribution of the direct component to the total (O)=* *= spectral irradiance at each altitude level =* *= EUP - REAL, contribution of the diffuse upwelling component to (O)=* *= the total spectral irradiance at each altitude level =* *= EDN - REAL, contribution of the diffuse downwelling component to (O)=* *= the total spectral irradiance at each altitude level =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) INTEGER nrows PARAMETER(nrows=2*kz) ******* * input: ******* INTEGER nlevel REAL zen, rsfc REAL tauu(kz), omu(kz), gu(kz) REAL dsdh(0:kz,kz) INTEGER nid(0:kz) LOGICAL delta ******* * output: ******* REAL fup(kz),fdn(kz),fdr(kz) REAL eup(kz),edn(kz),edr(kz) ******* * local: ******* REAL tausla(0:kz), tauc(0:kz) REAL mu2(0:kz), mu, sum * internal coefficients and matrix REAL lam(kz),taun(kz),bgam(kz) REAL e1(kz),e2(kz),e3(kz),e4(kz) REAL cup(kz),cdn(kz),cuptn(kz),cdntn(kz) REAL mu1(kz) INTEGER row REAL a(nrows),b(nrows),d(nrows),e(nrows),y(nrows) ******* * other: ******* REAL pifs, fdn0, surfem REAL gi(kz), omi(kz), tempg REAL f, g, om REAL gam1, gam2, gam3, gam4 * For calculations of Associated Legendre Polynomials for GAMA1,2,3,4 * in delta-function, modified quadrature, hemispheric constant, * Hybrid modified Eddington-delta function metods, p633,Table1. * W.E.Meador and W.R.Weaver, GAS,1980,v37,p.630 * W.J.Wiscombe and G.W. Grams, GAS,1976,v33,p2440, * uncomment the following two lines and the appropriate statements further * down. C REAL YLM0, YLM2, YLM4, YLM6, YLM8, YLM10, YLM12, YLMS, BETA0, C > BETA1, BETAn, amu1, subd REAL expon, expon0, expon1, divisr, temp, up, dn REAL ssfc INTEGER nlayer, mrows, lev INTEGER i, j * Some additional program constants: REAL eps PARAMETER (eps = 1.E-3) *_______________________________________________________________________ * MU = cosine of solar zenith angle * RSFC = surface albedo * TAUU = unscaled optical depth of each layer * OMU = unscaled single scattering albedo * GU = unscaled asymmetry factor * KLEV = max dimension of number of layers in atmosphere * NLAYER = number of layers in the atmosphere * NLEVEL = nlayer + 1 = number of levels * initial conditions: pi*solar flux = 1; diffuse incidence = 0 pifs = 1. fdn0 = 0. * emission at surface (for night light pollution, set pifs = 0, surfem = 1.) surfem = 0. nlayer = nlevel - 1 mu = COS(zen*pi/180.) ************** compute coefficients for each layer: * GAM1 - GAM4 = 2-stream coefficients, different for different approximations * EXPON0 = calculation of e when TAU is zero * EXPON1 = calculation of e when TAU is TAUN * CUP and CDN = calculation when TAU is zero * CUPTN and CDNTN = calc. when TAU is TAUN * DIVISR = prevents division by zero do j = 0, kz tauc(j) = 0. tausla(j) = 0. mu2(j) = 1./SQRT(largest) end do IF( .NOT. delta ) THEN DO i = 1, nlayer gi(i) = gu(i) omi(i) = omu(i) taun(i) = tauu(i) ENDDO ELSE * delta-scaling. Have to be done for delta-Eddington approximation, * delta discrete ordinate, Practical Improved Flux Method, delta function, * and Hybrid modified Eddington-delta function methods approximations DO i = 1, nlayer f = gu(i)*gu(i) gi(i) = (gu(i) - f)/(1 - f) omi(i) = (1 - f)*omu(i)/(1 - omu(i)*f) taun(i) = (1 - omu(i)*f)*tauu(i) ENDDO END IF * * calculate slant optical depth at the top of the atmosphere when zen>90. * in this case, higher altitude of the top layer is recommended which can * be easily changed in gridz.f. * IF(zen .GT. 90.0) THEN IF(nid(0) .LT. 0) THEN tausla(0) = largest ELSE sum = 0.0 DO j = 1, nid(0) sum = sum + 2.*taun(j)*dsdh(0,j) END DO tausla(0) = sum END IF END IF * DO 11, i = 1, nlayer g = gi(i) om = omi(i) tauc(i) = tauc(i-1) + taun(i) * stay away from 1 by precision. For g, also stay away from -1 tempg = AMIN1(abs(g),1. - precis) g = SIGN(tempg,g) om = AMIN1(om,1.-precis) * calculate slant optical depth * IF(nid(i) .LT. 0) THEN tausla(i) = largest ELSE sum = 0.0 DO j = 1, MIN(nid(i),i) sum = sum + taun(j)*dsdh(i,j) ENDDO DO j = MIN(nid(i),i)+1,nid(i) sum = sum + 2.*taun(j)*dsdh(i,j) ENDDO tausla(i) = sum IF(tausla(i) .EQ. tausla(i-1)) THEN mu2(i) = SQRT(largest) ELSE mu2(i) = (tauc(i)-tauc(i-1))/(tausla(i)-tausla(i-1)) mu2(i) = SIGN( AMAX1(ABS(mu2(i)),1./SQRT(largest)), $ mu2(i) ) END IF END IF * *** the following gamma equations are from pg 16,289, Table 1 *** save mu1 for each approx. for use in converting irradiance to actinic flux * Eddington approximation(Joseph et al., 1976, JAS, 33, 2452): gam1 = (7. - om*(4. + 3.*g))/4. gam2 = -(1. - om*(4. - 3.*g))/4. gam3 = (2. - 3.*g*mu)/4. gam4 = 1. - gam3 mu1(i) = 0.5 * quadrature (Liou, 1973, JAS, 30, 1303-1326; 1974, JAS, 31, 1473-1475): c gam1 = 1.7320508*(2. - om*(1. + g))/2. c gam2 = 1.7320508*om*(1. - g)/2. c gam3 = (1. - 1.7320508*g*mu)/2. c gam4 = 1. - gam3 c mu1(i) = 1./sqrt(3.) * hemispheric mean (Toon et al., 1089, JGR, 94, 16287): c gam1 = 2. - om*(1. + g) c gam2 = om*(1. - g) c gam3 = (2. - g*mu)/4. c gam4 = 1. - gam3 c mu1(i) = 0.5 * PIFM (Zdunkovski et al.,1980, Conrib.Atmos.Phys., 53, 147-166): c GAM1 = 0.25*(8. - OM*(5. + 3.*G)) c GAM2 = 0.75*OM*(1.-G) c GAM3 = 0.25*(2.-3.*G*MU) c GAM4 = 1. - GAM3 c mu1(i) = 0.5 * delta discrete ordinates (Schaller, 1979, Contrib.Atmos.Phys, 52, 17-26): c GAM1 = 0.5*1.7320508*(2. - OM*(1. + G)) c GAM2 = 0.5*1.7320508*OM*(1.-G) c GAM3 = 0.5*(1.-1.7320508*G*MU) c GAM4 = 1. - GAM3 c mu1(i) = 1./sqrt(3.) * Calculations of Associated Legendre Polynomials for GAMA1,2,3,4 * in delta-function, modified quadrature, hemispheric constant, * Hybrid modified Eddington-delta function metods, p633,Table1. * W.E.Meador and W.R.Weaver, GAS,1980,v37,p.630 * W.J.Wiscombe and G.W. Grams, GAS,1976,v33,p2440 c YLM0 = 2. c YLM2 = -3.*G*MU c YLM4 = 0.875*G**3*MU*(5.*MU**2-3.) c YLM6=-0.171875*G**5*MU*(15.-70.*MU**2+63.*MU**4) c YLM8=+0.073242*G**7*MU*(-35.+315.*MU**2-693.*MU**4 c *+429.*MU**6) c YLM10=-0.008118*G**9*MU*(315.-4620.*MU**2+18018.*MU**4 c *-25740.*MU**6+12155.*MU**8) c YLM12=0.003685*G**11*MU*(-693.+15015.*MU**2-90090.*MU**4 c *+218790.*MU**6-230945.*MU**8+88179.*MU**10) c YLMS=YLM0+YLM2+YLM4+YLM6+YLM8+YLM10+YLM12 c YLMS=0.25*YLMS c BETA0 = YLMS c c amu1=1./1.7320508 c YLM0 = 2. c YLM2 = -3.*G*amu1 c YLM4 = 0.875*G**3*amu1*(5.*amu1**2-3.) c YLM6=-0.171875*G**5*amu1*(15.-70.*amu1**2+63.*amu1**4) c YLM8=+0.073242*G**7*amu1*(-35.+315.*amu1**2-693.*amu1**4 c *+429.*amu1**6) c YLM10=-0.008118*G**9*amu1*(315.-4620.*amu1**2+18018.*amu1**4 c *-25740.*amu1**6+12155.*amu1**8) c YLM12=0.003685*G**11*amu1*(-693.+15015.*amu1**2-90090.*amu1**4 c *+218790.*amu1**6-230945.*amu1**8+88179.*amu1**10) c YLMS=YLM0+YLM2+YLM4+YLM6+YLM8+YLM10+YLM12 c YLMS=0.25*YLMS c BETA1 = YLMS c c BETAn = 0.25*(2. - 1.5*G-0.21875*G**3-0.085938*G**5 c *-0.045776*G**7) * Hybrid modified Eddington-delta function(Meador and Weaver,1980,JAS,37,630): c subd=4.*(1.-G*G*(1.-MU)) c GAM1 = (7.-3.*G*G-OM*(4.+3.*G)+OM*G*G*(4.*BETA0+3.*G))/subd c GAM2 =-(1.-G*G-OM*(4.-3.*G)-OM*G*G*(4.*BETA0+3.*G-4.))/subd c GAM3 = BETA0 c GAM4 = 1. - GAM3 c mu1(i) = (1. - g*g*(1.- mu) )/(2. - g*g) ***** * delta function (Meador, and Weaver, 1980, JAS, 37, 630): c GAM1 = (1. - OM*(1. - beta0))/MU c GAM2 = OM*BETA0/MU c GAM3 = BETA0 c GAM4 = 1. - GAM3 c mu1(i) = mu ***** * modified quadrature (Meador, and Weaver, 1980, JAS, 37, 630): c GAM1 = 1.7320508*(1. - OM*(1. - beta1)) c GAM2 = 1.7320508*OM*beta1 c GAM3 = BETA0 c GAM4 = 1. - GAM3 c mu1(i) = 1./sqrt(3.) * hemispheric constant (Toon et al., 1989, JGR, 94, 16287): c GAM1 = 2.*(1. - OM*(1. - betan)) c GAM2 = 2.*OM*BETAn c GAM3 = BETA0 c GAM4 = 1. - GAM3 c mu1(i) = 0.5 ***** * lambda = pg 16,290 equation 21 * big gamma = pg 16,290 equation 22 * checked limit for gam2/gam1 <<1: bgam -> (1/2)*gma2/gam1 * so if if gam2 = 0., then bgam = 0. lam(i) = sqrt(gam1*gam1 - gam2*gam2) IF( gam2 .NE. 0.) THEN bgam(i) = (gam1 - lam(i))/gam2 ELSE bgam(i) = 0. ENDIF expon = EXP(-lam(i)*taun(i)) * e1 - e4 = pg 16,292 equation 44 e1(i) = 1. + bgam(i)*expon e2(i) = 1. - bgam(i)*expon e3(i) = bgam(i) + expon e4(i) = bgam(i) - expon * the following sets up for the C equations 23, and 24 * found on page 16,290 * prevent division by zero (if LAMBDA=1/MU, shift 1/MU^2 by EPS = 1.E-3 * which is approx equiv to shifting MU by 0.5*EPS* (MU)**3 expon0 = EXP(-tausla(i-1)) expon1 = EXP(-tausla(i)) divisr = lam(i)*lam(i) - 1./(mu2(i)*mu2(i)) temp = AMAX1(eps,abs(divisr)) divisr = SIGN(temp,divisr) up = om*pifs*((gam1 - 1./mu2(i))*gam3 + gam4*gam2)/divisr dn = om*pifs*((gam1 + 1./mu2(i))*gam4 + gam2*gam3)/divisr * cup and cdn are when tau is equal to zero * cuptn and cdntn are when tau is equal to taun cup(i) = up*expon0 cdn(i) = dn*expon0 cuptn(i) = up*expon1 cdntn(i) = dn*expon1 11 CONTINUE ***************** set up matrix ****** * ssfc = pg 16,292 equation 37 where pi Fs is one (unity). ssfc = rsfc*mu*EXP(-tausla(nlayer))*pifs + surfem * MROWS = the number of rows in the matrix mrows = 2*nlayer * the following are from pg 16,292 equations 39 - 43. * set up first row of matrix: i = 1 a(1) = 0. b(1) = e1(i) d(1) = -e2(i) e(1) = fdn0 - cdn(i) row=1 * set up odd rows 3 thru (MROWS - 1): i = 0 DO 20, row = 3, mrows - 1, 2 i = i + 1 a(row) = e2(i)*e3(i) - e4(i)*e1(i) b(row) = e1(i)*e1(i + 1) - e3(i)*e3(i + 1) d(row) = e3(i)*e4(i + 1) - e1(i)*e2(i + 1) e(row) = e3(i)*(cup(i + 1) - cuptn(i)) + $ e1(i)*(cdntn(i) - cdn(i + 1)) 20 CONTINUE * set up even rows 2 thru (MROWS - 2): i = 0 DO 30, row = 2, mrows - 2, 2 i = i + 1 a(row) = e2(i + 1)*e1(i) - e3(i)*e4(i + 1) b(row) = e2(i)*e2(i + 1) - e4(i)*e4(i + 1) d(row) = e1(i + 1)*e4(i + 1) - e2(i + 1)*e3(i + 1) e(row) = (cup(i + 1) - cuptn(i))*e2(i + 1) - $ (cdn(i + 1) - cdntn(i))*e4(i + 1) 30 CONTINUE * set up last row of matrix at MROWS: row = mrows i = nlayer a(row) = e1(i) - rsfc*e3(i) b(row) = e2(i) - rsfc*e4(i) d(row) = 0. e(row) = ssfc - cuptn(i) + rsfc*cdntn(i) * solve tri-diagonal matrix: CALL tridag(a, b, d, e, y, mrows,kout) **** unfold solution of matrix, compute output fluxes: row = 1 lev = 1 j = 1 * the following equations are from pg 16,291 equations 31 & 32 fdr(lev) = pifs * EXP( -tausla(0) ) edr(lev) = mu * fdr(lev) edn(lev) = fdn0 eup(lev) = y(row)*e3(j) - y(row + 1)*e4(j) + cup(j) fdn(lev) = edn(lev)/mu1(lev) fup(lev) = eup(lev)/mu1(lev) DO 60, lev = 2, nlayer + 1 fdr(lev) = pifs * EXP(-tausla(lev-1)) edr(lev) = mu *fdr(lev) edn(lev) = y(row)*e3(j) + y(row + 1)*e4(j) + cdntn(j) eup(lev) = y(row)*e1(j) + y(row + 1)*e2(j) + cuptn(j) fdn(lev) = edn(lev)/mu1(j) fup(lev) = eup(lev)/mu1(j) row = row + 2 j = j + 1 60 CONTINUE *_______________________________________________________________________ RETURN END *=============================================================================* SUBROUTINE tridag(a,b,c,r,u,n,kout) *_______________________________________________________________________ * solves tridiagonal system. From Numerical Recipies, p. 40 *_______________________________________________________________________ IMPLICIT NONE * input: INTEGER n REAL a, b, c, r DIMENSION a(n),b(n),c(n),r(n) * output: REAL u DIMENSION u(n) * local: INTEGER j c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) REAL bet, gam DIMENSION gam(2*kz) *_______________________________________________________________________ IF (b(1) .EQ. 0.) STOP 1001 bet = b(1) u(1) = r(1)/bet DO 11, j = 2, n gam(j) = c(j - 1)/bet bet = b(j) - a(j)*gam(j) IF (bet .EQ. 0.) STOP 2002 u(j) = (r(j) - a(j)*u(j - 1))/bet 11 CONTINUE DO 12, j = n - 1, 1, -1 u(j) = u(j) - gam(j + 1)*u(j + 1) 12 CONTINUE *_______________________________________________________________________ RETURN END *=============================================================================* c Note: CDIR$ and CFPP$ comment lines are relevant only when running c on Cray computers. They cause better optimization of loops c immediately following. C SUBROUTINE DISORT( dsdh, nid, SUBROUTINE PSNDO( dsdh, nid, & NLYR, DTAUC, SSALB, PMOM, & ALBEDO, NSTR, & NUMU, UMU, CWT, UMU0, & MAXCLY, MAXULV, MAXUMU, MAXCMU, MAXPHI, $ RFLDIR, RFLDN, FLUP, U0U, & uavgso, uavgup, uavgdn, & sindir, sinup, sindn, & kout ) c Improved handling of numerical instabilities. Bernhard Mayer on 5/3/99. c disort seems to produce unstable results for certain combinations c of single scattering albedo and phase function. A temporary fix has been c introduced to avoid this problem: The original instability check in c UPBEAM fails on certain compiler/machine combinations (e.g., gcc/LINUX, c or xlf/IBM RS6000). This check has therefore been replaced by a new one. c Whenever UPBEAM reports an instability, the single scattering albedo c of the respective layer is changed by a small amount, and the c calculation is repeated until numerically stable conditions are reached c (all the necessary changes are confined to the new subroutine SOLVEC c and the slighly changed subroutine UPBEAM). To check for potential c instabilities, the variable 'RCOND' returned by SGECO is compared to c a machine-dependent constant, 'MINRCOND'. The value of this constant c determines (a) if really all instabilities are caught; and (b) the c amount by which the single scattering albedo has to be changed. The c value of 'MINRCOND' is therefore a compromise between numerical c stability on the one hand and uncertainties introduced by changing c the atmospheric conditions and increased computational time on the c other hand (an increase of MINRCOND will lead to the detection of c more potential numerical instabilities, and thus to an increase in c computational time; by changing the atmospheric conditions, that is, c the single scattering albedo, the result might however be changed c unfavourably, if the change is too large). From a limited number c of experiments we found that 'MINRCOND = 5000. * R1MACH(4)' seems c to be a good choice if high accuracy is required (more tests are c definitely neccessary!). If an instability is encountered, a message c is printed telling about neccessary changes to the single scattering c albedo. This message may be switched off by setting 'DEBUG = .FALSE.' c in subroutine SOLVEC. c c c modified to calculate sine-weighted intensities. Bernhard Mayer on 2/12/99. c modified to handle some numerical instabilities. Chris Fischer on 1/22/99. c modified by adding pseudo-spherical correction. Jun Zeng on 3/11/97. c dsdh: slant path of direct beam through each layer crossed c when travelling from the top of the atmosphere to layer i; c dsdh(i,j), i = 0..nlyr, j = 1..nlyr; c nid: number of layers crossed by the direct beam when c travelling from the top of the atmosphere to layer i; c NID(i), i = 0..nlyr. c uavgso, uvagup, and uvagdn are direct, downward diffuse, and upward c diffuse actinic flux (mean intensity). c u0u is the azimuthally averaged intensity, check DISORT.doc for details. c ******************************************************************* c Plane-parallel discrete ordinates radiative transfer program c V E R S I O N 1.1 c ( see DISORT.DOC for complete documentation ) c ******************************************************************* c +------------------------------------------------------------------+ c Calling Tree (omitting calls to ERRMSG): c (routines in parentheses are not in this file) c DISORT-+-(R1MACH) c +-ZEROIT c +-CHEKIN-+-(WRTBAD) c | +-(WRTDIM) c | +-DREF c +-ZEROAL c +-SETDIS-+-QGAUSN (1)-+-(D1MACH) c +-PRTINP c +-LEPOLY see 2 c +-SURFAC-+-QGAUSN see 1 c | +-LEPOLY see 2 c | +-ZEROIT c +-SOLEIG see 3 c +-UPBEAM-+-(SGECO) c | +-(SGESL) c +-TERPEV c +-TERPSO c +-SETMTX see 4 c +-SOLVE0-+-ZEROIT c | +-(SGBCO) c | +-(SGBSL) c +-FLUXES--ZEROIT c +-PRAVIN c +-RATIO--(R1MACH) c +-PRTINT c *** Intrinsic Functions used in DISORT package which take c non-negligible amount of time: c EXP : Called by- ALBTRN, ALTRIN, CMPINT, FLUXES, SETDIS, c SETMTX, SPALTR, USRINT, PLKAVG c SQRT : Called by- ASYMTX, LEPOLY, SOLEIG c +-------------------------------------------------------------------+ c Index conventions (for all DO-loops and all variable descriptions): c IU : for user polar angles c IQ,JQ,KQ : for computational polar angles ('quadrature angles') c IQ/2 : for half the computational polar angles (just the ones c in either 0-90 degrees, or 90-180 degrees) c J : for user azimuthal angles c K,L : for Legendre expansion coefficients or, alternatively, c subscripts of associated Legendre polynomials c LU : for user levels c LC : for computational layers (each having a different c single-scatter albedo and/or phase function) c LEV : for computational levels c MAZIM : for azimuthal components in Fourier cosine expansion c of intensity and phase function c +------------------------------------------------------------------+ c I N T E R N A L V A R I A B L E S c AMB(IQ/2,IQ/2) First matrix factor in reduced eigenvalue problem c of Eqs. SS(12), STWJ(8E) (used only in SOLEIG) c APB(IQ/2,IQ/2) Second matrix factor in reduced eigenvalue problem c of Eqs. SS(12), STWJ(8E) (used only in SOLEIG) c ARRAY(IQ,IQ) Scratch matrix for SOLEIG, UPBEAM and UPISOT c (see each subroutine for definition) c B() Right-hand side vector of Eq. SC(5) going into c SOLVE0,1; returns as solution vector c vector L, the constants of integration c BDR(IQ/2,0:IQ/2) Bottom-boundary bidirectional reflectivity for a c given azimuthal component. First index always c refers to a computational angle. Second index: c if zero, refers to incident beam angle UMU0; c if non-zero, refers to a computational angle. c BEM(IQ/2) Bottom-boundary directional emissivity at compu- c tational angles. c BPLANK Intensity emitted from bottom boundary c CBAND() Matrix of left-hand side of the linear system c Eq. SC(5), scaled by Eq. SC(12); in banded c form required by LINPACK solution routines c CC(IQ,IQ) C-sub-IJ in Eq. SS(5) c CMU(IQ) Computational polar angles (Gaussian) c CWT(IQ) Quadrature weights corresponding to CMU c DELM0 Kronecker delta, delta-sub-M0, where M = MAZIM c is the number of the Fourier component in the c azimuth cosine expansion c DITHER Small quantity subtracted from single-scattering c albedos of unity, in order to avoid using special c case formulas; prevents an eigenvalue of exactly c zero from occurring, which would cause an c immediate overflow c DTAUCP(LC) Computational-layer optical depths (delta-M-scaled c if DELTAM = TRUE, otherwise equal to DTAUC) c EMU(IU) Bottom-boundary directional emissivity at user c angles. c EVAL(IQ) Temporary storage for eigenvalues of Eq. SS(12) c EVECC(IQ,IQ) Complete eigenvectors of SS(7) on return from c SOLEIG; stored permanently in GC c EXPBEA(LC) Transmission of direct beam in delta-M optical c depth coordinates c FLYR(LC) Truncated fraction in delta-M method c GL(K,LC) Phase function Legendre polynomial expansion c coefficients, calculated from PMOM by c including single-scattering albedo, factor c 2K+1, and (if DELTAM=TRUE) the delta-M c scaling c GC(IQ,IQ,LC) Eigenvectors at polar quadrature angles, c g in Eq. SC(1) c GU(IU,IQ,LC) Eigenvectors interpolated to user polar angles c ( g in Eqs. SC(3) and S1(8-9), i.e. c G without the L factor ) c HLPR() Legendre coefficients of bottom bidirectional c reflectivity (after inclusion of 2K+1 factor) c IPVT(LC*IQ) Integer vector of pivot indices for LINPACK c routines c KK(IQ,LC) Eigenvalues of coeff. matrix in Eq. SS(7) c KCONV Counter in azimuth convergence test c LAYRU(LU) Computational layer in which user output level c UTAU(LU) is located c LL(IQ,LC) Constants of integration L in Eq. SC(1), c obtained by solving scaled version of Eq. SC(5) c LYRCUT TRUE, radiation is assumed zero below layer c NCUT because of almost complete absorption c NAZ Number of azimuthal components considered c NCUT Computational layer number in which absorption c optical depth first exceeds ABSCUT c OPRIM(LC) Single scattering albedo after delta-M scaling c PASS1 TRUE on first entry, FALSE thereafter c PKAG(0:LC) Integrated Planck function for internal emission c PSI(IQ) Sum just after square bracket in Eq. SD(9) c RMU(IU,0:IQ) Bottom-boundary bidirectional reflectivity for a c given azimuthal component. First index always c refers to a user angle. Second index: c if zero, refers to incident beam angle UMU0; c if non-zero, refers to a computational angle. c TAUC(0:LC) Cumulative optical depth (un-delta-M-scaled) c TAUCPR(0:LC) Cumulative optical depth (delta-M-scaled if c DELTAM = TRUE, otherwise equal to TAUC) c TPLANK Intensity emitted from top boundary c UUM(IU,LU) Expansion coefficients when the intensity c (u-super-M) is expanded in Fourier cosine series c in azimuth angle c U0C(IQ,LU) Azimuthally-averaged intensity c UTAUPR(LU) Optical depths of user output levels in delta-M c coordinates; equal to UTAU(LU) if no delta-M c WK() scratch array c XR0(LC) X-sub-zero in expansion of thermal source func- c tion preceding Eq. SS(14) (has no mu-dependence) c XR1(LC) X-sub-one in expansion of thermal source func- c tion; see Eqs. SS(14-16) c YLM0(L) Normalized associated Legendre polynomial c of subscript L at the beam angle (not saved c as function of superscipt M) c YLMC(L,IQ) Normalized associated Legendre polynomial c of subscript L at the computational angles c (not saved as function of superscipt M) c YLMU(L,IU) Normalized associated Legendre polynomial c of subscript L at the user angles c (not saved as function of superscipt M) c Z() scratch array used in SOLVE0,1 to solve a c linear system for the constants of integration c Z0(IQ) Solution vectors Z-sub-zero of Eq. SS(16) c Z0U(IU,LC) Z-sub-zero in Eq. SS(16) interpolated to user c angles from an equation derived from SS(16) c Z1(IQ) Solution vectors Z-sub-one of Eq. SS(16) c Z1U(IU,LC) Z-sub-one in Eq. SS(16) interpolated to user c angles from an equation derived from SS(16) c ZBEAM(IU,LC) Particular solution for beam source c ZJ(IQ) Right-hand side vector X-sub-zero in c Eq. SS(19), also the solution vector c Z-sub-zero after solving that system c ZZ(IQ,LC) Permanent storage for the beam source vectors ZJ c ZPLK0(IQ,LC) Permanent storage for the thermal source c vectors Z0 obtained by solving Eq. SS(16) c ZPLK1(IQ,LC) Permanent storage for the thermal source c vectors Z1 obtained by solving Eq. SS(16) c +-------------------------------------------------------------------+ c LOCAL SYMBOLIC DIMENSIONS (have big effect on storage requirements): c MXCLY = Max no. of computational layers c MXULV = Max no. of output levels c MXCMU = Max no. of computation polar angles c MXUMU = Max no. of output polar angles c MXPHI = Max no. of output azimuthal angles c +-------------------------------------------------------------------+ c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) c .. Parameters .. INTEGER MXCLY, MXULV, MXCMU, MXUMU, MXPHI, MI, MI9M2, NNLYRI PARAMETER ( MXCLY = 151, MXULV = 151, MXCMU = 32, MXUMU = 32, & MXPHI = 3, MI = MXCMU / 2, MI9M2 = 9*MI - 2, & NNLYRI = MXCMU*MXCLY ) c .. c .. Scalar Arguments .. CHARACTER HEADER*127 LOGICAL DELTAM, LAMBER, ONLYFL, PLANK, USRANG, USRTAU INTEGER IBCND, MAXCLY, MAXCMU, MAXPHI, MAXULV, MAXUMU, NLYR, & NPHI, NSTR, NTAU, NUMU REAL ACCUR, ALBEDO, BTEMP, FBEAM, FISOT, PHI0, TEMIS, TTEMP, & UMU0, WVNMHI, WVNMLO c sherical geometry REAL dsdh(0:kz,kz) INTEGER nid(0:kz) REAL tausla(0:kz), tauslau(0:kz), mu2(0:kz) c .. c .. Array Arguments .. LOGICAL PRNT( 7 ) REAL ALBMED( MAXUMU ), DFDT( MAXULV ), DTAUC( MAXCLY ), & FLUP( MAXULV ), HL( 0:MAXCMU ), PHI( MAXPHI ), & PMOM( 0:MAXCMU, MAXCLY ), RFLDIR( MAXULV ), & RFLDN( MAXULV ), SSALB( MAXCLY ), TEMPER( 0:MAXCLY ), & TRNMED( MAXUMU ), U0U( MAXUMU, MAXULV ), UAVG( MAXULV ), & UMU( MAXUMU ), CWT( MAXCMU ), UTAU( MAXULV ), & UU( MAXUMU, MAXULV, MAXPHI ), & uavgso( maxulv ), uavgup( maxulv ), uavgdn( maxulv ), & sindir( maxulv ), sinup( maxulv ), sindn ( maxulv ) c .. c .. Local Scalars .. LOGICAL COMPAR, LYRCUT, PASS1 INTEGER IQ, IU, J, KCONV, L, LC, LEV, LU, MAZIM, NAZ, NCOL, & NCOS, NCUT, NN REAL ANGCOS, AZERR, AZTERM, BPLANK, COSPHI, DELM0, DITHER, & DUM, RPD, SGN, TPLANK c .. c .. Local Arrays .. INTEGER IPVT( NNLYRI ), LAYRU( MXULV ) REAL AMB( MI, MI ), APB( MI, MI ), ARRAY( MXCMU, MXCMU ), & B( NNLYRI ), BDR( MI, 0:MI ), BEM( MI ), & CBAND( MI9M2, NNLYRI ), CC( MXCMU, MXCMU ), & CMU( MXCMU ), DTAUCP( MXCLY ), & EMU( MXUMU ), EVAL( MI ), EVECC( MXCMU, MXCMU ), & EXPBEA( 0:MXCLY ), FLDIR( MXULV ), FLDN( MXULV ), & FLYR( MXCLY ), GC( MXCMU, MXCMU, MXCLY ), & GL( 0:MXCMU, MXCLY ), GU( MXUMU, MXCMU, MXCLY ), & HLPR( 0:MXCMU ), KK( MXCMU, MXCLY ), LL( MXCMU, MXCLY ), & OPRIM( MXCLY ), PHIRAD( MXPHI ), PKAG( 0:MXCLY ), & PSI( MXCMU ), RMU( MXUMU, 0:MI ), TAUC( 0:MXCLY ), & TAUCPR( 0:MXCLY ), U0C( MXCMU, MXULV ), UTAUPR( MXULV ), & UUM( MXUMU, MXULV ), WK( MXCMU ), XR0( MXCLY ), & XR1( MXCLY ), YLM0( 0:MXCMU ), YLMC( 0:MXCMU, MXCMU ), & YLMU( 0:MXCMU, MXUMU ), Z( NNLYRI ), Z0( MXCMU ), & Z0U( MXUMU, MXCLY ), Z1( MXCMU ), Z1U( MXUMU, MXCLY ), & ZBEAM( MXUMU, MXCLY ), ZJ( MXCMU ), & ZPLK0( MXCMU, MXCLY ), ZPLK1( MXCMU, MXCLY ), & ZZ( MXCMU, MXCLY ) cgy added glsave and dgl to allow adjustable dimensioning in SOLVEC REAL GLSAVE( 0:MXCMU ), DGL( 0:MXCMU ) REAL AAD( MI, MI ), EVALD( MI ), EVECCD( MI, MI ), & WKD( MXCMU ) c .. c .. External Functions .. REAL PLKAVG, R1MACH, RATIO EXTERNAL R1MACH, RATIO c .. c .. External Subroutines .. EXTERNAL CHEKIN, FLUXES, LEPOLY, PRAVIN, PRTINP, & PRTINT, SETDIS, SETMTX, SOLEIG, SOLVE0, SURFAC, & UPBEAM, ZEROAL, ZEROIT c .. c .. Intrinsic Functions .. INTRINSIC ABS, ASIN, COS, LEN, MAX c .. SAVE PASS1, DITHER, RPD DATA PASS1 / .TRUE. / * Discrete ordinate constants: * For pseudo-spherical DISORT, PLANK, USRTAU and USRANG must be .FALSE.; * ONLYFL must be .TRUE.; FBEAM = 1.; FISOT = 0.; IBCND = 0 data LAMBER /.TRUE./ data USRTAU /.FALSE./ data PLANK /.FALSE./ data USRANG /.FALSE./ data ONLYFL /.TRUE./ data PRNT /.FALSE.,.FALSE.,.FALSE.,.FALSE.,.FALSE., $ .FALSE.,.FALSE./ data ACCUR /0.0001/ data HEADER /' '/ data NPHI /0/ data IBCND /0/ data FBEAM /1./ data FISOT /0.0/ data PHI0 /0.0/ * delat-M scaling option data DELTAM /.true./ IF( PASS1 ) THEN DITHER = 10.*R1MACH( 4 ) c ** Must dither more on Cray (14-digit prec) IF( DITHER.LT.1.E-10 ) DITHER = 10.*DITHER RPD = PI / 180.0 PASS1 = .FALSE. END IF 10 CONTINUE c ** Calculate cumulative optical depth c and dither single-scatter albedo c to improve numerical behavior of c eigenvalue/vector computation CALL ZEROIT( TAUC, MXCLY + 1 ) DO 20 LC = 1, NLYR IF( SSALB( LC ).EQ.1.0 ) SSALB( LC ) = 1.0 - DITHER TAUC( LC ) = TAUC( LC - 1 ) + DTAUC( LC ) 20 CONTINUE c ** Check input dimensions and variables CALL CHEKIN( NLYR, DTAUC, SSALB, PMOM, TEMPER, WVNMLO, WVNMHI, & USRTAU, NTAU, UTAU, NSTR, USRANG, NUMU, UMU, NPHI, & PHI, IBCND, FBEAM, UMU0, PHI0, FISOT, LAMBER, ALBEDO, & HL, BTEMP, TTEMP, TEMIS, PLANK, ONLYFL, ACCUR, TAUC, & MAXCLY, MAXULV, MAXUMU, MAXCMU, MAXPHI, MXCLY, MXULV, & MXUMU, MXCMU, MXPHI ) c ** Zero internal and output arrays CALL ZEROAL( MXCLY, EXPBEA(1), FLYR, OPRIM, TAUCPR(1), XR0, XR1, $ MXCMU, CMU, CWT, PSI, WK, Z0, Z1, ZJ, $ MXCMU+1, HLPR, YLM0, $ MXCMU**2, ARRAY, CC, EVECC, $ (MXCMU+1)*MXCLY, GL, $ (MXCMU+1)*MXCMU, YLMC, $ (MXCMU+1)*MXUMU, YLMU, $ MXCMU*MXCLY, KK, LL, ZZ, ZPLK0, ZPLK1, $ MXCMU**2*MXCLY, GC, $ MXULV, LAYRU, UTAUPR, $ MXUMU*MXCMU*MXCLY, GU, $ MXUMU*MXCLY, Z0U, Z1U, ZBEAM, $ MI, EVAL, $ MI**2, AMB, APB, $ NNLYRI, IPVT, Z, $ MAXULV, RFLDIR, RFLDN, FLUP, UAVG, DFDT, $ MAXUMU, ALBMED, TRNMED, $ MAXUMU*MAXULV, U0U, $ MAXUMU*MAXULV*MAXPHI, UU ) c ** Perform various setup operations CALL SETDIS( dsdh, nid, tausla, tauslau, mu2, & CMU, CWT, DELTAM, DTAUC, DTAUCP, EXPBEA, FBEAM, FLYR, & GL, HL, HLPR, IBCND, LAMBER, LAYRU, LYRCUT, MAXUMU, & MAXCMU, MXCMU, NCUT, NLYR, NTAU, NN, NSTR, PLANK, & NUMU, ONLYFL, OPRIM, PMOM, SSALB, TAUC, TAUCPR, UTAU, & UTAUPR, UMU, UMU0, USRTAU, USRANG, kout ) c ** Print input information IF ( PRNT(1) ) $ CALL PRTINP( NLYR, DTAUC, DTAUCP, SSALB, PMOM, TEMPER, $ WVNMLO, WVNMHI, NTAU, UTAU, NSTR, NUMU, UMU, $ NPHI, PHI, IBCND, FBEAM, UMU0, PHI0, FISOT, $ LAMBER, ALBEDO, HL, BTEMP, TTEMP, TEMIS, $ DELTAM, PLANK, ONLYFL, ACCUR, FLYR, LYRCUT, $ OPRIM, TAUC, TAUCPR, MAXCMU, PRNT(7) ) c ** Handle special case for getting albedo c and transmissivity of medium for many c beam angles at once c ** Calculate Planck functions BPLANK = 0.0 TPLANK = 0.0 CALL ZEROIT( PKAG, MXCLY + 1 ) c ======== BEGIN LOOP TO SUM AZIMUTHAL COMPONENTS OF INTENSITY ======= c (EQ STWJ 5) KCONV = 0 NAZ = NSTR - 1 c ** Azimuth-independent case IF( FBEAM.EQ.0.0 .OR. ( 1.- UMU0 ).LT.1.E-5 .OR. ONLYFL .OR. & ( NUMU.EQ.1 .AND. ( 1.- UMU(1) ).LT.1.E-5 ) ) & NAZ = 0 DO 160 MAZIM = 0, NAZ IF( MAZIM.EQ.0 ) DELM0 = 1.0 IF( MAZIM.GT.0 ) DELM0 = 0.0 c ** Get normalized associated Legendre c polynomials for c (a) incident beam angle cosine c (b) computational and user polar angle c cosines IF( FBEAM.GT.0.0 ) THEN NCOS = 1 ANGCOS = -UMU0 CALL LEPOLY( NCOS, MAZIM, MXCMU, NSTR - 1, [ANGCOS], YLM0 ) END IF IF( .NOT.ONLYFL .AND. USRANG ) & CALL LEPOLY( NUMU, MAZIM, MXCMU, NSTR-1, UMU, YLMU ) CALL LEPOLY( NN, MAZIM, MXCMU, NSTR-1, CMU, YLMC ) c ** Get normalized associated Legendre polys. c with negative arguments from those with c positive arguments; Dave/Armstrong Eq. (15) SGN = - 1.0 DO 50 L = MAZIM, NSTR - 1 SGN = - SGN DO 40 IQ = NN + 1, NSTR YLMC( L, IQ ) = SGN*YLMC( L, IQ - NN ) 40 CONTINUE 50 CONTINUE c ** Specify users bottom reflectivity c and emissivity properties IF ( .NOT.LYRCUT ) $ CALL SURFAC( ALBEDO, DELM0, FBEAM, HLPR, LAMBER, $ MI, MAZIM, MXCMU, MXUMU, NN, NUMU, NSTR, ONLYFL, $ UMU, USRANG, YLM0, YLMC, YLMU, BDR, EMU, BEM, $ RMU ) c =================== BEGIN LOOP ON COMPUTATIONAL LAYERS ============= DO 60 LC = 1, NCUT CALL SOLVEC( AMB, APB, ARRAY, CMU, CWT, GL( 0,LC ), MI, & MAZIM, MXCMU, NN, NSTR, YLM0, YLMC, CC, & EVECC, EVAL, KK( 1,LC ), GC( 1,1,LC ), AAD, EVECCD, & EVALD, WK, WKD, DELM0, FBEAM, IPVT, PI, UMU0, & ZJ, ZZ(1,LC), OPRIM(LC), LC, DITHER, mu2(lc), & glsave, dgl) cgy added glsave and dgl to call to allow adjustable dimensioning 60 CONTINUE c =================== END LOOP ON COMPUTATIONAL LAYERS =============== c ** Set coefficient matrix of equations combining c boundary and layer interface conditions CALL SETMTX( BDR, CBAND, CMU, CWT, DELM0, DTAUCP, GC, KK, & LAMBER, LYRCUT, MI, MI9M2, MXCMU, NCOL, NCUT, & NNLYRI, NN, NSTR, TAUCPR, WK ) c ** Solve for constants of integration in homo- c geneous solution (general boundary conditions) CALL SOLVE0( B, BDR, BEM, BPLANK, CBAND, CMU, CWT, EXPBEA, & FBEAM, FISOT, IPVT, LAMBER, LL, LYRCUT, MAZIM, MI, & MI9M2, MXCMU, NCOL, NCUT, NN, NSTR, NNLYRI, PI, & TPLANK, TAUCPR, UMU0, Z, ZZ, ZPLK0, ZPLK1 ) c ** Compute upward and downward fluxes IF ( MAZIM.EQ.0 ) $ CALL FLUXES( tausla, tauslau, $ CMU, CWT, FBEAM, GC, KK, LAYRU, LL, LYRCUT, $ MAXULV, MXCMU, MXULV, NCUT, NN, NSTR, NTAU, $ PI, PRNT, SSALB, TAUCPR, UMU0, UTAU, UTAUPR, $ XR0, XR1, ZZ, ZPLK0, ZPLK1, DFDT, FLUP, $ FLDN, FLDIR, RFLDIR, RFLDN, UAVG, U0C, $ uavgso, uavgup, uavgdn, $ sindir, sinup, sindn) IF( ONLYFL ) THEN IF( MAXUMU.GE.NSTR ) THEN c ** Save azimuthal-avg intensities c at quadrature angles DO 80 LU = 1, NTAU DO 70 IQ = 1, NSTR U0U( IQ, LU ) = U0C( IQ, LU ) 70 CONTINUE 80 CONTINUE END IF GO TO 170 END IF CALL ZEROIT( UUM, MXUMU*MXULV ) IF( MAZIM.EQ.0 ) THEN c ** Save azimuthally averaged intensities DO 110 LU = 1, NTAU DO 100 IU = 1, NUMU U0U( IU, LU ) = UUM( IU, LU ) DO 90 J = 1, NPHI UU( IU, LU, J ) = UUM( IU, LU ) 90 CONTINUE 100 CONTINUE 110 CONTINUE c ** Print azimuthally averaged intensities c at user angles IF( PRNT( 4 ) ) CALL PRAVIN( UMU, NUMU, MAXUMU, UTAU, NTAU, & U0U ) IF( NAZ.GT.0 ) THEN CALL ZEROIT( PHIRAD, MXPHI ) DO 120 J = 1, NPHI PHIRAD( J ) = RPD*( PHI( J ) - PHI0 ) 120 CONTINUE END IF ELSE c ** Increment intensity by current c azimuthal component (Fourier c cosine series); Eq SD(2) AZERR = 0.0 DO 150 J = 1, NPHI COSPHI = COS( MAZIM*PHIRAD( J ) ) DO 140 LU = 1, NTAU DO 130 IU = 1, NUMU AZTERM = UUM( IU, LU )*COSPHI UU( IU, LU, J ) = UU( IU, LU, J ) + AZTERM AZERR = MAX( AZERR, & RATIO( ABS(AZTERM), ABS(UU(IU,LU,J)) ) ) 130 CONTINUE 140 CONTINUE 150 CONTINUE IF( AZERR.LE.ACCUR ) KCONV = KCONV + 1 IF( KCONV.GE.2 ) GO TO 170 END IF 160 CONTINUE c =================== END LOOP ON AZIMUTHAL COMPONENTS =============== c ** Print intensities 170 CONTINUE IF( PRNT( 5 ) .AND. .NOT.ONLYFL ) CALL PRTINT( UU, UTAU, NTAU, & UMU, NUMU, PHI, NPHI, MAXULV, MAXUMU ) END SUBROUTINE ASYMTX( AA, EVEC, EVAL, M, IA, IEVEC, IER, WKD, AAD, & EVECD, EVALD ) c ======= D O U B L E P R E C I S I O N V E R S I O N ====== c Solves eigenfunction problem for real asymmetric matrix c for which it is known a priori that the eigenvalues are real. c This is an adaptation of a subroutine EIGRF in the IMSL c library to use real instead of complex arithmetic, accounting c for the known fact that the eigenvalues and eigenvectors in c the discrete ordinate solution are real. Other changes include c putting all the called subroutines in-line, deleting the c performance index calculation, updating many DO-loops c to Fortran77, and in calculating the machine precision c TOL instead of specifying it in a data statement. c EIGRF is based primarily on EISPACK routines. The matrix is c first balanced using the Parlett-Reinsch algorithm. Then c the Martin-Wilkinson algorithm is applied. c References: c Dongarra, J. and C. Moler, EISPACK -- A Package for Solving c Matrix Eigenvalue Problems, in Cowell, ed., 1984: c Sources and Development of Mathematical Software, c Prentice-Hall, Englewood Cliffs, NJ c Parlett and Reinsch, 1969: Balancing a Matrix for Calculation c of Eigenvalues and Eigenvectors, Num. Math. 13, 293-304 c Wilkinson, J., 1965: The Algebraic Eigenvalue Problem, c Clarendon Press, Oxford c I N P U T V A R I A B L E S: c AA : input asymmetric matrix, destroyed after solved c M : order of AA c IA : first dimension of AA c IEVEC : first dimension of EVEC c O U T P U T V A R I A B L E S: c EVEC : (unnormalized) eigenvectors of AA c ( column J corresponds to EVAL(J) ) c EVAL : (unordered) eigenvalues of AA ( dimension at least M ) c IER : if .NE. 0, signals that EVAL(IER) failed to converge; c in that case eigenvalues IER+1,IER+2,...,M are c correct but eigenvalues 1,...,IER are set to zero. c S C R A T C H V A R I A B L E S: c WKD : work area ( dimension at least 2*M ) c AAD : double precision stand-in for AA c EVECD : double precision stand-in for EVEC c EVALD : double precision stand-in for EVAL c Called by- SOLEIG c Calls- D1MACH, ERRMSG c +-------------------------------------------------------------------+ c .. Scalar Arguments .. INTEGER IA, IER, IEVEC, M c .. c .. Array Arguments .. REAL AA( IA, M ), EVAL( M ), EVEC( IEVEC, M ) REAL AAD( IA, M ), EVALD( M ), EVECD( IA, M ), & WKD( * ) c .. c .. Local Scalars .. LOGICAL NOCONV, NOTLAS INTEGER I, II, IN, J, K, KA, KKK, L, LB, LLL, N, N1, N2 REAL C1, C2, C3, C4, C5, C6, COL, DISCRI, F, G, H, & ONE, P, Q, R, REPL, RNORM, ROW, S, SCALE, SGN, T, & TOL, UU, VV, W, X, Y, Z, ZERO c .. c .. External Functions .. REAL D1MACH EXTERNAL D1MACH c .. c .. External Subroutines .. EXTERNAL ERRMSG c .. c .. Intrinsic Functions .. INTRINSIC ABS, DBLE, MIN, SIGN, SQRT c .. DATA C1 / 0.4375D0 / , C2 / 0.5D0 / , C3 / 0.75D0 / , & C4 / 0.95D0 / , C5 / 16.D0 / , C6 / 256.D0 / , & ZERO / 0.D0 / , ONE / 1.D0 / IER = 0 TOL = D1MACH( 4 ) IF( M.LT.1 .OR. IA.LT.M .OR. IEVEC.LT.M ) & CALL ERRMSG( 'ASYMTX--bad input variable(s)', .TRUE. ) c ** Handle 1x1 and 2x2 special cases IF( M.EQ.1 ) THEN EVAL( 1 ) = AA( 1, 1 ) EVEC( 1, 1 ) = 1.0 RETURN ELSE IF( M.EQ.2 ) THEN DISCRI = ( AA( 1,1 ) - AA( 2,2 ) )**2 + & 4.*AA( 1, 2 )*AA( 2, 1 ) IF( DISCRI.LT.0.0 ) & CALL ERRMSG( 'ASYMTX--complex evals in 2x2 case',.TRUE. ) SGN = 1.0 IF( AA( 1,1 ).LT.AA( 2,2 ) ) SGN = - 1.0 EVAL( 1 ) = 0.5*( AA( 1,1 ) + AA( 2,2 ) + SGN*SQRT( DISCRI ) ) EVAL( 2 ) = 0.5*( AA( 1,1 ) + AA( 2,2 ) - SGN*SQRT( DISCRI ) ) EVEC( 1, 1 ) = 1.0 EVEC( 2, 2 ) = 1.0 IF( AA( 1,1 ).EQ.AA( 2,2 ) .AND. & ( AA( 2,1 ).EQ.0.0 .OR. AA( 1,2 ).EQ.0.0 ) ) THEN RNORM = ABS( AA( 1,1 ) ) + ABS( AA( 1,2 ) ) + & ABS( AA( 2,1 ) ) + ABS( AA( 2,2 ) ) W = TOL*RNORM EVEC( 2, 1 ) = AA( 2, 1 ) / W EVEC( 1, 2 ) = - AA( 1, 2 ) / W ELSE EVEC( 2, 1 ) = AA( 2, 1 ) / ( EVAL( 1 ) - AA( 2,2 ) ) EVEC( 1, 2 ) = AA( 1, 2 ) / ( EVAL( 2 ) - AA( 1,1 ) ) END IF RETURN END IF c ** Put s.p. matrix into d.p. matrix DO 20 J = 1, M DO 10 K = 1, M AAD( J, K ) = DBLE( AA( J,K ) ) 10 CONTINUE 20 CONTINUE c ** Initialize output variables IER = 0 DO 40 I = 1, M EVALD( I ) = ZERO DO 30 J = 1, M EVECD( I, J ) = ZERO 30 CONTINUE EVECD( I, I ) = ONE 40 CONTINUE c ** Balance the input matrix and reduce its norm by c diagonal similarity transformation stored in WK; c then search for rows isolating an eigenvalue c and push them down RNORM = ZERO L = 1 K = M 50 CONTINUE KKK = K DO 90 J = KKK, 1, -1 ROW = ZERO DO 60 I = 1, K IF( I.NE.J ) ROW = ROW + ABS( AAD( J,I ) ) 60 CONTINUE IF( ROW.EQ.ZERO ) THEN WKD( K ) = J IF( J.NE.K ) THEN DO 70 I = 1, K REPL = AAD( I, J ) AAD( I, J ) = AAD( I, K ) AAD( I, K ) = REPL 70 CONTINUE DO 80 I = L, M REPL = AAD( J, I ) AAD( J, I ) = AAD( K, I ) AAD( K, I ) = REPL 80 CONTINUE END IF K = K - 1 GO TO 50 END IF 90 CONTINUE c ** Search for columns isolating an c eigenvalue and push them left 100 CONTINUE LLL = L DO 140 J = LLL, K COL = ZERO DO 110 I = L, K IF( I.NE.J ) COL = COL + ABS( AAD( I,J ) ) 110 CONTINUE IF( COL.EQ.ZERO ) THEN WKD( L ) = J IF( J.NE.L ) THEN DO 120 I = 1, K REPL = AAD( I, J ) AAD( I, J ) = AAD( I, L ) AAD( I, L ) = REPL 120 CONTINUE DO 130 I = L, M REPL = AAD( J, I ) AAD( J, I ) = AAD( L, I ) AAD( L, I ) = REPL 130 CONTINUE END IF L = L + 1 GO TO 100 END IF 140 CONTINUE c ** Balance the submatrix in rows L through K DO 150 I = L, K WKD( I ) = ONE 150 CONTINUE 160 CONTINUE NOCONV = .FALSE. DO 220 I = L, K COL = ZERO ROW = ZERO DO 170 J = L, K IF( J.NE.I ) THEN COL = COL + ABS( AAD( J,I ) ) ROW = ROW + ABS( AAD( I,J ) ) END IF 170 CONTINUE F = ONE G = ROW / C5 H = COL + ROW 180 CONTINUE IF( COL.LT.G ) THEN F = F*C5 COL = COL*C6 GO TO 180 END IF G = ROW*C5 190 CONTINUE IF( COL.GE.G ) THEN F = F / C5 COL = COL / C6 GO TO 190 END IF c ** Now balance IF( ( COL + ROW ) / F.LT.C4*H ) THEN WKD( I ) = WKD( I )*F NOCONV = .TRUE. DO 200 J = L, M AAD( I, J ) = AAD( I, J ) / F 200 CONTINUE DO 210 J = 1, K AAD( J, I ) = AAD( J, I )*F 210 CONTINUE END IF 220 CONTINUE IF( NOCONV ) GO TO 160 c ** Is A already in Hessenberg form? IF( K-1 .LT. L+1 ) GO TO 370 c ** Transfer A to a Hessenberg form DO 310 N = L + 1, K - 1 H = ZERO WKD( N + M ) = ZERO SCALE = ZERO c ** Scale column DO 230 I = N, K SCALE = SCALE + ABS( AAD( I,N - 1 ) ) 230 CONTINUE IF( SCALE.NE.ZERO ) THEN DO 240 I = K, N, -1 WKD( I + M ) = AAD( I, N - 1 ) / SCALE H = H + WKD( I + M )**2 240 CONTINUE G = - SIGN( SQRT( H ), WKD( N + M ) ) H = H - WKD( N + M )*G WKD( N + M ) = WKD( N + M ) - G c ** Form (I-(U*UT)/H)*A DO 270 J = N, M F = ZERO DO 250 I = K, N, -1 F = F + WKD( I + M )*AAD( I, J ) 250 CONTINUE DO 260 I = N, K AAD( I, J ) = AAD( I, J ) - WKD( I + M )*F / H 260 CONTINUE 270 CONTINUE c ** Form (I-(U*UT)/H)*A*(I-(U*UT)/H) DO 300 I = 1, K F = ZERO DO 280 J = K, N, -1 F = F + WKD( J + M )*AAD( I, J ) 280 CONTINUE DO 290 J = N, K AAD( I, J ) = AAD( I, J ) - WKD( J + M )*F / H 290 CONTINUE 300 CONTINUE WKD( N + M ) = SCALE*WKD( N + M ) AAD( N, N - 1 ) = SCALE*G END IF 310 CONTINUE DO 360 N = K - 2, L, -1 N1 = N + 1 N2 = N + 2 F = AAD( N + 1, N ) IF( F.NE.ZERO ) THEN F = F*WKD( N + 1 + M ) DO 320 I = N + 2, K WKD( I + M ) = AAD( I, N ) 320 CONTINUE IF( N + 1.LE.K ) THEN DO 350 J = 1, M G = ZERO DO 330 I = N + 1, K G = G + WKD( I + M )*EVECD( I, J ) 330 CONTINUE G = G / F DO 340 I = N + 1, K EVECD( I, J ) = EVECD( I, J ) + G*WKD( I + M ) 340 CONTINUE 350 CONTINUE END IF END IF 360 CONTINUE 370 CONTINUE N = 1 DO 390 I = 1, M DO 380 J = N, M RNORM = RNORM + ABS( AAD( I,J ) ) 380 CONTINUE N = I IF( I.LT.L .OR. I.GT.K ) EVALD( I ) = AAD( I, I ) 390 CONTINUE N = K T = ZERO c ** Search for next eigenvalues 400 CONTINUE IF( N.LT.L ) GO TO 550 IN = 0 N1 = N - 1 N2 = N - 2 c ** Look for single small sub-diagonal element 410 CONTINUE DO 420 I = L, N LB = N + L - I IF( LB.EQ.L ) GO TO 430 S = ABS( AAD( LB - 1,LB - 1 ) ) + ABS( AAD( LB,LB ) ) IF( S.EQ.ZERO ) S = RNORM IF( ABS( AAD( LB, LB-1 ) ).LE. TOL*S ) GO TO 430 420 CONTINUE 430 CONTINUE X = AAD( N, N ) IF( LB.EQ.N ) THEN c ** One eigenvalue found AAD( N, N ) = X + T EVALD( N ) = AAD( N, N ) N = N1 GO TO 400 END IF C next line has been included to avoid run time error caused by xlf IF ( ( N1.LE.0 ).OR.( N.LE.0 ) ) THEN WRITE(0,*) 'Subscript out of bounds in ASYMTX' STOP 9999 ENDIF Y = AAD( N1, N1 ) W = AAD( N, N1 )*AAD( N1, N ) IF( LB.EQ.N1 ) THEN c ** Two eigenvalues found P = ( Y - X )*C2 Q = P**2 + W Z = SQRT( ABS( Q ) ) AAD( N, N ) = X + T X = AAD( N, N ) AAD( N1, N1 ) = Y + T c ** Real pair Z = P + SIGN( Z, P ) EVALD( N1 ) = X + Z EVALD( N ) = EVALD( N1 ) IF( Z.NE.ZERO ) EVALD( N ) = X - W / Z X = AAD( N, N1 ) c ** Employ scale factor in case c X and Z are very small R = SQRT( X*X + Z*Z ) P = X / R Q = Z / R c ** Row modification DO 440 J = N1, M Z = AAD( N1, J ) AAD( N1, J ) = Q*Z + P*AAD( N, J ) AAD( N, J ) = Q*AAD( N, J ) - P*Z 440 CONTINUE c ** Column modification DO 450 I = 1, N Z = AAD( I, N1 ) AAD( I, N1 ) = Q*Z + P*AAD( I, N ) AAD( I, N ) = Q*AAD( I, N ) - P*Z 450 CONTINUE c ** Accumulate transformations DO 460 I = L, K Z = EVECD( I, N1 ) EVECD( I, N1 ) = Q*Z + P*EVECD( I, N ) EVECD( I, N ) = Q*EVECD( I, N ) - P*Z 460 CONTINUE N = N2 GO TO 400 END IF IF( IN.EQ.30 ) THEN c ** No convergence after 30 iterations; set error c indicator to the index of the current eigenvalue IER = N GO TO 700 END IF c ** Form shift IF( IN.EQ.10 .OR. IN.EQ.20 ) THEN T = T + X DO 470 I = L, N AAD( I, I ) = AAD( I, I ) - X 470 CONTINUE S = ABS( AAD( N,N1 ) ) + ABS( AAD( N1,N2 ) ) X = C3*S Y = X W = -C1*S**2 END IF IN = IN + 1 c ** Look for two consecutive small sub-diagonal elements C inhibit vectorization by CF77, as this will cause a run time error CDIR$ NEXTSCALAR DO 480 J = LB, N2 I = N2 + LB - J Z = AAD( I, I ) R = X - Z S = Y - Z P = ( R*S - W ) / AAD( I + 1, I ) + AAD( I, I + 1 ) Q = AAD( I + 1, I + 1 ) - Z - R - S R = AAD( I + 2, I + 1 ) S = ABS( P ) + ABS( Q ) + ABS( R ) P = P / S Q = Q / S R = R / S IF( I.EQ.LB ) GO TO 490 UU = ABS( AAD( I, I-1 ) )*( ABS( Q ) + ABS( R ) ) VV = ABS( P ) * ( ABS( AAD( I-1, I-1 ) ) + ABS( Z ) + & ABS( AAD( I+1, I+1 ) ) ) IF( UU .LE. TOL*VV ) GO TO 490 480 CONTINUE 490 CONTINUE AAD( I+2, I ) = ZERO c ** fpp vectorization of this loop triggers c array bounds errors, so inhibit CFPP$ NOVECTOR L DO 500 J = I + 3, N AAD( J, J - 2 ) = ZERO AAD( J, J - 3 ) = ZERO 500 CONTINUE c ** Double QR step involving rows K to N and columns M to N DO 540 KA = I, N1 NOTLAS = KA.NE.N1 IF( KA.EQ.I ) THEN S = SIGN( SQRT( P*P + Q*Q + R*R ), P ) IF( LB.NE.I ) AAD( KA, KA - 1 ) = -AAD( KA, KA - 1 ) ELSE P = AAD( KA, KA - 1 ) Q = AAD( KA + 1, KA - 1 ) R = ZERO IF( NOTLAS ) R = AAD( KA + 2, KA - 1 ) X = ABS( P ) + ABS( Q ) + ABS( R ) IF( X.EQ.ZERO ) GO TO 540 P = P / X Q = Q / X R = R / X S = SIGN( SQRT( P*P + Q*Q + R*R ), P ) AAD( KA, KA - 1 ) = -S*X END IF P = P + S X = P / S Y = Q / S Z = R / S Q = Q / P R = R / P c ** Row modification DO 510 J = KA, M P = AAD( KA, J ) + Q*AAD( KA + 1, J ) IF( NOTLAS ) THEN P = P + R*AAD( KA + 2, J ) AAD( KA + 2, J ) = AAD( KA + 2, J ) - P*Z END IF AAD( KA + 1, J ) = AAD( KA + 1, J ) - P*Y AAD( KA, J ) = AAD( KA, J ) - P*X 510 CONTINUE c ** Column modification DO 520 II = 1, MIN( N, KA + 3 ) P = X*AAD( II, KA ) + Y*AAD( II, KA + 1 ) IF( NOTLAS ) THEN P = P + Z*AAD( II, KA + 2 ) AAD( II, KA + 2 ) = AAD( II, KA + 2 ) - P*R END IF AAD( II, KA + 1 ) = AAD( II, KA + 1 ) - P*Q AAD( II, KA ) = AAD( II, KA ) - P 520 CONTINUE c ** Accumulate transformations DO 530 II = L, K P = X*EVECD( II, KA ) + Y*EVECD( II, KA + 1 ) IF( NOTLAS ) THEN P = P + Z*EVECD( II, KA + 2 ) EVECD( II, KA + 2 ) = EVECD( II, KA + 2 ) - P*R END IF EVECD( II, KA + 1 ) = EVECD( II, KA + 1 ) - P*Q EVECD( II, KA ) = EVECD( II, KA ) - P 530 CONTINUE 540 CONTINUE GO TO 410 c ** All evals found, now backsubstitute real vector 550 CONTINUE IF( RNORM.NE.ZERO ) THEN DO 580 N = M, 1, -1 N2 = N AAD( N, N ) = ONE DO 570 I = N - 1, 1, -1 W = AAD( I, I ) - EVALD( N ) IF( W.EQ.ZERO ) W = TOL*RNORM R = AAD( I, N ) DO 560 J = N2, N - 1 R = R + AAD( I, J )*AAD( J, N ) 560 CONTINUE AAD( I, N ) = -R / W N2 = I 570 CONTINUE 580 CONTINUE c ** End backsubstitution vectors of isolated evals DO 600 I = 1, M IF( I.LT.L .OR. I.GT.K ) THEN DO 590 J = I, M EVECD( I, J ) = AAD( I, J ) 590 CONTINUE END IF 600 CONTINUE c ** Multiply by transformation matrix IF( K.NE.0 ) THEN DO 630 J = M, L, -1 DO 620 I = L, K Z = ZERO DO 610 N = L, MIN( J, K ) Z = Z + EVECD( I, N )*AAD( N, J ) 610 CONTINUE EVECD( I, J ) = Z 620 CONTINUE 630 CONTINUE END IF END IF DO 650 I = L, K DO 640 J = 1, M EVECD( I, J ) = EVECD( I, J )*WKD( I ) 640 CONTINUE 650 CONTINUE c ** Interchange rows if permutations occurred DO 670 I = L-1, 1, -1 J = WKD( I ) IF( I.NE.J ) THEN DO 660 N = 1, M REPL = EVECD( I, N ) EVECD( I, N ) = EVECD( J, N ) EVECD( J, N ) = REPL 660 CONTINUE END IF 670 CONTINUE DO 690 I = K + 1, M J = WKD( I ) IF( I.NE.J ) THEN DO 680 N = 1, M REPL = EVECD( I, N ) EVECD( I, N ) = EVECD( J, N ) EVECD( J, N ) = REPL 680 CONTINUE END IF 690 CONTINUE c ** Put results into output arrays 700 CONTINUE DO 720 J = 1, M EVAL( J ) = EVALD( J ) DO 710 K = 1, M EVEC( J, K ) = EVECD( J, K ) 710 CONTINUE 720 CONTINUE END SUBROUTINE CHEKIN( NLYR, DTAUC, SSALB, PMOM, TEMPER, WVNMLO, & WVNMHI, USRTAU, NTAU, UTAU, NSTR, USRANG, NUMU, & UMU, NPHI, PHI, IBCND, FBEAM, UMU0, PHI0, & FISOT, LAMBER, ALBEDO, HL, BTEMP, TTEMP, TEMIS, & PLANK, ONLYFL, ACCUR, TAUC, MAXCLY, MAXULV, & MAXUMU, MAXCMU, MAXPHI, MXCLY, MXULV, MXUMU, & MXCMU, MXPHI ) c Checks the input dimensions and variables c Calls- WRTBAD, WRTDIM, DREF, ERRMSG c Called by- DISORT c -------------------------------------------------------------------- c .. Scalar Arguments .. LOGICAL LAMBER, ONLYFL, PLANK, USRANG, USRTAU INTEGER IBCND, MAXCLY, MAXCMU, MAXPHI, MAXULV, MAXUMU, MXCLY, & MXCMU, MXPHI, MXULV, MXUMU, NLYR, NPHI, NSTR, NTAU, NUMU REAL ACCUR, ALBEDO, BTEMP, FBEAM, FISOT, PHI0, TEMIS, TTEMP, & UMU0, WVNMHI, WVNMLO c .. c .. Array Arguments .. REAL DTAUC( MAXCLY ), HL( 0:MAXCMU ), PHI( MAXPHI ), & PMOM( 0:MAXCMU, MAXCLY ), SSALB( MAXCLY ), & TAUC( 0:MXCLY ), TEMPER( 0:MAXCLY ), UMU( MAXUMU ), & UTAU( MAXULV ) c .. c .. Local Scalars .. LOGICAL INPERR INTEGER IRMU, IU, J, K, LC, LU REAL FLXALB, RMU c .. c .. External Functions .. LOGICAL WRTBAD, WRTDIM REAL DREF EXTERNAL WRTBAD, WRTDIM, DREF c .. c .. External Subroutines .. EXTERNAL ERRMSG c .. c .. Intrinsic Functions .. INTRINSIC ABS, MOD c .. INPERR = .FALSE. IF( NLYR.LT.1 ) INPERR = WRTBAD( 'NLYR' ) IF( NLYR.GT.MAXCLY ) INPERR = WRTBAD( 'MAXCLY' ) DO 20 LC = 1, NLYR IF( DTAUC( LC ).LT.0.0 ) INPERR = WRTBAD( 'DTAUC' ) IF( SSALB( LC ).LT.0.0 .OR. SSALB( LC ).GT.1.0 ) & INPERR = WRTBAD( 'SSALB' ) IF( PLANK .AND. IBCND.NE.1 ) THEN IF( LC.EQ.1 .AND. TEMPER( 0 ).LT.0.0 ) & INPERR = WRTBAD( 'TEMPER' ) IF( TEMPER( LC ).LT.0.0 ) INPERR = WRTBAD( 'TEMPER' ) END IF DO 10 K = 0, NSTR IF( PMOM( K,LC ).LT.-1.0 .OR. PMOM( K,LC ).GT.1.0 ) & INPERR = WRTBAD( 'PMOM' ) 10 CONTINUE 20 CONTINUE IF( IBCND.EQ.1 ) THEN IF( MAXULV.LT.2 ) INPERR = WRTBAD( 'MAXULV' ) ELSE IF( USRTAU ) THEN IF( NTAU.LT.1 ) INPERR = WRTBAD( 'NTAU' ) IF( MAXULV.LT.NTAU ) INPERR = WRTBAD( 'MAXULV' ) DO 30 LU = 1, NTAU IF( ABS( UTAU( LU ) - TAUC( NLYR ) ).LE. 1.E-4 ) & UTAU( LU ) = TAUC( NLYR ) IF( UTAU( LU ).LT.0.0 .OR. UTAU( LU ).GT. TAUC( NLYR ) ) & INPERR = WRTBAD( 'UTAU' ) 30 CONTINUE ELSE IF( MAXULV.LT.NLYR + 1 ) INPERR = WRTBAD( 'MAXULV' ) END IF IF( NSTR.LT.2 .OR. MOD( NSTR,2 ).NE.0 ) INPERR = WRTBAD( 'NSTR' ) c IF( NSTR.EQ.2 ) c & CALL ERRMSG( 'CHEKIN--2 streams not recommended;'// c & ' use specialized 2-stream code instead',.False.) IF( NSTR.GT.MAXCMU ) INPERR = WRTBAD( 'MAXCMU' ) IF( USRANG ) THEN IF( NUMU.LT.0 ) INPERR = WRTBAD( 'NUMU' ) IF( .NOT.ONLYFL .AND. NUMU.EQ.0 ) INPERR = WRTBAD( 'NUMU' ) IF( NUMU.GT.MAXUMU ) INPERR = WRTBAD( 'MAXUMU' ) IF( IBCND.EQ.1 .AND. 2*NUMU.GT.MAXUMU ) & INPERR = WRTBAD( 'MAXUMU' ) DO 40 IU = 1, NUMU IF( UMU( IU ).LT.-1.0 .OR. UMU( IU ).GT.1.0 .OR. & UMU( IU ).EQ.0.0 ) INPERR = WRTBAD( 'UMU' ) IF( IBCND.EQ.1 .AND. UMU( IU ).LT.0.0 ) & INPERR = WRTBAD( 'UMU' ) IF( IU.GT.1 ) THEN IF( UMU( IU ).LT.UMU( IU-1 ) ) INPERR = WRTBAD( 'UMU' ) END IF 40 CONTINUE ELSE IF( MAXUMU.LT.NSTR ) INPERR = WRTBAD( 'MAXUMU' ) END IF IF( .NOT.ONLYFL .AND. IBCND.NE.1 ) THEN IF( NPHI.LE.0 ) INPERR = WRTBAD( 'NPHI' ) IF( NPHI.GT.MAXPHI ) INPERR = WRTBAD( 'MAXPHI' ) DO 50 J = 1, NPHI IF( PHI( J ).LT.0.0 .OR. PHI( J ).GT.360.0 ) & INPERR = WRTBAD( 'PHI' ) 50 CONTINUE END IF IF( IBCND.LT.0 .OR. IBCND.GT.1 ) INPERR = WRTBAD( 'IBCND' ) IF( IBCND.EQ.0 ) THEN IF( FBEAM.LT.0.0 ) INPERR = WRTBAD( 'FBEAM' ) IF( FBEAM.GT.0.0 .AND. abs(UMU0).GT.1.0 ) & INPERR = WRTBAD( 'UMU0' ) IF( FBEAM.GT.0.0 .AND. ( PHI0.LT.0.0 .OR.PHI0.GT.360.0 ) ) & INPERR = WRTBAD( 'PHI0' ) IF( FISOT.LT.0.0 ) INPERR = WRTBAD( 'FISOT' ) IF( LAMBER ) THEN IF( ALBEDO.LT.0.0 .OR. ALBEDO.GT.1.0 ) & INPERR = WRTBAD( 'ALBEDO' ) ELSE c ** Make sure flux albedo at dense mesh of incident c angles does not assume unphysical values DO 60 IRMU = 0, 100 RMU = IRMU*0.01 FLXALB = DREF( RMU, HL, NSTR ) IF( FLXALB.LT.0.0 .OR. FLXALB.GT.1.0 ) & INPERR = WRTBAD( 'HL' ) 60 CONTINUE END IF ELSE IF( IBCND.EQ.1 ) THEN IF( ALBEDO.LT.0.0 .OR. ALBEDO.GT.1.0 ) & INPERR = WRTBAD( 'ALBEDO' ) END IF IF( PLANK .AND. IBCND.NE.1 ) THEN IF( WVNMLO.LT.0.0 .OR. WVNMHI.LE.WVNMLO ) & INPERR = WRTBAD( 'WVNMLO,HI' ) IF( TEMIS.LT.0.0 .OR. TEMIS.GT.1.0 ) INPERR = WRTBAD( 'TEMIS' ) IF( BTEMP.LT.0.0 ) INPERR = WRTBAD( 'BTEMP' ) IF( TTEMP.LT.0.0 ) INPERR = WRTBAD( 'TTEMP' ) END IF IF( ACCUR.LT.0.0 .OR. ACCUR.GT.1.E-2 ) INPERR = WRTBAD( 'ACCUR' ) IF( MXCLY.LT.NLYR ) INPERR = WRTDIM( 'MXCLY', NLYR ) IF( IBCND.NE.1 ) THEN IF( USRTAU .AND. MXULV.LT.NTAU ) & INPERR = WRTDIM( 'MXULV',NTAU ) IF( .NOT.USRTAU .AND. MXULV .LT. NLYR + 1 ) & INPERR = WRTDIM( 'MXULV', NLYR + 1 ) ELSE IF( MXULV.LT.2 ) INPERR = WRTDIM( 'MXULV', 2 ) END IF IF( MXCMU.LT.NSTR ) INPERR = WRTDIM( 'MXCMU', NSTR ) IF( USRANG .AND. MXUMU.LT.NUMU ) INPERR = WRTDIM( 'MXUMU', NUMU ) IF( USRANG .AND. IBCND.EQ.1 .AND.MXUMU.LT.2*NUMU ) & INPERR = WRTDIM( 'MXUMU', NUMU ) IF( .NOT.USRANG .AND. MXUMU.LT.NSTR ) & INPERR = WRTDIM( 'MXUMU', NSTR ) IF( .NOT.ONLYFL .AND. IBCND.NE.1 .AND. MXPHI.LT.NPHI ) & INPERR = WRTDIM( 'MXPHI', NPHI ) IF( INPERR ) & CALL ERRMSG( 'DISORT--input and/or dimension errors',.True.) IF( PLANK ) THEN DO 70 LC = 1, NLYR IF( ABS( TEMPER( LC ) - TEMPER( LC-1 ) ).GT. 20.0 ) & CALL ERRMSG('CHEKIN--vertical temperature step may' & // ' be too large for good accuracy', & .False.) 70 CONTINUE END IF END SUBROUTINE FLUXES( tausla, tauslau, & CMU, CWT, FBEAM, GC, KK, LAYRU, LL, LYRCUT, & MAXULV, MXCMU, MXULV, NCUT, NN, NSTR, NTAU, PI, & PRNT, SSALB, TAUCPR, UMU0, UTAU, UTAUPR, XR0, & XR1, ZZ, ZPLK0, ZPLK1, DFDT, FLUP, FLDN, FLDIR, & RFLDIR, RFLDN, UAVG, U0C, & uavgso, uavgup, uavgdn, $ sindir, sinup, sindn) c Calculates the radiative fluxes, mean intensity, and flux c derivative with respect to optical depth from the m=0 intensity c components (the azimuthally-averaged intensity) c I N P U T V A R I A B L E S: c CMU : Abscissae for Gauss quadrature over angle cosine c CWT : Weights for Gauss quadrature over angle cosine c GC : Eigenvectors at polar quadrature angles, SC(1) c KK : Eigenvalues of coeff. matrix in Eq. SS(7) c LAYRU : Layer number of user level UTAU c LL : Constants of integration in Eq. SC(1), obtained c by solving scaled version of Eq. SC(5); c exponential term of Eq. SC(12) not included c LYRCUT : Logical flag for truncation of comput. layer c NN : Order of double-Gauss quadrature (NSTR/2) c NCUT : Number of computational layer where absorption c optical depth exceeds ABSCUT c TAUCPR : Cumulative optical depth (delta-M-scaled) c UTAUPR : Optical depths of user output levels in delta-M c coordinates; equal to UTAU if no delta-M c XR0 : Expansion of thermal source function in Eq. SS(14) c XR1 : Expansion of thermal source function Eqs. SS(16) c ZZ : Beam source vectors in Eq. SS(19) c ZPLK0 : Thermal source vectors Z0, by solving Eq. SS(16) c ZPLK1 : Thermal source vectors Z1, by solving Eq. SS(16) c (remainder are DISORT input variables) c O U T P U T V A R I A B L E S: c U0C : Azimuthally averaged intensities c ( at polar quadrature angles ) c (RFLDIR, RFLDN, FLUP, DFDT, UAVG are DISORT output variables) c I N T E R N A L V A R I A B L E S: c DIRINT : Direct intensity attenuated c FDNTOT : Total downward flux (direct + diffuse) c FLDIR : Direct-beam flux (delta-M scaled) c FLDN : Diffuse down-flux (delta-M scaled) c FNET : Net flux (total-down - diffuse-up) c FACT : EXP( - UTAUPR / UMU0 ) c PLSORC : Planck source function (thermal) c ZINT : Intensity of m = 0 case, in Eq. SC(1) c Called by- DISORT c Calls- ZEROIT c +-------------------------------------------------------------------+ c .. Scalar Arguments .. LOGICAL LYRCUT INTEGER MAXULV, MXCMU, MXULV, NCUT, NN, NSTR, NTAU REAL FBEAM, PI, UMU0 c .. c .. Array Arguments .. LOGICAL PRNT( * ) INTEGER LAYRU( MXULV ) REAL CMU( MXCMU ), CWT( MXCMU ), DFDT( MAXULV ), & FLDIR( MXULV ), FLDN( MXULV ), FLUP( MAXULV ), & GC( MXCMU, MXCMU, * ), KK( MXCMU, * ), LL( MXCMU, * ), & RFLDIR( MAXULV ), RFLDN( MAXULV ), SSALB( * ), & TAUCPR( 0:* ), U0C( MXCMU, MXULV ), UAVG( MAXULV ), & UTAU( MAXULV ), UTAUPR( MXULV ), XR0( * ), XR1( * ), & ZPLK0( MXCMU, * ), ZPLK1( MXCMU, * ), ZZ( MXCMU, * ), & uavgso(*),uavgup(*), uavgdn(*), & sindir(*),sinup(*), sindn(*) REAL tausla(0:*), tauslau(0:*) c .. c .. Local Scalars .. INTEGER IQ, JQ, LU, LYU REAL ANG1, ANG2, DIRINT, FACT, FDNTOT, FNET, PLSORC, ZINT c .. c .. External Subroutines .. EXTERNAL ZEROIT c .. c .. Intrinsic Functions .. INTRINSIC ACOS, EXP c .. IF( PRNT( 2 ) ) WRITE( *, 9000 ) c ** Zero DISORT output arrays CALL ZEROIT( U0C, MXULV*MXCMU ) CALL ZEROIT( FLDIR, MXULV ) CALL ZEROIT( FLDN, MXULV ) call zeroit( uavgso, maxulv ) call zeroit( uavgup, maxulv ) call zeroit( uavgdn, maxulv ) call zeroit( sindir, maxulv ) call zeroit( sinup, maxulv ) call zeroit( sindn, maxulv ) c ** Loop over user levels DO 80 LU = 1, NTAU LYU = LAYRU( LU ) IF( LYRCUT .AND. LYU.GT.NCUT ) THEN c ** No radiation reaches c ** this level FDNTOT = 0.0 FNET = 0.0 PLSORC = 0.0 GO TO 70 END IF IF( FBEAM.GT.0.0 ) THEN FACT = EXP( - tausla(LU-1) ) DIRINT = FBEAM*FACT FLDIR( LU ) = UMU0*( FBEAM*FACT ) RFLDIR( LU ) = UMU0*FBEAM * EXP( -tauslau(lu-1) ) sindir( LU ) = SQRT(1.-UMU0*UMU0)*FBEAM * $ EXP( -tauslau(lu-1) ) ELSE DIRINT = 0.0 FLDIR( LU ) = 0.0 RFLDIR( LU ) = 0.0 sindir( LU ) = 0.0 END IF DO 30 IQ = 1, NN ZINT = 0.0 DO 10 JQ = 1, NN ZINT = ZINT + GC( IQ, JQ, LYU )*LL( JQ, LYU )* & EXP( -KK( JQ,LYU )*( UTAUPR( LU ) - & TAUCPR( LYU ) ) ) 10 CONTINUE DO 20 JQ = NN + 1, NSTR ZINT = ZINT + GC( IQ, JQ, LYU )*LL( JQ, LYU )* & EXP( -KK( JQ,LYU )*( UTAUPR( LU ) - & TAUCPR( LYU - 1 ) ) ) 20 CONTINUE U0C( IQ, LU ) = ZINT IF( FBEAM.GT.0.0 ) U0C( IQ, LU ) = ZINT + ZZ( IQ, LYU )*FACT U0C( IQ, LU ) = U0C( IQ, LU ) + ZPLK0( IQ, LYU ) + & ZPLK1( IQ, LYU )*UTAUPR( LU ) UAVG( LU ) = UAVG( LU ) + CWT( NN + 1 - IQ )*U0C( IQ, LU ) uavgdn(lu) = uavgdn(lu) + cwt(nn+1-iq) * u0c( iq,lu ) sindn(lu) = sindn(lu) + cwt(nn+1-iq) * & SQRT(1.-CMU(NN+1-IQ)*CMU(NN+1-IQ))* & U0C( IQ, LU ) FLDN( LU ) = FLDN( LU ) + CWT( NN + 1 - IQ )* & CMU( NN + 1 - IQ )*U0C( IQ, LU ) 30 CONTINUE DO 60 IQ = NN + 1, NSTR ZINT = 0.0 DO 40 JQ = 1, NN ZINT = ZINT + GC( IQ, JQ, LYU )*LL( JQ, LYU )* & EXP( -KK( JQ,LYU )*( UTAUPR( LU ) - & TAUCPR( LYU ) ) ) 40 CONTINUE DO 50 JQ = NN + 1, NSTR ZINT = ZINT + GC( IQ, JQ, LYU )*LL( JQ, LYU )* & EXP( -KK( JQ,LYU )*( UTAUPR( LU ) - & TAUCPR( LYU - 1 ) ) ) 50 CONTINUE U0C( IQ, LU ) = ZINT IF( FBEAM.GT.0.0 ) U0C( IQ, LU ) = ZINT + ZZ( IQ, LYU )*FACT U0C( IQ, LU ) = U0C( IQ, LU ) + ZPLK0( IQ, LYU ) + & ZPLK1( IQ, LYU )*UTAUPR( LU ) UAVG( LU ) = UAVG( LU ) + CWT( IQ - NN )*U0C( IQ, LU ) uavgup(lu) = uavgup(lu) + cwt(iq-nn) * u0c( iq,lu ) sinup (lu) = sinup(lu) + cwt(iq-nn) * & SQRT(1.-CMU(IQ-NN)*CMU(IQ-NN))* & U0C( IQ, LU ) FLUP( LU ) = FLUP( LU ) + CWT( IQ - NN )*CMU( IQ - NN )* & U0C( IQ, LU ) 60 CONTINUE FLUP( LU ) = 2.*PI*FLUP( LU ) FLDN( LU ) = 2.*PI*FLDN( LU ) FDNTOT = FLDN( LU ) + FLDIR( LU ) FNET = FDNTOT - FLUP( LU ) RFLDN( LU ) = FDNTOT - RFLDIR( LU ) UAVG( LU ) = ( 2.*PI*UAVG( LU ) + DIRINT ) / ( 4.*PI ) uavgso( lu ) = dirint / (4.*pi) uavgup( lu ) = (2.0 * pi * uavgup(lu) )/ (4.*pi) uavgdn( lu) = (2.0 * pi * uavgdn(lu) )/ (4.*pi) sindn ( lu ) = 2.*PI*sindn ( LU ) sinup ( lu ) = 2.*PI*sinup ( LU ) PLSORC = XR0( LYU ) + XR1( LYU )*UTAUPR( LU ) DFDT( LU ) = ( 1.- SSALB( LYU ) ) * 4.*PI * & ( UAVG( LU ) - PLSORC ) 70 CONTINUE IF( PRNT( 2 ) ) WRITE( *, FMT = 9010 ) UTAU( LU ), LYU, & RFLDIR( LU ), RFLDN( LU ), FDNTOT, FLUP( LU ), FNET, & UAVG( LU ), PLSORC, DFDT( LU ) 80 CONTINUE IF( PRNT( 3 ) ) THEN WRITE( *, FMT = 9020 ) DO 100 LU = 1, NTAU WRITE( *, FMT = 9030 ) UTAU( LU ) DO 90 IQ = 1, NN ANG1 = 180./ PI* ACOS( CMU( 2*NN - IQ + 1 ) ) ANG2 = 180./ PI* ACOS( CMU( IQ ) ) WRITE( *, 9040 ) ANG1, CMU(2*NN-IQ+1), U0C(IQ,LU), $ ANG2, CMU(IQ), U0C(IQ+NN,LU) 90 CONTINUE 100 CONTINUE END IF 9000 FORMAT( //, 21X, $ '<----------------------- FLUXES ----------------------->', /, $ ' Optical Compu Downward Downward Downward ', $ ' Upward Mean Planck d(Net Flux)', /, $ ' Depth Layer Direct Diffuse Total ', $ 'Diffuse Net Intensity Source / d(Op Dep)', / ) 9010 FORMAT( F10.4, I7, 1P, 7E12.3, E14.3 ) 9020 FORMAT( / , / , ' ******** AZIMUTHALLY AVERAGED INTENSITIES', & ' ( at polar quadrature angles ) *******' ) 9030 FORMAT( /, ' Optical depth =', F10.4, //, $ ' Angle (deg) cos(Angle) Intensity', $ ' Angle (deg) cos(Angle) Intensity' ) 9040 FORMAT( 2( 0P,F16.4,F13.5,1P,E14.3 ) ) END SUBROUTINE LEPOLY( NMU, M, MAXMU, TWONM1, MU, YLM ) c Computes the normalized associated Legendre polynomial, c defined in terms of the associated Legendre polynomial c Plm = P-sub-l-super-m as c Ylm(MU) = sqrt( (l-m)!/(l+m)! ) * Plm(MU) c for fixed order m and all degrees from l = m to TWONM1. c When m.GT.0, assumes that Y-sub(m-1)-super(m-1) is available c from a prior call to the routine. c REFERENCE: Dave, J.V. and B.H. Armstrong, Computations of c High-Order Associated Legendre Polynomials, c J. Quant. Spectrosc. Radiat. Transfer 10, c 557-562, 1970. (hereafter D/A) c METHOD: Varying degree recurrence relationship. c NOTE 1: The D/A formulas are transformed by c setting M = n-1; L = k-1. c NOTE 2: Assumes that routine is called first with M = 0, c then with M = 1, etc. up to M = TWONM1. c NOTE 3: Loops are written in such a way as to vectorize. c I N P U T V A R I A B L E S: c NMU : Number of arguments of YLM c M : Order of YLM c MAXMU : First dimension of YLM c TWONM1 : Max degree of YLM c MU(i) : Arguments of YLM (i = 1 to NMU) c If M.GT.0, YLM(M-1,i) for i = 1 to NMU is assumed to exist c from a prior call. c O U T P U T V A R I A B L E: c YLM(l,i) : l = M to TWONM1, normalized associated Legendre c polynomials evaluated at argument MU(i) c Called by- DISORT, ALBTRN, SURFAC c Calls- ERRMSG c +-------------------------------------------------------------------+ c .. Parameters .. INTEGER MAXSQT PARAMETER ( MAXSQT = 1000 ) c .. c .. Scalar Arguments .. INTEGER M, MAXMU, NMU, TWONM1 c .. c .. Array Arguments .. REAL MU( * ), YLM( 0:MAXMU, * ) c .. c .. Local Scalars .. LOGICAL PASS1 INTEGER I, L, NS REAL TMP1, TMP2 c .. c .. Local Arrays .. REAL SQT( MAXSQT ) c .. c .. External Subroutines .. EXTERNAL ERRMSG c .. c .. Intrinsic Functions .. INTRINSIC FLOAT, SQRT c .. SAVE SQT, PASS1 DATA PASS1 / .TRUE. / IF( PASS1 ) THEN PASS1 = .FALSE. DO 10 NS = 1, MAXSQT SQT( NS ) = SQRT( FLOAT( NS ) ) 10 CONTINUE END IF IF( 2*TWONM1.GT.MAXSQT ) & CALL ERRMSG('LEPOLY--need to increase param MAXSQT',.True.) IF( M.EQ.0 ) THEN c ** Upward recurrence for ordinary c Legendre polynomials DO 20 I = 1, NMU YLM( 0, I ) = 1.0 YLM( 1, I ) = MU( I ) 20 CONTINUE DO 40 L = 2, TWONM1 DO 30 I = 1, NMU YLM( L, I ) = ( ( 2*L - 1 )*MU( I )*YLM( L - 1, I ) - & ( L - 1 )*YLM( L - 2, I ) ) / L 30 CONTINUE 40 CONTINUE ELSE DO 50 I = 1, NMU c ** Y-sub-m-super-m; derived from c ** D/A Eqs. (11,12) YLM( M, I ) = - SQT( 2*M - 1 ) / SQT( 2*M )* & SQRT( 1.- MU(I)**2 )*YLM( M - 1, I ) c ** Y-sub-(m+1)-super-m; derived from c ** D/A Eqs.(13,14) using Eqs.(11,12) YLM( M + 1, I ) = SQT( 2*M + 1 )*MU( I )*YLM( M, I ) 50 CONTINUE c ** Upward recurrence; D/A EQ.(10) DO 70 L = M + 2, TWONM1 TMP1 = SQT( L - M )*SQT( L + M ) TMP2 = SQT( L - M - 1 )*SQT( L + M - 1 ) DO 60 I = 1, NMU YLM( L, I ) = ( ( 2*L - 1 )*MU( I )*YLM( L-1, I ) - & TMP2*YLM( L-2, I ) ) / TMP1 60 CONTINUE 70 CONTINUE END IF END SUBROUTINE PRAVIN( UMU, NUMU, MAXUMU, UTAU, NTAU, U0U ) c Print azimuthally averaged intensities at user angles c Called by- DISORT c LENFMT Max number of polar angle cosines UMU that can be c printed on one line, as set in FORMAT statement c -------------------------------------------------------------------- c .. Scalar Arguments .. INTEGER MAXUMU, NTAU, NUMU c .. c .. Array Arguments .. REAL U0U( MAXUMU, NTAU ), UMU( NUMU ), UTAU( NTAU ) c .. c .. Local Scalars .. INTEGER IU, IUMAX, IUMIN, LENFMT, LU, NP, NPASS c .. c .. Intrinsic Functions .. INTRINSIC MIN c .. IF( NUMU.LT.1 ) RETURN WRITE( *, '(//,A)' ) & ' ******* AZIMUTHALLY AVERAGED INTENSITIES ' // & '(at user polar angles) ********' LENFMT = 8 NPASS = 1 + (NUMU-1) / LENFMT WRITE( *,'(/,A,/,A)') ' Optical Polar Angle Cosines', & ' Depth' DO 20 NP = 1, NPASS IUMIN = 1 + LENFMT * ( NP - 1 ) IUMAX = MIN( LENFMT*NP, NUMU ) WRITE( *,'(/,10X,8F14.5)') ( UMU(IU), IU = IUMIN, IUMAX ) DO 10 LU = 1, NTAU WRITE( *, '(0P,F10.4,1P,8E14.4)' ) UTAU( LU ), & ( U0U( IU,LU ), IU = IUMIN, IUMAX ) 10 CONTINUE 20 CONTINUE END SUBROUTINE PRTINP( NLYR, DTAUC, DTAUCP, SSALB, PMOM, TEMPER, & WVNMLO, WVNMHI, NTAU, UTAU, NSTR, NUMU, UMU, & NPHI, PHI, IBCND, FBEAM, UMU0, PHI0, FISOT, & LAMBER, ALBEDO, HL, BTEMP, TTEMP, TEMIS, & DELTAM, PLANK, ONLYFL, ACCUR, FLYR, LYRCUT, & OPRIM, TAUC, TAUCPR, MAXCMU, PRTMOM ) c Print values of input variables c Called by- DISORT c -------------------------------------------------------------------- c .. Scalar Arguments .. LOGICAL DELTAM, LAMBER, LYRCUT, ONLYFL, PLANK, PRTMOM INTEGER IBCND, MAXCMU, NLYR, NPHI, NSTR, NTAU, NUMU REAL ACCUR, ALBEDO, BTEMP, FBEAM, FISOT, PHI0, TEMIS, TTEMP, & UMU0, WVNMHI, WVNMLO c .. c .. Array Arguments .. REAL DTAUC( * ), DTAUCP( * ), FLYR( * ), HL( 0:MAXCMU ), & OPRIM( * ), PHI( * ), PMOM( 0:MAXCMU, * ), SSALB( * ), & TAUC( 0:* ), TAUCPR( 0:* ), TEMPER( 0:* ), UMU( * ), & UTAU( * ) c .. c .. Local Scalars .. INTEGER IU, J, K, LC, LU REAL YESSCT c .. WRITE( *, '(/,A,I4,A,I4)' ) ' No. streams =', NSTR, & ' No. computational layers =', NLYR IF( IBCND.NE.1 ) WRITE( *, '(I4,A,10F10.4,/,(26X,10F10.4))' ) & NTAU,' User optical depths :', ( UTAU(LU), LU = 1, NTAU ) IF( .NOT.ONLYFL ) WRITE( *, '(I4,A,10F9.5,/,(31X,10F9.5))' ) & NUMU,' User polar angle cosines :',( UMU(IU), IU = 1, NUMU ) IF( .NOT.ONLYFL .AND. IBCND.NE.1 ) & WRITE( *, '(I4,A,10F9.2,/,(28X,10F9.2))' ) & NPHI,' User azimuthal angles :',( PHI(J), J = 1, NPHI ) IF( .NOT.PLANK .OR. IBCND.EQ.1 ) & WRITE( *, '(A)' ) ' No thermal emission' WRITE( *, '(A,I2)' ) ' Boundary condition flag: IBCND =', IBCND IF( IBCND.EQ.0 ) THEN WRITE( *, '(A,1P,E11.3,A,0P,F8.5,A,F7.2,/,A,1P,E11.3)' ) & ' Incident beam with intensity =', FBEAM, & ' and polar angle cosine = ', UMU0, & ' and azimuth angle =', PHI0, & ' plus isotropic incident intensity =', FISOT IF( LAMBER ) WRITE( *, '(A,0P,F8.4)' ) & ' Bottom albedo (Lambertian) =', ALBEDO IF( .NOT.LAMBER ) WRITE( *, '(A,/,(10X,10F9.5))' ) & ' Legendre coeffs of bottom bidirectional reflectivity :', & ( HL( K ), K = 0, NSTR ) IF( PLANK ) WRITE( *, '(A,2F14.4,/,A,F10.2,A,F10.2,A,F8.4)' ) & ' Thermal emission in wavenumber interval :', WVNMLO, & WVNMHI, & ' Bottom temperature =', BTEMP, & ' Top temperature =', TTEMP, & ' Top emissivity =',TEMIS ELSE IF( IBCND.EQ.1 ) THEN WRITE(*,'(A)') ' Isotropic illumination from top and bottom' WRITE( *, '(A,0P,F8.4)' ) & ' Bottom albedo (Lambertian) =', ALBEDO END IF IF( DELTAM ) WRITE( *, '(A)' ) ' Uses delta-M method' IF( .NOT.DELTAM ) WRITE( *, '(A)' ) ' Does not use delta-M method' IF( IBCND.EQ.1 ) THEN WRITE( *, '(A)' ) ' Calculate albedo and transmissivity of'// & ' medium vs. incident beam angle' ELSE IF( ONLYFL ) THEN WRITE( *, '(A)' ) & ' Calculate fluxes and azim-averaged intensities only' ELSE WRITE( *, '(A)' ) ' Calculate fluxes and intensities' END IF WRITE( *, '(A,1P,E11.2)' ) & ' Relative convergence criterion for azimuth series =', & ACCUR IF( LYRCUT ) WRITE( *, '(A)' ) & ' Sets radiation = 0 below absorption optical depth 10' c ** Print layer variables IF( PLANK ) WRITE( *, FMT = 9180 ) IF( .NOT.PLANK ) WRITE( *, FMT = 9190 ) YESSCT = 0.0 DO 10 LC = 1, NLYR YESSCT = YESSCT + SSALB( LC ) IF( PLANK ) & WRITE(*,'(I4,2F10.4,F10.5,F12.5,2F10.4,F10.5,F9.4,F14.3)') & LC, DTAUC( LC ), TAUC( LC ), SSALB( LC ), FLYR( LC ), & DTAUCP( LC ), TAUCPR( LC ), OPRIM( LC ), PMOM(1,LC), & TEMPER( LC-1 ) IF( .NOT.PLANK ) & WRITE(*,'(I4,2F10.4,F10.5,F12.5,2F10.4,F10.5,F9.4)') & LC, DTAUC( LC ), TAUC( LC ), SSALB( LC ), FLYR( LC ), & DTAUCP( LC ), TAUCPR( LC ), OPRIM( LC ), PMOM( 1,LC ) 10 CONTINUE IF( PLANK ) WRITE( *, '(85X,F14.3)' ) TEMPER( NLYR ) IF( PRTMOM .AND. YESSCT.GT.0.0 ) THEN WRITE( *, '(/,A)' ) ' Layer Phase Function Moments' DO 20 LC = 1, NLYR IF( SSALB( LC ).GT.0.0 ) & WRITE( *, '(I6,10F11.6,/,(6X,10F11.6))' ) & LC, ( PMOM( K, LC ), K = 0, NSTR ) 20 CONTINUE END IF c ** (Read every other line in these formats) 9180 FORMAT( /, 37X, '<------------- Delta-M --------------->', /, &' Total Single ', & 'Total Single', /, &' Optical Optical Scatter Truncated ', & 'Optical Optical Scatter Asymm', /, &' Depth Depth Albedo Fraction ', & 'Depth Depth Albedo Factor Temperature' ) 9190 FORMAT( /, 37X, '<------------- Delta-M --------------->', /, &' Total Single ', & 'Total Single', /, &' Optical Optical Scatter Truncated ', & 'Optical Optical Scatter Asymm', /, &' Depth Depth Albedo Fraction ', & 'Depth Depth Albedo Factor' ) END SUBROUTINE PRTINT( UU, UTAU, NTAU, UMU, NUMU, PHI, NPHI, MAXULV, & MAXUMU ) c Prints the intensity at user polar and azimuthal angles c All arguments are DISORT input or output variables c Called by- DISORT c LENFMT Max number of azimuth angles PHI that can be printed c on one line, as set in FORMAT statement c +-------------------------------------------------------------------+ c .. Scalar Arguments .. INTEGER MAXULV, MAXUMU, NPHI, NTAU, NUMU c .. c .. Array Arguments .. REAL PHI( * ), UMU( * ), UTAU( * ), UU( MAXUMU, MAXULV, * ) c .. c .. Local Scalars .. INTEGER IU, J, JMAX, JMIN, LENFMT, LU, NP, NPASS c .. c .. Intrinsic Functions .. INTRINSIC MIN c .. IF( NPHI.LT.1 ) RETURN WRITE( *, '(//,A)' ) & ' ********* I N T E N S I T I E S *********' LENFMT = 10 NPASS = 1 + (NPHI-1) / LENFMT WRITE( *, '(/,A,/,A,/,A)' ) & ' Polar Azimuth angles (degrees)', & ' Optical Angle', & ' Depth Cosine' DO 30 LU = 1, NTAU DO 20 NP = 1, NPASS JMIN = 1 + LENFMT * ( NP - 1 ) JMAX = MIN( LENFMT*NP, NPHI ) WRITE( *, '(/,18X,10F11.2)' ) ( PHI(J), J = JMIN, JMAX ) IF( NP.EQ.1 ) WRITE( *, '(F10.4,F8.4,1P,10E11.3)' ) & UTAU(LU), UMU(1), (UU(1, LU, J), J = JMIN, JMAX) IF( NP.GT.1 ) WRITE( *, '(10X,F8.4,1P,10E11.3)' ) & UMU(1), (UU(1, LU, J), J = JMIN, JMAX) DO 10 IU = 2, NUMU WRITE( *, '(10X,F8.4,1P,10E11.3)' ) & UMU( IU ), ( UU( IU, LU, J ), J = JMIN, JMAX ) 10 CONTINUE 20 CONTINUE 30 CONTINUE END SUBROUTINE QGAUSN( M, GMU, GWT ) c Compute weights and abscissae for ordinary Gaussian quadrature c on the interval (0,1); that is, such that c sum(i=1 to M) ( GWT(i) f(GMU(i)) ) c is a good approximation to c integral(0 to 1) ( f(x) dx ) c INPUT : M order of quadrature rule c OUTPUT : GMU(I) array of abscissae (I = 1 TO M) c GWT(I) array of weights (I = 1 TO M) c REFERENCE: Davis, P.J. and P. Rabinowitz, Methods of Numerical c Integration, Academic Press, New York, pp. 87, 1975 c METHOD: Compute the abscissae as roots of the Legendre c polynomial P-sub-M using a cubically convergent c refinement of Newton's method. Compute the c weights from EQ. 2.7.3.8 of Davis/Rabinowitz. Note c that Newton's method can very easily diverge; only a c very good initial guess can guarantee convergence. c The initial guess used here has never led to divergence c even for M up to 1000. c ACCURACY: relative error no better than TOL or computer c precision (machine epsilon), whichever is larger c INTERNAL VARIABLES: c ITER : number of Newton Method iterations c MAXIT : maximum allowed iterations of Newton Method c PM2,PM1,P : 3 successive Legendre polynomials c PPR : derivative of Legendre polynomial c P2PRI : 2nd derivative of Legendre polynomial c TOL : convergence criterion for Legendre poly root iteration c X,XI : successive iterates in cubically-convergent version c of Newtons Method (seeking roots of Legendre poly.) c Called by- SETDIS, SURFAC c Calls- D1MACH, ERRMSG c +-------------------------------------------------------------------+ c .. Scalar Arguments .. INTEGER M c .. c .. Array Arguments .. REAL GMU( M ), GWT( M ) c .. c .. Local Scalars .. INTEGER ITER, K, LIM, MAXIT, NN, NP1 REAL CONA, PI, T REAL(kind(0.0d0)) :: EN, NNP1, ONE, P, P2PRI, PM1, PM2, PPR, & PROD, TMP, TOL, TWO, X, XI c .. c .. External Functions .. REAL(kind(0.0d0)) :: D1MACH EXTERNAL D1MACH c .. c .. External Subroutines .. EXTERNAL ERRMSG c .. c .. Intrinsic Functions .. INTRINSIC ABS, ASIN, COS, FLOAT, MOD, TAN c .. SAVE PI, TOL DATA PI / 0.0 / , MAXIT / 1000 / , ONE / 1.D0 / , & TWO / 2.D0 / IF( PI.EQ.0.0 ) THEN PI = 2.*ASIN( 1.0 ) TOL = 10.*D1MACH( 4 ) END IF IF( M.LT.1 ) CALL ERRMSG( 'QGAUSN--Bad value of M',.True.) IF( M.EQ.1 ) THEN GMU( 1 ) = 0.5 GWT( 1 ) = 1.0 RETURN END IF EN = M NP1 = M + 1 NNP1 = M*NP1 CONA = FLOAT( M - 1 ) / ( 8*M**3 ) LIM = M / 2 DO 30 K = 1, LIM c ** Initial guess for k-th root c of Legendre polynomial, from c Davis/Rabinowitz (2.7.3.3a) T = ( 4*K - 1 )*PI / ( 4*M + 2 ) X = COS( T + CONA / TAN( T ) ) ITER = 0 c ** Upward recurrence for c Legendre polynomials 10 CONTINUE ITER = ITER + 1 PM2 = ONE PM1 = X DO 20 NN = 2, M P = ( ( 2*NN - 1 )*X*PM1 - ( NN - 1 )*PM2 ) / NN PM2 = PM1 PM1 = P 20 CONTINUE c ** Newton Method TMP = ONE / ( ONE - X**2 ) PPR = EN*( PM2 - X*P )*TMP P2PRI = ( TWO*X*PPR - NNP1*P )*TMP XI = X - ( P / PPR )*( ONE + & ( P / PPR )*P2PRI / ( TWO*PPR ) ) c ** Check for convergence IF( ABS( XI - X ).GT.TOL ) THEN IF( ITER.GT.MAXIT ) & CALL ERRMSG( 'QGAUSN--max iteration count',.True.) X = XI GO TO 10 END IF c ** Iteration finished--calculate weights, c abscissae for (-1,1) GMU( K ) = -X GWT( K ) = TWO / ( TMP*( EN*PM2 )**2 ) GMU( NP1 - K ) = -GMU( K ) GWT( NP1 - K ) = GWT( K ) 30 CONTINUE c ** Set middle abscissa and weight c for rules of odd order IF( MOD( M,2 ).NE.0 ) THEN GMU( LIM + 1 ) = 0.0 PROD = ONE DO 40 K = 3, M, 2 PROD = PROD * K / ( K - 1 ) 40 CONTINUE GWT( LIM + 1 ) = TWO / PROD**2 END IF c ** Convert from (-1,1) to (0,1) DO 50 K = 1, M GMU( K ) = 0.5*GMU( K ) + 0.5 GWT( K ) = 0.5*GWT( K ) 50 CONTINUE END SUBROUTINE SETDIS( dsdh, nid, tausla, tauslau, mu2, & CMU, CWT, DELTAM, DTAUC, DTAUCP, EXPBEA, FBEAM, & FLYR, GL, HL, HLPR, IBCND, LAMBER, LAYRU, & LYRCUT, MAXUMU, MAXCMU, MXCMU, NCUT, NLYR, & NTAU, NN, NSTR, PLANK, NUMU, ONLYFL, OPRIM, & PMOM, SSALB, TAUC, TAUCPR, UTAU, UTAUPR, UMU, & UMU0, USRTAU, USRANG, kout ) c Perform miscellaneous setting-up operations c INPUT : all are DISORT input variables (see DOC file) c OUTPUT: NTAU,UTAU if USRTAU = FALSE c NUMU,UMU if USRANG = FALSE c CMU,CWT computational polar angles and c corresponding quadrature weights c EXPBEA transmission of direct beam c FLYR truncated fraction in delta-M method c GL phase function Legendre coefficients multi- c plied by (2L+1) and single-scatter albedo c HLPR Legendre moments of surface bidirectional c reflectivity, times 2K+1 c LAYRU Computational layer in which UTAU falls c LYRCUT flag as to whether radiation will be zeroed c below layer NCUT c NCUT computational layer where absorption c optical depth first exceeds ABSCUT c NN NSTR / 2 c OPRIM delta-M-scaled single-scatter albedo c TAUCPR delta-M-scaled optical depth c UTAUPR delta-M-scaled version of UTAU c Called by- DISORT c Calls- QGAUSN, ERRMSG c ---------------------------------------------------------------------- c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) c .. Scalar Arguments .. LOGICAL DELTAM, LAMBER, LYRCUT, ONLYFL, PLANK, USRANG, USRTAU INTEGER IBCND, MAXCMU, MAXUMU, MXCMU, NCUT, NLYR, NN, NSTR, & NTAU, NUMU REAL FBEAM, UMU0 c geometry REAL dsdh(0:kz,kz) INTEGER nid(0:kz) REAL tausla(0:kz), tauslau(0:kz), mu2(0:kz) REAL sum, sumu c .. c .. Array Arguments .. INTEGER LAYRU( * ) REAL CMU( MXCMU ), CWT( MXCMU ), DTAUC( * ), DTAUCP( * ), & EXPBEA( 0:* ), FLYR( * ), GL( 0:MXCMU, * ), & HL( 0:MAXCMU ), HLPR( 0:MXCMU ), OPRIM( * ), & PMOM( 0:MAXCMU, * ), SSALB( * ), TAUC( 0:* ), & TAUCPR( 0:* ), UMU( MAXUMU ), UTAU( * ), UTAUPR( * ) c .. c .. Local Scalars .. INTEGER IQ, IU, K, LC, LU REAL ABSCUT, ABSTAU, F REAL R1MACH EXTERNAL R1MACH c .. c .. External Subroutines .. EXTERNAL ERRMSG, QGAUSN c .. c .. Intrinsic Functions .. INTRINSIC ABS, EXP c .. DATA ABSCUT / 10. / IF( .NOT.USRTAU ) THEN c ** Set output levels at computational c layer boundaries NTAU = NLYR + 1 DO 10 LC = 0, NTAU - 1 UTAU( LC + 1 ) = TAUC( LC ) 10 CONTINUE END IF c ** Apply delta-M scaling and move description c of computational layers to local variables EXPBEA( 0 ) = 1.0 TAUCPR( 0 ) = 0.0 ABSTAU = 0.0 do i = 0, kz tausla( i ) = 0.0 tauslau( i ) = 0.0 mu2(i) = 1./largest end do DO 40 LC = 1, NLYR PMOM( 0, LC ) = 1.0 IF( ABSTAU.LT.ABSCUT ) NCUT = LC ABSTAU = ABSTAU + ( 1.- SSALB( LC ) )*DTAUC( LC ) IF( .NOT.DELTAM ) THEN OPRIM( LC ) = SSALB( LC ) DTAUCP( LC ) = DTAUC( LC ) TAUCPR( LC ) = TAUC( LC ) DO 20 K = 0, NSTR - 1 GL( K, LC ) = ( 2*K + 1 )*OPRIM( LC )*PMOM( K, LC ) 20 CONTINUE F = 0.0 ELSE c ** Do delta-M transformation F = PMOM( NSTR, LC ) OPRIM(LC) = SSALB(LC) * ( 1.- F ) / ( 1.- F * SSALB(LC) ) DTAUCP( LC ) = ( 1.- F*SSALB( LC ) )*DTAUC( LC ) TAUCPR( LC ) = TAUCPR( LC-1 ) + DTAUCP( LC ) DO 30 K = 0, NSTR - 1 GL( K, LC ) = ( 2*K + 1 ) * OPRIM( LC ) * & ( PMOM( K,LC ) - F ) / ( 1.- F ) 30 CONTINUE END IF FLYR( LC ) = F EXPBEA( LC ) = 0.0 40 CONTINUE c * calculate slant optical depth * IF(umu0 .LT. 0.0) THEN IF(nid(0) .LT. 0) THEN tausla(0) = largest tauslau(0) = largest ELSE sum = 0.0 sumu = 0.0 DO lc = 1, nid(0) sum = sum + 2.*dtaucp(lc)*dsdh(0,lc) sumu = sumu + 2.*dtauc(lc)*dsdh(0,lc) END DO tausla(0) = sum tauslau(0) = sumu END IF END IF expbea( 0 ) = EXP( -tausla( 0 ) ) * DO 41, lc = 1, nlyr IF(nid(lc) .LT. 0) THEN tausla(lc) = largest tauslau(lc) = largest ELSE sum = 0.0 sumu = 0.0 DO lu = 1, MIN(nid(lc),lc) sum = sum + dtaucp(lu)*dsdh(lc,lu) sumu = sumu + dtauc(lu)*dsdh(lc,lu) ENDDO DO lu = MIN(nid(lc),lc)+1,nid(lc) sum = sum + 2.*dtaucp(lu)*dsdh(lc,lu) sumu = sumu + 2.*dtauc(lu)*dsdh(lc,lu) ENDDO tausla(lc) = sum tauslau(lc) = sumu IF(tausla(lc) .EQ. tausla(lc-1)) THEN mu2(lc) = largest ELSE mu2(lc) = (taucpr(lc)-taucpr(lc-1)) $ /(tausla(lc)-tausla(lc-1)) mu2(lc) = SIGN( AMAX1(ABS(mu2(lc)),1./largest), $ mu2(lc) ) END IF END IF expbea(lc) = EXP( -tausla( lc ) ) 41 CONTINUE c ** If no thermal emission, cut off medium below c absorption optical depth = ABSCUT ( note that c delta-M transformation leaves absorption c optical depth invariant ). Not worth the c trouble for one-layer problems, though. LYRCUT = .FALSE. IF( ABSTAU.GE.ABSCUT .AND. .NOT.PLANK .AND. IBCND.NE.1 .AND. & NLYR.GT.1 ) LYRCUT = .TRUE. IF( .NOT.LYRCUT ) NCUT = NLYR c ** Set arrays defining location of user c ** output levels within delta-M-scaled c ** computational mesh DO 70 LU = 1, NTAU DO 50 LC = 1, NLYR IF( UTAU( LU ).GE.TAUC( LC - 1 ) .AND. & UTAU( LU ).LE.TAUC( LC ) ) GO TO 60 50 CONTINUE LC = NLYR 60 CONTINUE UTAUPR( LU ) = UTAU( LU ) IF( DELTAM ) UTAUPR( LU ) = TAUCPR( LC - 1 ) + & ( 1.- SSALB( LC )*FLYR( LC ) )* & ( UTAU( LU ) - TAUC( LC-1 ) ) LAYRU( LU ) = LC 70 CONTINUE c ** Calculate computational polar angle cosines c and associated quadrature weights for Gaussian c quadrature on the interval (0,1) (upward) NN = NSTR / 2 CALL QGAUSN( NN, CMU, CWT ) c ** Downward (neg) angles and weights DO 80 IQ = 1, NN CMU( IQ + NN ) = - CMU( IQ ) CWT( IQ + NN ) = CWT( IQ ) 80 CONTINUE c IF( FBEAM.GT.0.0 ) THEN c ** Compare beam angle to comput. angles DO 90 IQ = 1, NN C ** Dither mu2 if it is close to one of the C quadrature angles. DO lc = 1, nlyr IF ( ABS(mu2(lc)) .lt. 1.E5 ) THEN IF( ABS( 1. - ABS(mu2(lc))/CMU( IQ ) ) .LT. 0.05 ) & mu2(lc) = mu2(lc)*0.999 ENDIF END DO 90 CONTINUE c END IF IF( .NOT.USRANG .OR. ( ONLYFL .AND. MAXUMU.GE.NSTR ) ) THEN c ** Set output polar angles to c computational polar angles NUMU = NSTR DO 100 IU = 1, NN UMU( IU ) = - CMU( NN + 1 - IU ) 100 CONTINUE DO 110 IU = NN + 1, NSTR UMU( IU ) = CMU( IU - NN ) 110 CONTINUE END IF IF( USRANG .AND. IBCND.EQ.1 ) THEN c ** Shift positive user angle cosines to c upper locations and put negatives c in lower locations DO 120 IU = 1, NUMU UMU( IU + NUMU ) = UMU( IU ) 120 CONTINUE DO 130 IU = 1, NUMU UMU( IU ) = -UMU( 2*NUMU + 1 - IU ) 130 CONTINUE NUMU = 2*NUMU END IF IF( .NOT.LYRCUT .AND. .NOT.LAMBER ) THEN DO 140 K = 0, NSTR HLPR( K ) = ( 2*K + 1 )*HL( K ) 140 CONTINUE END IF END SUBROUTINE SETMTX( BDR, CBAND, CMU, CWT, DELM0, DTAUCP, GC, KK, & LAMBER, LYRCUT, MI, MI9M2, MXCMU, NCOL, NCUT, & NNLYRI, NN, NSTR, TAUCPR, WK ) c Calculate coefficient matrix for the set of equations c obtained from the boundary conditions and the continuity- c of-intensity-at-layer-interface equations; store in the c special banded-matrix format required by LINPACK routines c I N P U T V A R I A B L E S: c BDR : Surface bidirectional reflectivity c CMU : Abscissae for Gauss quadrature over angle cosine c CWT : Weights for Gauss quadrature over angle cosine c DELM0 : Kronecker delta, delta-sub-m0 c GC : Eigenvectors at polar quadrature angles, SC(1) c KK : Eigenvalues of coeff. matrix in Eq. SS(7) c LYRCUT : Logical flag for truncation of comput. layer c NN : Number of streams in a hemisphere (NSTR/2) c NCUT : Total number of computational layers considered c TAUCPR : Cumulative optical depth (delta-M-scaled) c (remainder are DISORT input variables) c O U T P U T V A R I A B L E S: c CBAND : Left-hand side matrix of linear system Eq. SC(5), c scaled by Eq. SC(12); in banded form required c by LINPACK solution routines c NCOL : Counts of columns in CBAND c I N T E R N A L V A R I A B L E S: c IROW : Points to row in CBAND c JCOL : Points to position in layer block c LDA : Row dimension of CBAND c NCD : Number of diagonals below or above main diagonal c NSHIFT : For positioning number of rows in band storage c WK : Temporary storage for EXP evaluations c Called by- DISORT, ALBTRN c Calls- ZEROIT c +--------------------------------------------------------------------+ c .. Scalar Arguments .. LOGICAL LAMBER, LYRCUT INTEGER MI, MI9M2, MXCMU, NCOL, NCUT, NN, NNLYRI, NSTR REAL DELM0 c .. c .. Array Arguments .. REAL BDR( MI, 0:MI ), CBAND( MI9M2, NNLYRI ), CMU( MXCMU ), & CWT( MXCMU ), DTAUCP( * ), GC( MXCMU, MXCMU, * ), & KK( MXCMU, * ), TAUCPR( 0:* ), WK( MXCMU ) c .. c .. Local Scalars .. INTEGER IQ, IROW, JCOL, JQ, K, LC, LDA, NCD, NNCOL, NSHIFT REAL EXPA, SUM c .. c .. External Subroutines .. EXTERNAL ZEROIT c .. c .. Intrinsic Functions .. INTRINSIC EXP c .. CALL ZEROIT( CBAND, MI9M2*NNLYRI ) NCD = 3*NN - 1 LDA = 3*NCD + 1 NSHIFT = LDA - 2*NSTR + 1 NCOL = 0 c ** Use continuity conditions of Eq. STWJ(17) c to form coefficient matrix in STWJ(20); c employ scaling transformation STWJ(22) DO 60 LC = 1, NCUT DO 10 IQ = 1, NN WK( IQ ) = EXP( KK( IQ,LC )*DTAUCP( LC ) ) 10 CONTINUE JCOL = 0 DO 30 IQ = 1, NN NCOL = NCOL + 1 IROW = NSHIFT - JCOL DO 20 JQ = 1, NSTR CBAND( IROW + NSTR, NCOL ) = GC( JQ, IQ, LC ) CBAND( IROW, NCOL ) = - GC( JQ, IQ, LC )*WK( IQ ) IROW = IROW + 1 20 CONTINUE JCOL = JCOL + 1 30 CONTINUE DO 50 IQ = NN + 1, NSTR NCOL = NCOL + 1 IROW = NSHIFT - JCOL DO 40 JQ = 1, NSTR CBAND( IROW + NSTR, NCOL ) = GC( JQ, IQ, LC )* & WK( NSTR + 1 - IQ ) CBAND( IROW, NCOL ) = - GC( JQ, IQ, LC ) IROW = IROW + 1 40 CONTINUE JCOL = JCOL + 1 50 CONTINUE 60 CONTINUE c ** Use top boundary condition of STWJ(20a) for c first layer JCOL = 0 DO 80 IQ = 1, NN EXPA = EXP( KK( IQ,1 )*TAUCPR( 1 ) ) IROW = NSHIFT - JCOL + NN DO 70 JQ = NN, 1, -1 CBAND( IROW, JCOL + 1 ) = GC( JQ, IQ, 1 )*EXPA IROW = IROW + 1 70 CONTINUE JCOL = JCOL + 1 80 CONTINUE DO 100 IQ = NN + 1, NSTR IROW = NSHIFT - JCOL + NN DO 90 JQ = NN, 1, -1 CBAND( IROW, JCOL + 1 ) = GC( JQ, IQ, 1 ) IROW = IROW + 1 90 CONTINUE JCOL = JCOL + 1 100 CONTINUE c ** Use bottom boundary condition of c STWJ(20c) for last layer NNCOL = NCOL - NSTR JCOL = 0 DO 130 IQ = 1, NN NNCOL = NNCOL + 1 IROW = NSHIFT - JCOL + NSTR DO 120 JQ = NN + 1, NSTR IF( LYRCUT .OR. ( LAMBER .AND. DELM0.EQ.0 ) ) THEN c ** No azimuthal-dependent intensity if Lam- c bert surface; no intensity component if c truncated bottom layer CBAND( IROW, NNCOL ) = GC( JQ, IQ, NCUT ) ELSE SUM = 0.0 DO 110 K = 1, NN SUM = SUM + CWT( K )*CMU( K )*BDR( JQ - NN, K )* & GC( NN + 1 - K, IQ, NCUT ) 110 CONTINUE CBAND( IROW, NNCOL ) = GC( JQ, IQ, NCUT ) - & ( 1.+ DELM0 )*SUM END IF IROW = IROW + 1 120 CONTINUE JCOL = JCOL + 1 130 CONTINUE DO 160 IQ = NN + 1, NSTR NNCOL = NNCOL + 1 IROW = NSHIFT - JCOL + NSTR EXPA = WK( NSTR + 1 - IQ ) DO 150 JQ = NN + 1, NSTR IF( LYRCUT .OR. ( LAMBER .AND. DELM0.EQ.0 ) ) THEN CBAND( IROW, NNCOL ) = GC( JQ, IQ, NCUT )*EXPA ELSE SUM = 0.0 DO 140 K = 1, NN SUM = SUM + CWT( K )*CMU( K )*BDR( JQ - NN, K )* & GC( NN + 1 - K, IQ, NCUT ) 140 CONTINUE CBAND( IROW, NNCOL ) = ( GC( JQ,IQ,NCUT ) - & ( 1.+ DELM0 )*SUM )*EXPA END IF IROW = IROW + 1 150 CONTINUE JCOL = JCOL + 1 160 CONTINUE END SUBROUTINE SOLEIG( AMB, APB, ARRAY, CMU, CWT, GL, MI, MAZIM, & MXCMU, NN, NSTR, YLMC, CC, EVECC, EVAL, KK, GC, & AAD, EVECCD, EVALD, WKD ) c Solves eigenvalue/vector problem necessary to construct c homogeneous part of discrete ordinate solution; STWJ(8b) c ** NOTE ** Eigenvalue problem is degenerate when single c scattering albedo = 1; present way of doing it c seems numerically more stable than alternative c methods that we tried c I N P U T V A R I A B L E S: c GL : Delta-M scaled Legendre coefficients of phase function c (including factors 2l+1 and single-scatter albedo) c CMU : Computational polar angle cosines c CWT : Weights for quadrature over polar angle cosine c MAZIM : Order of azimuthal component c NN : Half the total number of streams c YLMC : Normalized associated Legendre polynomial c at the quadrature angles CMU c (remainder are DISORT input variables) c O U T P U T V A R I A B L E S: c CC : C-sub-ij in Eq. SS(5); needed in SS(15&18) c EVAL : NN eigenvalues of Eq. SS(12) on return from ASYMTX c but then square roots taken c EVECC : NN eigenvectors (G+) - (G-) on return c from ASYMTX ( column j corresponds to EVAL(j) ) c but then (G+) + (G-) is calculated from SS(10), c G+ and G- are separated, and G+ is stacked on c top of G- to form NSTR eigenvectors of SS(7) c GC : Permanent storage for all NSTR eigenvectors, but c in an order corresponding to KK c KK : Permanent storage for all NSTR eigenvalues of SS(7), c but re-ordered with negative values first ( square c roots of EVAL taken and negatives added ) c I N T E R N A L V A R I A B L E S: c AMB,APB : Matrices (alpha-beta), (alpha+beta) in reduced c eigenvalue problem c ARRAY : Complete coefficient matrix of reduced eigenvalue c problem: (alfa+beta)*(alfa-beta) c GPPLGM : (G+) + (G-) (cf. Eqs. SS(10-11)) c GPMIGM : (G+) - (G-) (cf. Eqs. SS(10-11)) c WKD : Scratch array required by ASYMTX c Called by- DISORT, ALBTRN c Calls- ASYMTX, ERRMSG c +-------------------------------------------------------------------+ c .. Scalar Arguments .. INTEGER MAZIM, MI, MXCMU, NN, NSTR c .. c .. Array Arguments .. REAL AMB( MI, MI ), APB( MI, MI ), ARRAY( MI, * ), & CC( MXCMU, MXCMU ), CMU( MXCMU ), CWT( MXCMU ), & EVAL( MI ), EVECC( MXCMU, MXCMU ), GC( MXCMU, MXCMU ), & GL( 0:MXCMU ), KK( MXCMU ), YLMC( 0:MXCMU, MXCMU ) REAL(kind(0.0d0)) :: AAD( MI, MI ), EVALD( MI ), EVECCD( MI, MI ), & WKD( MXCMU ) c .. c .. Local Scalars .. INTEGER IER, IQ, JQ, KQ, L REAL ALPHA, BETA, GPMIGM, GPPLGM, SUM c .. c .. External Subroutines .. EXTERNAL ASYMTX, ERRMSG c .. c .. Intrinsic Functions .. INTRINSIC ABS, SQRT c .. c ** Calculate quantities in Eqs. SS(5-6) DO 40 IQ = 1, NN DO 20 JQ = 1, NSTR SUM = 0.0 DO 10 L = MAZIM, NSTR - 1 SUM = SUM + GL( L )*YLMC( L, IQ )*YLMC( L, JQ ) 10 CONTINUE CC( IQ, JQ ) = 0.5*SUM*CWT( JQ ) 20 CONTINUE DO 30 JQ = 1, NN c ** Fill remainder of array using symmetry c relations C(-mui,muj) = C(mui,-muj) c and C(-mui,-muj) = C(mui,muj) CC( IQ + NN, JQ ) = CC( IQ, JQ + NN ) CC( IQ + NN, JQ + NN ) = CC( IQ, JQ ) c ** Get factors of coeff. matrix c of reduced eigenvalue problem ALPHA = CC( IQ, JQ ) / CMU( IQ ) BETA = CC( IQ, JQ + NN ) / CMU( IQ ) AMB( IQ, JQ ) = ALPHA - BETA APB( IQ, JQ ) = ALPHA + BETA 30 CONTINUE AMB( IQ, IQ ) = AMB( IQ, IQ ) - 1.0 / CMU( IQ ) APB( IQ, IQ ) = APB( IQ, IQ ) - 1.0 / CMU( IQ ) 40 CONTINUE c ** Finish calculation of coefficient matrix of c reduced eigenvalue problem: get matrix c product (alfa+beta)*(alfa-beta); SS(12) DO 70 IQ = 1, NN DO 60 JQ = 1, NN SUM = 0. DO 50 KQ = 1, NN SUM = SUM + APB( IQ, KQ )*AMB( KQ, JQ ) 50 CONTINUE ARRAY( IQ, JQ ) = SUM 60 CONTINUE 70 CONTINUE c ** Find (real) eigenvalues and eigenvectors CALL ASYMTX( ARRAY, EVECC, EVAL, NN, MI, MXCMU, IER, WKD, AAD, & EVECCD, EVALD ) IF( IER.GT.0 ) THEN WRITE( *, FMT = '(//,A,I4,A)' ) ' ASYMTX--eigenvalue no. ', & IER, ' didnt converge. Lower-numbered eigenvalues wrong.' CALL ERRMSG( 'ASYMTX--convergence problems',.True.) END IF CDIR$ IVDEP DO 80 IQ = 1, NN EVAL( IQ ) = SQRT( ABS( EVAL( IQ ) ) ) KK( IQ + NN ) = EVAL( IQ ) c ** Add negative eigenvalue KK( NN + 1 - IQ ) = -EVAL( IQ ) 80 CONTINUE c ** Find eigenvectors (G+) + (G-) from SS(10) c and store temporarily in APB array DO 110 JQ = 1, NN DO 100 IQ = 1, NN SUM = 0. DO 90 KQ = 1, NN SUM = SUM + AMB( IQ, KQ )*EVECC( KQ, JQ ) 90 CONTINUE APB( IQ, JQ ) = SUM / EVAL( JQ ) 100 CONTINUE 110 CONTINUE DO 130 JQ = 1, NN CDIR$ IVDEP DO 120 IQ = 1, NN GPPLGM = APB( IQ, JQ ) GPMIGM = EVECC( IQ, JQ ) c ** Recover eigenvectors G+,G- from c their sum and difference; stack them c to get eigenvectors of full system c SS(7) (JQ = eigenvector number) EVECC( IQ, JQ ) = 0.5*( GPPLGM + GPMIGM ) EVECC( IQ + NN, JQ ) = 0.5*( GPPLGM - GPMIGM ) c ** Eigenvectors corresponding to c negative eigenvalues (corresp. to c reversing sign of 'k' in SS(10) ) GPPLGM = - GPPLGM EVECC(IQ, JQ+NN) = 0.5 * ( GPPLGM + GPMIGM ) EVECC(IQ+NN,JQ+NN) = 0.5 * ( GPPLGM - GPMIGM ) GC( IQ+NN, JQ+NN ) = EVECC( IQ, JQ ) GC( NN+1-IQ, JQ+NN ) = EVECC( IQ+NN, JQ ) GC( IQ+NN, NN+1-JQ ) = EVECC( IQ, JQ+NN ) GC( NN+1-IQ, NN+1-JQ ) = EVECC( IQ+NN, JQ+NN ) 120 CONTINUE 130 CONTINUE END SUBROUTINE SOLVE0( B, BDR, BEM, BPLANK, CBAND, CMU, CWT, EXPBEA, & FBEAM, FISOT, IPVT, LAMBER, LL, LYRCUT, MAZIM, & MI, MI9M2, MXCMU, NCOL, NCUT, NN, NSTR, NNLYRI, & PI, TPLANK, TAUCPR, UMU0, Z, ZZ, ZPLK0, ZPLK1 ) c Construct right-hand side vector B for general boundary c conditions STWJ(17) and solve system of equations obtained c from the boundary conditions and the continuity-of- c intensity-at-layer-interface equations. c Thermal emission contributes only in azimuthal independence. c I N P U T V A R I A B L E S: c BDR : Surface bidirectional reflectivity c BEM : Surface bidirectional emissivity c BPLANK : Bottom boundary thermal emission c CBAND : Left-hand side matrix of linear system Eq. SC(5), c scaled by Eq. SC(12); in banded form required c by LINPACK solution routines c CMU : Abscissae for Gauss quadrature over angle cosine c CWT : Weights for Gauss quadrature over angle cosine c EXPBEA : Transmission of incident beam, EXP(-TAUCPR/UMU0) c LYRCUT : Logical flag for truncation of comput. layer c MAZIM : Order of azimuthal component c ncol : Counts of columns in CBAND c NN : Order of double-Gauss quadrature (NSTR/2) c NCUT : Total number of computational layers considered c TPLANK : Top boundary thermal emission c TAUCPR : Cumulative optical depth (delta-M-scaled) c ZZ : Beam source vectors in Eq. SS(19) c ZPLK0 : Thermal source vectors Z0, by solving Eq. SS(16) c ZPLK1 : Thermal source vectors Z1, by solving Eq. SS(16) c (remainder are DISORT input variables) c O U T P U T V A R I A B L E S: c B : Right-hand side vector of Eq. SC(5) going into c SGBSL; returns as solution vector of Eq. SC(12), c constants of integration without exponential term c c LL : Permanent storage for B, but re-ordered c I N T E R N A L V A R I A B L E S: c IPVT : Integer vector of pivot indices c IT : Pointer for position in B c NCD : Number of diagonals below or above main diagonal c RCOND : Indicator of singularity for CBAND c Z : Scratch array required by SGBCO c Called by- DISORT c Calls- ZEROIT, SGBCO, ERRMSG, SGBSL c +-------------------------------------------------------------------+ c .. Scalar Arguments .. LOGICAL LAMBER, LYRCUT INTEGER MAZIM, MI, MI9M2, MXCMU, NCOL, NCUT, NN, NNLYRI, NSTR REAL BPLANK, FBEAM, FISOT, PI, TPLANK, UMU0 c .. c .. Array Arguments .. INTEGER IPVT( * ) REAL B( NNLYRI ), BDR( MI, 0:MI ), BEM( MI ), & CBAND( MI9M2, NNLYRI ), CMU( MXCMU ), CWT( MXCMU ), & EXPBEA( 0:* ), LL( MXCMU, * ), TAUCPR( 0:* ), & Z( NNLYRI ), ZPLK0( MXCMU, * ), ZPLK1( MXCMU, * ), & ZZ( MXCMU, * ) c .. c .. Local Scalars .. INTEGER IPNT, IQ, IT, JQ, LC, NCD REAL RCOND, SUM c .. c .. External Subroutines .. EXTERNAL ERRMSG, SGBCO, SGBSL, ZEROIT c .. CALL ZEROIT( B, NNLYRI ) c ** Construct B, STWJ(20a,c) for c parallel beam + bottom reflection + c thermal emission at top and/or bottom IF( MAZIM.GT.0 .AND. FBEAM.GT.0.0 ) THEN c ** Azimuth-dependent case c (never called if FBEAM = 0) IF( LYRCUT .OR. LAMBER ) THEN c ** No azimuthal-dependent intensity for Lambert surface; c no intensity component for truncated bottom layer DO 10 IQ = 1, NN c ** Top boundary B( IQ ) = - ZZ( NN + 1 - IQ, 1 )*EXPBEA( 0 ) c ** Bottom boundary B( NCOL - NN + IQ ) = -ZZ( IQ + NN, NCUT )*EXPBEA( NCUT ) 10 CONTINUE ELSE DO 30 IQ = 1, NN B( IQ ) = - ZZ( NN + 1 - IQ, 1 )*EXPBEA( 0 ) SUM = 0. DO 20 JQ = 1, NN SUM = SUM + CWT( JQ )*CMU( JQ )*BDR( IQ, JQ )* & ZZ( NN + 1 - JQ, NCUT )*EXPBEA( NCUT ) 20 CONTINUE B( NCOL - NN + IQ ) = SUM IF( FBEAM.GT.0.0 ) B( NCOL - NN + IQ ) = SUM + & ( BDR( IQ,0 )*UMU0*FBEAM / PI - ZZ( IQ + NN,NCUT ) )* & EXPBEA( NCUT ) 30 CONTINUE END IF c ** Continuity condition for layer c interfaces of Eq. STWJ(20b) IT = NN DO 50 LC = 1, NCUT - 1 DO 40 IQ = 1, NSTR IT = IT + 1 B( IT ) = ( ZZ( IQ, LC+1 ) - ZZ( IQ, LC ) )*EXPBEA( LC ) 40 CONTINUE 50 CONTINUE ELSE c ** Azimuth-independent case IF( FBEAM.EQ.0.0 ) THEN DO 60 IQ = 1, NN c ** Top boundary B( IQ ) = -ZPLK0( NN + 1 - IQ, 1 ) + FISOT + TPLANK 60 CONTINUE IF( LYRCUT ) THEN c ** No intensity component for truncated c bottom layer DO 70 IQ = 1, NN c ** Bottom boundary B( NCOL - NN + IQ ) = - ZPLK0( IQ + NN, NCUT ) - & ZPLK1( IQ + NN, NCUT )* & TAUCPR( NCUT ) 70 CONTINUE ELSE DO 90 IQ = 1, NN SUM = 0. DO 80 JQ = 1, NN SUM = SUM + CWT( JQ )*CMU( JQ )*BDR( IQ, JQ )* & ( ZPLK0( NN + 1 - JQ,NCUT ) + & ZPLK1( NN + 1 - JQ,NCUT )*TAUCPR( NCUT ) ) 80 CONTINUE B( NCOL - NN + IQ ) = 2.*SUM + BEM( IQ )*BPLANK - & ZPLK0( IQ + NN, NCUT ) - & ZPLK1( IQ + NN, NCUT )* & TAUCPR( NCUT ) 90 CONTINUE END IF c ** Continuity condition for layer c interfaces, STWJ(20b) IT = NN DO 110 LC = 1, NCUT - 1 DO 100 IQ = 1, NSTR IT = IT + 1 B( IT ) = ZPLK0( IQ, LC + 1 ) - ZPLK0( IQ, LC ) + & ( ZPLK1( IQ, LC + 1 ) - ZPLK1( IQ, LC ) )* & TAUCPR( LC ) 100 CONTINUE 110 CONTINUE ELSE DO 120 IQ = 1, NN B( IQ ) = - ZZ( NN + 1 - IQ, 1 )*EXPBEA( 0 ) - & ZPLK0( NN + 1 - IQ, 1 ) + FISOT + TPLANK 120 CONTINUE IF( LYRCUT ) THEN DO 130 IQ = 1, NN B(NCOL-NN+IQ) = - ZZ(IQ+NN, NCUT) * EXPBEA(NCUT) & - ZPLK0(IQ+NN, NCUT) & - ZPLK1(IQ+NN, NCUT) * TAUCPR(NCUT) 130 CONTINUE ELSE DO 150 IQ = 1, NN SUM = 0. DO 140 JQ = 1, NN SUM = SUM + CWT(JQ) * CMU(JQ) * BDR(IQ,JQ) & * ( ZZ(NN+1-JQ, NCUT) * EXPBEA(NCUT) & + ZPLK0(NN+1-JQ, NCUT) & + ZPLK1(NN+1-JQ, NCUT) * TAUCPR(NCUT)) 140 CONTINUE B(NCOL-NN+IQ) = 2.*SUM + ( BDR(IQ,0) * UMU0*FBEAM/PI & - ZZ(IQ+NN, NCUT) ) * EXPBEA(NCUT) & + BEM(IQ) * BPLANK & - ZPLK0(IQ+NN, NCUT) & - ZPLK1(IQ+NN, NCUT) * TAUCPR(NCUT) 150 CONTINUE END IF IT = NN DO 170 LC = 1, NCUT - 1 DO 160 IQ = 1, NSTR IT = IT + 1 B(IT) = ( ZZ(IQ,LC+1) - ZZ(IQ,LC) ) * EXPBEA(LC) & + ZPLK0(IQ,LC+1) - ZPLK0(IQ,LC) + & ( ZPLK1(IQ,LC+1) - ZPLK1(IQ,LC) ) * TAUCPR(LC) 160 CONTINUE 170 CONTINUE END IF END IF c ** Find L-U (lower/upper triangular) decomposition c of band matrix CBAND and test if it is nearly c singular (note: CBAND is destroyed) c (CBAND is in LINPACK packed format) RCOND = 0.0 NCD = 3*NN - 1 CALL SGBCO( CBAND, MI9M2, NCOL, NCD, NCD, IPVT, RCOND, Z ) IF( 1.0 + RCOND.EQ.1.0 ) & CALL ERRMSG('SOLVE0--SGBCO says matrix near singular',.FALSE.) c ** Solve linear system with coeff matrix CBAND c and R.H. side(s) B after CBAND has been L-U c decomposed. Solution is returned in B. CALL SGBSL( CBAND, MI9M2, NCOL, NCD, NCD, IPVT, B, 0 ) c ** Zero CBAND (it may contain 'foreign' c elements upon returning from LINPACK); c necessary to prevent errors CALL ZEROIT( CBAND, MI9M2*NNLYRI ) DO 190 LC = 1, NCUT IPNT = LC*NSTR - NN DO 180 IQ = 1, NN LL( NN + 1 - IQ, LC ) = B( IPNT + 1 - IQ ) LL( IQ + NN, LC ) = B( IQ + IPNT ) 180 CONTINUE 190 CONTINUE RETURN END SUBROUTINE SURFAC( ALBEDO, DELM0, FBEAM, HLPR, LAMBER, MI, MAZIM, & MXCMU, MXUMU, NN, NUMU, NSTR, ONLYFL, UMU, & USRANG, YLM0, YLMC, YLMU, BDR, EMU, BEM, RMU ) c Specifies user's surface bidirectional properties, STWJ(21) c I N P U T V A R I A B L E S: c DELM0 : Kronecker delta, delta-sub-m0 c HLPR : Legendre moments of surface bidirectional reflectivity c (with 2K+1 factor included) c MAZIM : Order of azimuthal component c NN : Order of double-Gauss quadrature (NSTR/2) c YLM0 : Normalized associated Legendre polynomial c at the beam angle c YLMC : Normalized associated Legendre polynomials c at the quadrature angles c YLMU : Normalized associated Legendre polynomials c at the user angles c (remainder are DISORT input variables) c O U T P U T V A R I A B L E S: c BDR : Surface bidirectional reflectivity (computational angles) c RMU : Surface bidirectional reflectivity (user angles) c BEM : Surface directional emissivity (computational angles) c EMU : Surface directional emissivity (user angles) c I N T E R N A L V A R I A B L E S: c DREF Directional reflectivity c NMUG : Number of angle cosine quadrature points on (0,1) for c integrating bidirectional reflectivity to get c directional emissivity (it is necessary to use a c quadrature set distinct from the computational c angles, because the computational angles may not be c dense enough--NSTR may be too small--to give an c accurate approximation for the integration). c GMU : The NMUG angle cosine quadrature points on (0,1) c GWT : The NMUG angle cosine quadrature weights on (0,1) c YLMG : Normalized associated Legendre polynomials c at the NMUG quadrature angles c Called by- DISORT c Calls- QGAUSN, LEPOLY, ZEROIT, ERRMSG c +-------------------------------------------------------------------+ c .. Parameters .. INTEGER NMUG, MAXSTR PARAMETER ( NMUG = 10, MAXSTR = 100 ) c .. c .. Scalar Arguments .. LOGICAL LAMBER, ONLYFL, USRANG INTEGER MAZIM, MI, MXCMU, MXUMU, NN, NSTR, NUMU REAL ALBEDO, DELM0, FBEAM c .. c .. Array Arguments .. REAL BDR( MI, 0:MI ), BEM( MI ), EMU( MXUMU ), & HLPR( 0:MXCMU ), RMU( MXUMU, 0:MI ), UMU( * ), & YLM0( 0:MXCMU ), YLMC( 0:MXCMU, MXCMU ), & YLMU( 0:MXCMU, MXUMU ) c .. c .. Local Scalars .. LOGICAL PASS1 INTEGER IQ, IU, JG, JQ, K REAL DREF, SGN, SUM c .. c .. Local Arrays .. REAL GMU( NMUG ), GWT( NMUG ), YLMG( 0:MAXSTR, NMUG ) c .. c .. External Subroutines .. EXTERNAL ERRMSG, LEPOLY, QGAUSN, ZEROIT c .. SAVE PASS1, GMU, GWT, YLMG DATA PASS1 / .TRUE. / IF( PASS1 ) THEN PASS1 = .FALSE. CALL QGAUSN( NMUG, GMU, GWT ) CALL LEPOLY( NMUG, 0, MAXSTR, MAXSTR, GMU, YLMG ) c ** Convert Legendre polys. to negative GMU SGN = - 1.0 DO 20 K = 0, MAXSTR SGN = - SGN DO 10 JG = 1, NMUG YLMG( K, JG ) = SGN*YLMG( K, JG ) 10 CONTINUE 20 CONTINUE END IF CALL ZEROIT( BDR, MI*( MI + 1 ) ) CALL ZEROIT( BEM, MI ) IF( LAMBER .AND. MAZIM.EQ.0 ) THEN DO 40 IQ = 1, NN BEM( IQ ) = 1.- ALBEDO DO 30 JQ = 0, NN BDR( IQ, JQ ) = ALBEDO 30 CONTINUE 40 CONTINUE ELSE IF( .NOT.LAMBER ) THEN c ** Compute surface bidirectional c properties at computational angles DO 80 IQ = 1, NN DO 60 JQ = 1, NN SUM = 0.0 DO 50 K = MAZIM, NSTR - 1 SUM = SUM + HLPR( K )*YLMC( K, IQ )* & YLMC( K, JQ + NN ) 50 CONTINUE BDR( IQ, JQ ) = ( 2.- DELM0 )*SUM 60 CONTINUE IF( FBEAM.GT.0.0 ) THEN SUM = 0.0 DO 70 K = MAZIM, NSTR - 1 SUM = SUM + HLPR( K )*YLMC( K, IQ )*YLM0( K ) 70 CONTINUE BDR( IQ, 0 ) = ( 2.- DELM0 )*SUM END IF 80 CONTINUE IF( MAZIM.EQ.0 ) THEN IF( NSTR.GT.MAXSTR ) & CALL ERRMSG('SURFAC--parameter MAXSTR too small',.True.) c ** Integrate bidirectional reflectivity c at reflection polar angles CMU and c incident angles GMU to get c directional emissivity at c computational angles CMU. DO 110 IQ = 1, NN DREF = 0.0 DO 100 JG = 1, NMUG SUM = 0.0 DO 90 K = 0, NSTR - 1 SUM = SUM + HLPR( K )*YLMC( K, IQ )* & YLMG( K, JG ) 90 CONTINUE DREF = DREF + 2.*GWT( JG )*GMU( JG )*SUM 100 CONTINUE BEM( IQ ) = 1.- DREF 110 CONTINUE END IF END IF c ** Compute surface bidirectional c properties at user angles IF( .NOT.ONLYFL .AND. USRANG ) THEN CALL ZEROIT( EMU, MXUMU ) CALL ZEROIT( RMU, MXUMU*( MI + 1 ) ) DO 180 IU = 1, NUMU IF( UMU( IU ).GT.0.0 ) THEN IF( LAMBER .AND. MAZIM.EQ.0 ) THEN DO 120 IQ = 0, NN RMU( IU, IQ ) = ALBEDO 120 CONTINUE EMU( IU ) = 1.- ALBEDO ELSE IF( .NOT.LAMBER ) THEN DO 140 IQ = 1, NN SUM = 0.0 DO 130 K = MAZIM, NSTR - 1 SUM = SUM + HLPR( K )*YLMU( K, IU )* & YLMC( K, IQ + NN ) 130 CONTINUE RMU( IU, IQ ) = ( 2.- DELM0 )*SUM 140 CONTINUE IF( FBEAM.GT.0.0 ) THEN SUM = 0.0 DO 150 K = MAZIM, NSTR - 1 SUM = SUM + HLPR( K )*YLMU( K, IU )*YLM0( K ) 150 CONTINUE RMU( IU, 0 ) = ( 2.- DELM0 )*SUM END IF IF( MAZIM.EQ.0 ) THEN c ** Integrate bidirectional reflectivity c at reflection angles UMU and c incident angles GMU to get c directional emissivity at c user angles UMU. DREF = 0.0 DO 170 JG = 1, NMUG SUM = 0.0 DO 160 K = 0, NSTR - 1 SUM = SUM + HLPR( K )*YLMU( K, IU )* & YLMG( K, JG ) 160 CONTINUE DREF = DREF + 2.*GWT( JG )*GMU( JG )*SUM 170 CONTINUE EMU( IU ) = 1.- DREF END IF END IF END IF 180 CONTINUE END IF END *bm SOLVEC calls SOLEIG and UPBEAM; if UPBEAM reports a potenially *bm unstable solution, the calculation is repeated with a slightly *bm changed single scattering albedo; this process is iterates *bm until a stable solution is found; as stable solutions may be *bm reached either by increasing or by decreasing the single *bm scattering albedo, both directions are explored ('upward' and *bm 'downward' iteration); the solution which required the smaller *bm change in the single scattering albedo is finally returned *bm by SOLVEC. SUBROUTINE SOLVEC( AMB, APB, ARRAY, CMU, CWT, GL, MI, & MAZIM, MXCMU, NN, NSTR, YLM0, YLMC, CC, & EVECC, EVAL, KK, GC, AAD, EVECCD, EVALD, & WK, WKD, DELM0, FBEAM, IPVT, PI, UMU0, ZJ, ZZ, & OPRIM, LC, DITHER, mu2, glsave, dgl) cgy added glsave and dgl to call to allow adjustable dimensioning c .. Scalar Arguments .. INTEGER MAZIM, MI, MXCMU, NN, NSTR, LC REAL DELM0, FBEAM, PI, UMU0, OPRIM, DITHER REAL mu2 c .. c .. Array Arguments .. INTEGER IPVT( * ) REAL AMB( MI, MI ), APB( MI, MI ), ARRAY( MI, * ), & CC( MXCMU, MXCMU ), CMU( MXCMU ), CWT( MXCMU ), & EVAL( MI ), EVECC( MXCMU, MXCMU ), GC( MXCMU, MXCMU ), & GL( 0:MXCMU ), KK( MXCMU ), & YLM0( 0:MXCMU ), YLMC( 0:MXCMU, MXCMU ), & WK( MXCMU ), ZJ( MXCMU ), ZZ( MXCMU ) REAL(kind(0.0d0)) :: AAD( MI, MI ), EVALD( MI ), EVECCD( MI, MI ), & WKD( MXCMU ) *bm Variables for instability fix INTEGER UAGAIN, DAGAIN REAL MINRCOND, ADD, UADD, DADD, SSA, DSSA, FACTOR REAL GLSAVE( 0:MXCMU ), DGL( 0:MXCMU ) LOGICAL DONE, NOUP, NODN, DEBUG, INSTAB *bm reset parameters DONE = .FALSE. NOUP = .FALSE. NODN = .FALSE. *bm flag for printing debugging output * DEBUG = .TRUE. DEBUG = .FALSE. *bm instability parameter; the solution is considered *bm unstable, if the RCOND reported by SGECO is smaller *bm than MINRCOND MINRCOND = 5000. * R1MACH(4) *bm if an instability is detected, the single scattering albedo *bm is iterated downwards in steps of DADD and upwards in steps *bm of UADD; in practice, MINRCOND and -MINRCOND should *bm be reasonable choices for these parameters DADD = -MINRCOND UADD = MINRCOND UAGAIN = 0 DAGAIN = 0 ADD = DADD *bm save array GL( ) because it will be *bm changed if an iteration should be neccessary DO K = MAZIM, NSTR - 1 GLSAVE( K ) = GL( K ) ENDDO SSA = OPRIM *bm in case of an instability reported by UPBEAM (INSTAB) *bm the single scattering albedo will be changed by a small *bm amount (ADD); this is indicated by DAGAIN or UAGAIN *bm being larger than 0; a change in the single scattering *bm albedo is equivalent to scaling the array GL( ) 666 IF ( DAGAIN .GT. 0 .OR. UAGAIN .GT. 0) THEN FACTOR = (SSA + ADD) / SSA DO K = MAZIM, NSTR - 1 GL( K ) = GL( K ) * FACTOR ENDDO SSA = SSA + ADD *bm if the single scattering albedo is now smaller than 0 *bm the downward iteration is stopped and upward iteration *bm is forced instead IF( SSA .LT. DITHER) THEN NODN = .TRUE. DAGAIN = -1 goto 778 ENDIF *bm if the single scattering albedo is now larger than its maximum *bm allowed value (1.0 - DITHER), the upward iteration is *bm stopped and downward iteration is forced instead IF( SSA .GT. 1.0 - DITHER) THEN NOUP = .TRUE. UAGAIN = -1 goto 888 ENDIF ENDIF c ** Solve eigenfunction problem in Eq. STWJ(8B); c return eigenvalues and eigenvectors 777 CALL SOLEIG( AMB, APB, ARRAY, CMU, CWT, GL, MI, & MAZIM, MXCMU, NN, NSTR, YLMC, CC, EVECC, EVAL, & KK, GC, AAD, EVECCD, EVALD, & WKD ) c ** Calculate particular solutions of c q.SS(18) for incident beam source IF ( FBEAM.GT.0.0 ) THEN CALL UPBEAM( mu2, $ ARRAY, CC, CMU, DELM0, FBEAM, GL, $ IPVT, MAZIM, MXCMU, NN, NSTR, PI, UMU0, WK, $ YLM0, YLMC, ZJ, ZZ, MINRCOND, INSTAB) ENDIF c ** Calculate particular solutions of c Eq. SS(15) for thermal emission source c (not available in psndo.f) *bm finished if the result is stable on the first try IF ( (.NOT. INSTAB) .AND. $ (UAGAIN .EQ. 0) .AND. (DAGAIN .EQ. 0)) THEN goto 999 ENDIF *bm downward iteration IF( INSTAB .AND. UAGAIN .EQ. 0 ) THEN DAGAIN = DAGAIN + 1 GOTO 666 ENDIF *bm upward iteration IF( INSTAB .AND. UAGAIN .GT. 0 ) THEN UAGAIN = UAGAIN + 1 GOTO 666 ENDIF *bm ( DAGAIN .NE. 0 ) at this place means that the downward *bm iteration is finished 778 IF (DAGAIN .NE. 0 .AND. UAGAIN .EQ. 0) THEN *bm save downward iteration data for later use and *bm restore original input data DO K = MAZIM, NSTR - 1 DGL( K ) = GL( K ) GL( K ) = GLSAVE( K ) ENDDO DSSA = SSA SSA = OPRIM *bm start upward iteration ADD = UADD UAGAIN = UAGAIN + 1 GOTO 666 ENDIF *bm both iterations finished 888 IF (DONE) THEN goto 998 ENDIF *bm if neither upward nor downward iteration converged, the *bm original conditions are restored and SOLEIG/UPBEAM *bm is called for the last time IF (NOUP .AND. NODN) THEN DO K = MAZIM, NSTR - 1 GL( K ) = GLSAVE( K ) ENDDO SSA = OPRIM IF (DEBUG) THEN write (*,*) '! *** Neither upward nor downward iteration' write (*,*) '! *** converged; using original result.' ENDIF DONE = .TRUE. GOTO 777 ENDIF *bm if upward iteration did not converge, the stable downward conditions *bm are restored and SOLEIG/UPBEAM is called for the last time IF (NOUP) THEN DO K = MAZIM, NSTR - 1 GL( K ) = DGL( K ) ENDDO SSA = DSSA IF (DEBUG) THEN write (*,*) '! *** The upward iteration did not converge.' write (*,*) '! *** Had to iterate ', DAGAIN, $ ' times in layer LC =', LC,';' write (*,*) '! *** changed SSA from ', $ OPRIM, ' to ', SSA,',' write (*,*) '! *** by a factor of ', SSA/OPRIM ENDIF DONE = .TRUE. GOTO 777 ENDIF *bm if downward iteration did not converge, we are done *bm (the result of the upward iteration will be used) IF (NODN) THEN IF (DEBUG) THEN write (*,*) '! *** The downward iteration did not converge.' write (*,*) '! *** Had to iterate ', UAGAIN, $ ' times in layer LC =', LC,';' write (*,*) '! *** changed SSA from ', $ OPRIM, ' to ', SSA,',' write (*,*) '! *** by a factor of ', SSA/OPRIM ENDIF DONE = .TRUE. GOTO 998 ENDIF *bm if both iterations converged, and if the upward iteration *bm required more steps than the downward iteration, the stable *bm downward conditions are restored and SOLEIG/UPBEAM is *bm called for the last time IF (UAGAIN .GT. DAGAIN) THEN DO K = MAZIM, NSTR - 1 GL( K ) = DGL( K ) ENDDO SSA = DSSA IF (DEBUG) THEN write (*,*) '! *** Both iterations converged;', $ ' using downward.' write (*,*) '! *** Had to iterate ', DAGAIN, $ ' times in layer LC =', LC,';' write (*,*) '! *** changed SSA from ', $ OPRIM, ' to ', SSA,',' write (*,*) '! *** by a factor of ', SSA/OPRIM ENDIF DONE = .TRUE. GOTO 777 ELSE IF (DEBUG) THEN write (*,*) '! *** Both iterations converged;', $ ' using upward.' write (*,*) '! *** Had to iterate ', UAGAIN, $ ' times in layer LC =', LC,';' write (*,*) '! *** changed SSA from ', $ OPRIM, ' to ', SSA,',' write (*,*) '! *** by a factor of ', SSA/OPRIM ENDIF DONE = .TRUE. goto 998 ENDIF *bm finally restore original input data 998 DO K = MAZIM, NSTR - 1 GL( K ) = GLSAVE( K ) ENDDO 999 CONTINUE END SUBROUTINE UPBEAM( mu2, & ARRAY, CC, CMU, DELM0, FBEAM, GL, IPVT, MAZIM, & MXCMU, NN, NSTR, PI, UMU0, WK, YLM0, YLMC, ZJ, & ZZ, MINRCOND, INSTAB ) c Finds the incident-beam particular solution of SS(18) c I N P U T V A R I A B L E S: c CC : C-sub-ij in Eq. SS(5) c CMU : Abscissae for Gauss quadrature over angle cosine c DELM0 : Kronecker delta, delta-sub-m0 c GL : Delta-M scaled Legendre coefficients of phase function c (including factors 2L+1 and single-scatter albedo) c MAZIM : Order of azimuthal component c YLM0 : Normalized associated Legendre polynomial c at the beam angle c YLMC : Normalized associated Legendre polynomial c at the quadrature angles c (remainder are DISORT input variables) c O U T P U T V A R I A B L E S: c ZJ : Right-hand side vector X-sub-zero in SS(19); also the c solution vector Z-sub-zero after solving that system c ZZ : Permanent storage for ZJ, but re-ordered c I N T E R N A L V A R I A B L E S: c ARRAY : Coefficient matrix in left-hand side of Eq. SS(19) c IPVT : Integer vector of pivot indices required by LINPACK c WK : Scratch array required by LINPACK c Called by- DISORT c Calls- SGECO, ERRMSG, SGESL c +-------------------------------------------------------------------+ c .. Scalar Arguments .. INTEGER MAZIM, MXCMU, NN, NSTR LOGICAL INSTAB REAL MINRCOND REAL DELM0, FBEAM, PI, UMU0 REAL mu2 c .. c .. Array Arguments .. INTEGER IPVT( * ) REAL ARRAY( MXCMU, MXCMU ), CC( MXCMU, MXCMU ), CMU( MXCMU ), & GL( 0:MXCMU ), WK( MXCMU ), YLM0( 0:MXCMU ), & YLMC( 0:MXCMU, * ), ZJ( MXCMU ), ZZ( MXCMU ) c .. c .. Local Scalars .. INTEGER IQ, JOB, JQ, K REAL RCOND, SUM c .. c .. External Subroutines .. EXTERNAL ERRMSG, SGECO, SGESL c .. DO 30 IQ = 1, NSTR DO 10 JQ = 1, NSTR ARRAY( IQ, JQ ) = -CC( IQ, JQ ) 10 CONTINUE ARRAY( IQ, IQ ) = 1.+ CMU( IQ ) / mu2 + ARRAY( IQ, IQ ) SUM = 0. DO 20 K = MAZIM, NSTR - 1 SUM = SUM + GL( K )*YLMC( K, IQ )*YLM0( K ) 20 CONTINUE ZJ( IQ ) = ( 2.- DELM0 )*FBEAM*SUM / ( 4.*PI ) 30 CONTINUE c ** Find L-U (lower/upper triangular) decomposition c of ARRAY and see if it is nearly singular c (NOTE: ARRAY is destroyed) RCOND = 0.0 CALL SGECO( ARRAY, MXCMU, NSTR, IPVT, RCOND, WK ) *bm IF( 1.0 + RCOND.EQ.1.0 ) *bm & CALL ERRMSG('UPBEAM--SGECO says matrix near singular',.FALSE.) *bm *bm replaced original check of RCOND by the following: INSTAB = .FALSE. IF( ABS(RCOND) .LT. MINRCOND ) THEN INSTAB = .TRUE. RETURN ENDIF c ** Solve linear system with coeff matrix ARRAY c (assumed already L-U decomposed) and R.H. side(s) c ZJ; return solution(s) in ZJ JOB = 0 CALL SGESL( ARRAY, MXCMU, NSTR, IPVT, ZJ, JOB ) CDIR$ IVDEP DO 40 IQ = 1, NN ZZ( IQ + NN ) = ZJ( IQ ) ZZ( NN + 1 - IQ ) = ZJ( IQ + NN ) 40 CONTINUE END SUBROUTINE ZEROAL( ND1, EXPBEA, FLYR, OPRIM, TAUCPR, XR0, XR1, & ND2, CMU, CWT, PSI, WK, Z0, Z1, ZJ, & ND3, HLPR, YLM0, & ND4, ARRAY, CC, EVECC, & ND5, GL, & ND6, YLMC, & ND7, YLMU, & ND8, KK, LL, ZZ, ZPLK0, ZPLK1, & ND9, GC, & ND10, LAYRU, UTAUPR, & ND11, GU, & ND12, Z0U, Z1U, ZBEAM, & ND13, EVAL, & ND14, AMB, APB, & ND15, IPVT, Z, & ND16, RFLDIR, RFLDN, FLUP, UAVG, DFDT, & ND17, ALBMED, TRNMED, & ND18, U0U, & ND19, UU ) c ZERO ARRAYS; NDn is dimension of all arrays following c it in the argument list c Called by- DISORT c -------------------------------------------------------------------- c .. Scalar Arguments .. INTEGER ND1, ND10, ND11, ND12, ND13, ND14, ND15, ND16, ND17, & ND18, ND19, ND2, ND3, ND4, ND5, ND6, ND7, ND8, ND9 c .. c .. Array Arguments .. INTEGER IPVT( * ), LAYRU( * ) REAL ALBMED( * ), AMB( * ), APB( * ), ARRAY( * ), CC( * ), & CMU( * ), CWT( * ), DFDT( * ), EVAL( * ), EVECC( * ), & EXPBEA( * ), FLUP( * ), FLYR( * ), GC( * ), GL( * ), & GU( * ), HLPR( * ), KK( * ), LL( * ), OPRIM( * ), & PSI( * ), RFLDIR( * ), RFLDN( * ), TAUCPR( * ), & TRNMED( * ), U0U( * ), UAVG( * ), UTAUPR( * ), UU( * ), & WK( * ), XR0( * ), XR1( * ), YLM0( * ), YLMC( * ), & YLMU( * ), Z( * ), Z0( * ), Z0U( * ), Z1( * ), Z1U( * ), & ZBEAM( * ), ZJ( * ), ZPLK0( * ), ZPLK1( * ), ZZ( * ) c .. c .. Local Scalars .. INTEGER N c .. DO 10 N = 1, ND1 EXPBEA( N ) = 0.0 FLYR( N ) = 0.0 OPRIM( N ) = 0.0 TAUCPR( N ) = 0.0 XR0( N ) = 0.0 XR1( N ) = 0.0 10 CONTINUE DO 20 N = 1, ND2 CMU( N ) = 0.0 CWT( N ) = 0.0 PSI( N ) = 0.0 WK( N ) = 0.0 Z0( N ) = 0.0 Z1( N ) = 0.0 ZJ( N ) = 0.0 20 CONTINUE DO 30 N = 1, ND3 HLPR( N ) = 0.0 YLM0( N ) = 0.0 30 CONTINUE DO 40 N = 1, ND4 ARRAY( N ) = 0.0 CC( N ) = 0.0 EVECC( N ) = 0.0 40 CONTINUE DO 50 N = 1, ND5 GL( N ) = 0.0 50 CONTINUE DO 60 N = 1, ND6 YLMC( N ) = 0.0 60 CONTINUE DO 70 N = 1, ND7 YLMU( N ) = 0.0 70 CONTINUE DO 80 N = 1, ND8 KK( N ) = 0.0 LL( N ) = 0.0 ZZ( N ) = 0.0 ZPLK0( N ) = 0.0 ZPLK1( N ) = 0.0 80 CONTINUE DO 90 N = 1, ND9 GC( N ) = 0.0 90 CONTINUE DO 100 N = 1, ND10 LAYRU( N ) = 0 UTAUPR( N ) = 0.0 100 CONTINUE DO 110 N = 1, ND11 GU( N ) = 0.0 110 CONTINUE DO 120 N = 1, ND12 Z0U( N ) = 0.0 Z1U( N ) = 0.0 ZBEAM( N ) = 0.0 120 CONTINUE DO 130 N = 1, ND13 EVAL( N ) = 0.0 130 CONTINUE DO 140 N = 1, ND14 AMB( N ) = 0.0 APB( N ) = 0.0 140 CONTINUE DO 150 N = 1, ND15 IPVT( N ) = 0 Z( N ) = 0.0 150 CONTINUE DO 160 N = 1, ND16 RFLDIR( N ) = 0. RFLDN( N ) = 0. FLUP( N ) = 0. UAVG( N ) = 0. DFDT( N ) = 0. 160 CONTINUE DO 170 N = 1, ND17 ALBMED( N ) = 0. TRNMED( N ) = 0. 170 CONTINUE DO 180 N = 1, ND18 U0U( N ) = 0. 180 CONTINUE DO 190 N = 1, ND19 UU( N ) = 0. 190 CONTINUE END SUBROUTINE ZEROIT( A, LENGTH ) c Zeros a real array A having LENGTH elements c -------------------------------------------------------------------- c .. Scalar Arguments .. INTEGER LENGTH c .. c .. Array Arguments .. REAL A( LENGTH ) c .. c .. Local Scalars .. INTEGER L c .. DO 10 L = 1, LENGTH A( L ) = 0.0 10 CONTINUE END c REAL FUNCTION DREF( MU, HL, NSTR ) C ############################## FUNCTION DREF( MU, HL, NSTR ) C ############################## c Exact flux albedo for given angle of incidence, given c a bidirectional reflectivity characterized by its c Legendre coefficients ( NOTE** these will only agree c with bottom-boundary albedos calculated by DISORT in c the limit as number of streams go to infinity, because c DISORT evaluates the integral 'CL' only approximately, c by quadrature, while this routine calculates it exactly.) c INPUT : MU Cosine of incidence angle c HL Legendre coefficients of bidirectional reflectivity c NSTR Number of elements of HL to consider c INTERNAL VARIABLES (P-sub-L is the L-th Legendre polynomial) : c CL Integral from 0 to 1 of MU * P-sub-L(MU) c (vanishes for L = 3, 5, 7, ... ) c PL P-sub-L c PLM1 P-sub-(L-1) c PLM2 P-sub-(L-2) c Called by- CHEKIN c Calls- ERRMSG c +-------------------------------------------------------------------+ IMPLICIT NONE REAL DREF c .. Parameters .. INTEGER MAXTRM PARAMETER ( MAXTRM = 100 ) c .. c .. Scalar Arguments .. INTEGER NSTR REAL MU c .. c .. Array Arguments .. REAL HL( 0:NSTR ) c .. c .. Local Scalars .. LOGICAL PASS1 INTEGER L REAL CL, PL, PLM1, PLM2 c .. c .. Local Arrays .. REAL C( MAXTRM ) c .. c .. External Subroutines .. EXTERNAL ERRMSG c .. c .. Intrinsic Functions .. INTRINSIC MOD c .. SAVE PASS1, C DATA PASS1 / .TRUE. / c .. IF( PASS1 ) THEN PASS1 = .FALSE. CL = 0.125 C( 2 ) = 10.*CL DO 10 L = 4, MAXTRM, 2 CL = - CL*( L - 3 ) / ( L + 2 ) C( L ) = 2.*( 2*L + 1 )*CL 10 CONTINUE END IF IF( NSTR.LT.2 .OR. ABS(MU).GT.1.0 ) & CALL ERRMSG( 'DREF--input argument error(s)',.True. ) IF( NSTR.GT.MAXTRM ) & CALL ERRMSG( 'DREF--parameter MAXTRM too small',.True. ) DREF = HL( 0 ) - 2.*HL( 1 )*MU PLM2 = 1.0 PLM1 = - MU DO 20 L = 2, NSTR - 1 c ** Legendre polynomial recurrence PL = ( ( 2*L - 1 )*( -MU )*PLM1 - ( L-1 )*PLM2 ) / L IF( MOD( L,2 ).EQ.0 ) DREF = DREF + C( L )*HL( L )*PL PLM2 = PLM1 PLM1 = PL 20 CONTINUE IF( DREF.LT.0.0 .OR. DREF.GT.1.0 ) & CALL ERRMSG( 'DREF--albedo value not in (0,1)',.False. ) END c REAL FUNCTION RATIO( A, B ) C ############################## FUNCTION RATIO( A, B ) C ############################## c Calculate ratio A/B with over- and under-flow protection c (thanks to Prof. Jeff Dozier for some suggestions here). c Since this routine takes two logs, it is no speed demon, c but it is invaluable for comparing results from two runs c of a program under development. c NOTE: In Fortran90, built-in functions TINY and HUGE c can replace the R1MACH calls. c --------------------------------------------------------------- IMPLICIT NONE REAL RATIO c .. Scalar Arguments .. REAL A, B c .. c .. Local Scalars .. LOGICAL PASS1 REAL ABSA, ABSB, HUGE, POWA, POWB, POWMAX, POWMIN, TINY c .. c .. External Functions .. REAL R1MACH EXTERNAL R1MACH c .. c .. Intrinsic Functions .. INTRINSIC ABS, LOG10, SIGN c .. SAVE PASS1, TINY, HUGE, POWMAX, POWMIN DATA PASS1 / .TRUE. / c .. IF( PASS1 ) THEN TINY = R1MACH( 1 ) HUGE = R1MACH( 2 ) POWMAX = LOG10( HUGE ) POWMIN = LOG10( TINY ) PASS1 = .FALSE. END IF IF( A.EQ.0.0 ) THEN IF( B.EQ.0.0 ) THEN RATIO = 1.0 ELSE RATIO = 0.0 END IF ELSE IF( B.EQ.0.0 ) THEN RATIO = SIGN( HUGE, A ) ELSE ABSA = ABS( A ) ABSB = ABS( B ) POWA = LOG10( ABSA ) POWB = LOG10( ABSB ) IF( ABSA.LT.TINY .AND. ABSB.LT.TINY ) THEN RATIO = 1.0 ELSE IF( POWA - POWB.GE.POWMAX ) THEN RATIO = HUGE ELSE IF( POWA - POWB.LE.POWMIN ) THEN RATIO = TINY ELSE RATIO = ABSA / ABSB END IF c ** DONT use old trick of determining sign c ** from A*B because A*B may (over/under)flow IF( ( A.GT.0.0 .AND. B.LT.0.0 ) .OR. & ( A.LT.0.0 .AND. B.GT.0.0 ) ) RATIO = -RATIO END IF END c c------------------------------------------------------------------------- c SUBROUTINE ErrMsg( MESSAG, FATAL ) c Print out a warning or error message; abort if error c after making symbolic dump (machine-specific) LOGICAL FATAL, MsgLim, Cray CHARACTER*(*) MESSAG INTEGER MaxMsg, NumMsg SAVE MaxMsg, NumMsg, MsgLim DATA NumMsg / 0 /, MaxMsg / 100 /, MsgLim / .FALSE. / IF ( FATAL ) THEN WRITE ( *, '(//,2A,//)' ) ' ******* ERROR >>>>>> ', MESSAG STOP END IF NumMsg = NumMsg + 1 IF( MsgLim ) RETURN IF ( NumMsg.LE.MaxMsg ) THEN WRITE ( *, '(/,2A,/)' ) ' ******* WARNING >>>>>> ', MESSAG ELSE WRITE ( *,99 ) MsgLim = .True. ENDIF RETURN 99 FORMAT( //,' >>>>>> TOO MANY WARNING MESSAGES -- ', $ 'They will no longer be printed <<<<<<<', // ) END c ------------------------------------------------------------------------- c LOGICAL FUNCTION WrtBad ( VarNam ) C ############################## FUNCTION WrtBad(VarNam) C ############################## c Write names of erroneous variables and return 'TRUE' c INPUT : VarNam = Name of erroneous variable to be written c ( CHARACTER, any length ) IMPLICIT NONE CHARACTER*(*) VarNam LOGICAL WrtBad INTEGER MaxMsg, NumMsg SAVE NumMsg, MaxMsg DATA NumMsg / 0 /, MaxMsg / 50 / WrtBad = .TRUE. NumMsg = NumMsg + 1 WRITE ( *, '(3A)' ) ' **** Input variable ', VarNam, $ ' in error ****' IF ( NumMsg.EQ.MaxMsg ) $ CALL ErrMsg ( 'Too many input errors. Aborting...', .TRUE. ) RETURN END c LOGICAL FUNCTION WrtDim ( DimNam, MinVal ) C ############################## FUNCTION WrtDim(DimNam,MinVal) C ############################## c Write name of too-small symbolic dimension and c the value it should be increased to; return 'TRUE' c INPUT : DimNam = Name of symbolic dimension which is too small c ( CHARACTER, any length ) c Minval = Value to which that dimension should be c increased (at least) IMPLICIT NONE CHARACTER*(*) DimNam INTEGER MinVal LOGICAL WrtDim WRITE ( *, '(3A,I7)' ) ' **** Symbolic dimension ', DimNam, $ ' should be increased to at least ', MinVal WrtDim = .TRUE. RETURN END c LOGICAL FUNCTION TstBad( VarNam, RelErr ) C ############################## FUNCTION TstBad(VarNam, RelErr) C ############################## c Write name (VarNam) of variable failing self-test and its c percent error from the correct value; return 'FALSE'. IMPLICIT NONE CHARACTER*(*) VarNam REAL RelErr LOGICAL TstBad TstBad = .FALSE. WRITE( *, '(/,3A,1P,E11.2,A)' ) $ ' Output variable ', VarNam,' differed by ', 100.*RelErr, $ ' per cent from correct value. Self-test failed.' RETURN END C SUBROUTINE SGBCO( ABD, LDA, N, ML, MU, IPVT, RCOND, Z ) C FACTORS A REAL BAND MATRIX BY GAUSSIAN ELIMINATION C AND ESTIMATES THE CONDITION OF THE MATRIX. C REVISION DATE: 8/1/82 C AUTHOR: MOLER, C. B., (U. OF NEW MEXICO) C IF RCOND IS NOT NEEDED, SGBFA IS SLIGHTLY FASTER. C TO SOLVE A*X = B , FOLLOW SBGCO BY SGBSL. C INPUT: C ABD REAL(LDA, N) C CONTAINS THE MATRIX IN BAND STORAGE. THE COLUMNS C OF THE MATRIX ARE STORED IN THE COLUMNS OF ABD AND C THE DIAGONALS OF THE MATRIX ARE STORED IN ROWS C ML+1 THROUGH 2*ML+MU+1 OF ABD . C SEE THE COMMENTS BELOW FOR DETAILS. C LDA INTEGER C THE LEADING DIMENSION OF THE ARRAY ABD . C LDA MUST BE .GE. 2*ML + MU + 1 . C N INTEGER C THE ORDER OF THE ORIGINAL MATRIX. C ML INTEGER C NUMBER OF DIAGONALS BELOW THE MAIN DIAGONAL. C 0 .LE. ML .LT. N . C MU INTEGER C NUMBER OF DIAGONALS ABOVE THE MAIN DIAGONAL. C 0 .LE. MU .LT. N . C MORE EFFICIENT IF ML .LE. MU . C ON RETURN C ABD AN UPPER TRIANGULAR MATRIX IN BAND STORAGE AND C THE MULTIPLIERS WHICH WERE USED TO OBTAIN IT. C THE FACTORIZATION CAN BE WRITTEN A = L*U WHERE C L IS A PRODUCT OF PERMUTATION AND UNIT LOWER C TRIANGULAR MATRICES AND U IS UPPER TRIANGULAR. C IPVT INTEGER(N) C AN INTEGER VECTOR OF PIVOT INDICES. C RCOND REAL C AN ESTIMATE OF THE RECIPROCAL CONDITION OF A . C FOR THE SYSTEM A*X = B , RELATIVE PERTURBATIONS C IN A AND B OF SIZE EPSILON MAY CAUSE C RELATIVE PERTURBATIONS IN X OF SIZE EPSILON/RCOND . C IF RCOND IS SO SMALL THAT THE LOGICAL EXPRESSION C 1.0 + RCOND .EQ. 1.0 C IS TRUE, THEN A MAY BE SINGULAR TO WORKING C PRECISION. IN PARTICULAR, RCOND IS ZERO IF C EXACT SINGULARITY IS DETECTED OR THE ESTIMATE C UNDERFLOWS. C Z REAL(N) C A WORK VECTOR WHOSE CONTENTS ARE USUALLY UNIMPORTANT. C IF A IS CLOSE TO A SINGULAR MATRIX, THEN Z IS C AN APPROXIMATE NULL VECTOR IN THE SENSE THAT C NORM(A*Z) = RCOND*NORM(A)*NORM(Z) . C BAND STORAGE C IF A IS A BAND MATRIX, THE FOLLOWING PROGRAM SEGMENT C WILL SET UP THE INPUT. C ML = (BAND WIDTH BELOW THE DIAGONAL) C MU = (BAND WIDTH ABOVE THE DIAGONAL) C M = ML + MU + 1 C DO 20 J = 1, N C I1 = MAX0(1, J-MU) C I2 = MIN0(N, J+ML) C DO 10 I = I1, I2 C K = I - J + M C ABD(K,J) = A(I,J) C 10 CONTINUE C 20 CONTINUE C THIS USES ROWS ML+1 THROUGH 2*ML+MU+1 OF ABD . C IN ADDITION, THE FIRST ML ROWS IN ABD ARE USED FOR C ELEMENTS GENERATED DURING THE TRIANGULARIZATION. C THE TOTAL NUMBER OF ROWS NEEDED IN ABD IS 2*ML+MU+1 . C THE ML+MU BY ML+MU UPPER LEFT TRIANGLE AND THE C ML BY ML LOWER RIGHT TRIANGLE ARE NOT REFERENCED. C EXAMPLE: IF THE ORIGINAL MATRIX IS C 11 12 13 0 0 0 C 21 22 23 24 0 0 C 0 32 33 34 35 0 C 0 0 43 44 45 46 C 0 0 0 54 55 56 C 0 0 0 0 65 66 C THEN N = 6, ML = 1, MU = 2, LDA .GE. 5 AND ABD SHOULD CONTAIN C * * * + + + , * = NOT USED C * * 13 24 35 46 , + = USED FOR PIVOTING C * 12 23 34 45 56 C 11 22 33 44 55 66 C 21 32 43 54 65 * C ROUTINES CALLED: FROM LINPACK: SGBFA C FROM BLAS: SAXPY, SDOT, SSCAL, SASUM C FROM FORTRAN: ABS, AMAX1, MAX0, MIN0, SIGN EXTERNAL SGBFA, SAXPY, SDOT, SASUM, SSCAL INTEGER LDA, N, ML, MU, IPVT(*) REAL ABD(LDA,*), Z(*) REAL RCOND REAL SDOT, EK, T, WK, WKM REAL ANORM, S, SASUM, SM, YNORM INTEGER IS, INFO, J, JU, K, KB, KP1, L, LA, LM, LZ, M, MM C ** COMPUTE 1-NORM OF A ANORM = 0.0E0 L = ML + 1 IS = L + MU DO 10 J = 1, N ANORM = AMAX1(ANORM, SASUM(L,ABD(IS,J), 1)) IF (IS .GT. ML + 1) IS = IS - 1 IF (J .LE. MU) L = L + 1 IF (J .GE. N - ML) L = L - 1 10 CONTINUE C ** FACTOR CALL SGBFA(ABD, LDA, N, ML, MU, IPVT, INFO) C RCOND = 1/(NORM(A)*(ESTIMATE OF NORM(INVERSE(A)))) . C ESTIMATE = NORM(Z)/NORM(Y) WHERE A*Z = Y AND TRANS(A)*Y = E . C TRANS(A) IS THE TRANSPOSE OF A . THE COMPONENTS OF E ARE C CHOSEN TO CAUSE MAXIMUM LOCAL GROWTH IN THE ELEMENTS OF W WHERE C TRANS(U)*W = E . THE VECTORS ARE FREQUENTLY RESCALED TO AVOID C OVERFLOW. C ** SOLVE TRANS(U)*W = E EK = 1.0E0 DO 20 J = 1, N Z(J) = 0.0E0 20 CONTINUE M = ML + MU + 1 JU = 0 DO 100 K = 1, N IF (Z(K) .NE. 0.0E0) EK = SIGN(EK, -Z(K)) IF (ABS(EK-Z(K)) .GT. ABS(ABD(M,K))) THEN S = ABS(ABD(M,K))/ABS(EK-Z(K)) CALL SSCAL(N, S, Z, 1) EK = S*EK ENDIF WK = EK - Z(K) WKM = -EK - Z(K) S = ABS(WK) SM = ABS(WKM) IF (ABD(M,K) .NE. 0.0E0) THEN WK = WK /ABD(M,K) WKM = WKM/ABD(M,K) ELSE WK = 1.0E0 WKM = 1.0E0 ENDIF KP1 = K + 1 JU = MIN0(MAX0(JU, MU+IPVT(K)), N) MM = M IF (KP1 .LE. JU) THEN DO 60 J = KP1, JU MM = MM - 1 SM = SM + ABS(Z(J)+WKM*ABD(MM,J)) Z(J) = Z(J) + WK*ABD(MM,J) S = S + ABS(Z(J)) 60 CONTINUE IF (S .LT. SM) THEN T = WKM - WK WK = WKM MM = M DO 70 J = KP1, JU MM = MM - 1 Z(J) = Z(J) + T*ABD(MM,J) 70 CONTINUE ENDIF ENDIF Z(K) = WK 100 CONTINUE S = 1.0E0 / SASUM(N, Z, 1) CALL SSCAL(N, S, Z, 1) C ** SOLVE TRANS(L)*Y = W DO 120 KB = 1, N K = N + 1 - KB LM = MIN0(ML, N-K) IF (K .LT. N) Z(K) = Z(K) + SDOT(LM, ABD(M+1,K), 1, Z(K+1), 1) IF (ABS(Z(K)) .GT. 1.0E0) THEN S = 1.0E0 / ABS(Z(K)) CALL SSCAL(N, S, Z, 1) ENDIF L = IPVT(K) T = Z(L) Z(L) = Z(K) Z(K) = T 120 CONTINUE S = 1.0E0 / SASUM(N, Z, 1) CALL SSCAL(N, S, Z, 1) YNORM = 1.0E0 C ** SOLVE L*V = Y DO 140 K = 1, N L = IPVT(K) T = Z(L) Z(L) = Z(K) Z(K) = T LM = MIN0(ML, N-K) IF (K .LT. N) CALL SAXPY(LM, T, ABD(M+1,K), 1, Z(K+1), 1) IF (ABS(Z(K)) .GT. 1.0E0) THEN S = 1.0E0 / ABS(Z(K)) CALL SSCAL(N, S, Z, 1) YNORM = S*YNORM ENDIF 140 CONTINUE S = 1.0E0/SASUM(N, Z, 1) CALL SSCAL(N, S, Z, 1) YNORM = S*YNORM C ** SOLVE U*Z = W DO 160 KB = 1, N K = N + 1 - KB IF (ABS(Z(K)) .GT. ABS(ABD(M,K))) THEN S = ABS(ABD(M,K)) / ABS(Z(K)) CALL SSCAL(N, S, Z, 1) YNORM = S*YNORM ENDIF IF (ABD(M,K) .NE. 0.0E0) Z(K) = Z(K)/ABD(M,K) IF (ABD(M,K) .EQ. 0.0E0) Z(K) = 1.0E0 LM = MIN0(K, M) - 1 LA = M - LM LZ = K - LM T = -Z(K) CALL SAXPY(LM, T, ABD(LA,K), 1, Z(LZ), 1) 160 CONTINUE C ** MAKE ZNORM = 1.0 S = 1.0E0 / SASUM(N, Z, 1) CALL SSCAL(N, S, Z, 1) YNORM = S*YNORM IF (ANORM .NE. 0.0E0) RCOND = YNORM/ANORM IF (ANORM .EQ. 0.0E0) RCOND = 0.0E0 RETURN END SUBROUTINE SGBFA( ABD, LDA, N, ML, MU, IPVT, INFO ) C FACTORS A REAL BAND MATRIX BY ELIMINATION. C REVISION DATE: 8/1/82 C AUTHOR: MOLER, C. B., (U. OF NEW MEXICO) C SGBFA IS USUALLY CALLED BY SBGCO, BUT IT CAN BE CALLED C DIRECTLY WITH A SAVING IN TIME IF RCOND IS NOT NEEDED. C INPUT: SAME AS 'SGBCO' C ON RETURN: C ABD,IPVT SAME AS 'SGBCO' C INFO INTEGER C = 0 NORMAL VALUE. C = K IF U(K,K) .EQ. 0.0 . THIS IS NOT AN ERROR C CONDITION FOR THIS SUBROUTINE, BUT IT DOES C INDICATE THAT SGBSL WILL DIVIDE BY ZERO IF C CALLED. USE RCOND IN SBGCO FOR A RELIABLE C INDICATION OF SINGULARITY. C (SEE 'SGBCO' FOR DESCRIPTION OF BAND STORAGE MODE) C ROUTINES CALLED: FROM BLAS: SAXPY, SSCAL, ISAMAX C FROM FORTRAN: MAX0, MIN0 EXTERNAL SAXPY, SSCAL, ISAMAX INTEGER LDA, N, ML, MU, IPVT(*), INFO REAL ABD(LDA,*) REAL T INTEGER I,ISAMAX,I0,J,JU,JZ,J0,J1,K,KP1,L,LM,M,MM,NM1 M = ML + MU + 1 INFO = 0 C ** ZERO INITIAL FILL-IN COLUMNS J0 = MU + 2 J1 = MIN0(N, M) - 1 DO 20 JZ = J0, J1 I0 = M + 1 - JZ DO 10 I = I0, ML ABD(I,JZ) = 0.0E0 10 CONTINUE 20 CONTINUE JZ = J1 JU = 0 C ** GAUSSIAN ELIMINATION WITH PARTIAL PIVOTING NM1 = N - 1 DO 120 K = 1, NM1 KP1 = K + 1 C ** ZERO NEXT FILL-IN COLUMN JZ = JZ + 1 IF (JZ .LE. N) THEN DO 40 I = 1, ML ABD(I,JZ) = 0.0E0 40 CONTINUE ENDIF C ** FIND L = PIVOT INDEX LM = MIN0(ML, N-K) L = ISAMAX(LM+1, ABD(M,K), 1) + M - 1 IPVT(K) = L + K - M IF (ABD(L,K) .EQ. 0.0E0) THEN C ** ZERO PIVOT IMPLIES THIS COLUMN C ** ALREADY TRIANGULARIZED INFO = K ELSE C ** INTERCHANGE IF NECESSARY IF (L .NE. M) THEN T = ABD(L,K) ABD(L,K) = ABD(M,K) ABD(M,K) = T ENDIF C ** COMPUTE MULTIPLIERS T = -1.0E0 / ABD(M,K) CALL SSCAL(LM, T, ABD(M+1,K), 1) C ** ROW ELIMINATION WITH COLUMN INDEXING JU = MIN0(MAX0(JU, MU+IPVT(K)), N) MM = M DO 80 J = KP1, JU L = L - 1 MM = MM - 1 T = ABD(L,J) IF (L .NE. MM) THEN ABD(L,J) = ABD(MM,J) ABD(MM,J) = T ENDIF CALL SAXPY(LM, T, ABD(M+1,K), 1, ABD(MM+1,J), 1) 80 CONTINUE ENDIF 120 CONTINUE IPVT(N) = N IF (ABD(M,N) .EQ. 0.0E0) INFO = N RETURN END SUBROUTINE SGBSL( ABD, LDA, N, ML, MU, IPVT, B, JOB ) C SOLVES THE REAL BAND SYSTEM C A * X = B OR TRANSPOSE(A) * X = B C USING THE FACTORS COMPUTED BY SBGCO OR SGBFA. C REVISION DATE: 8/1/82 C AUTHOR: MOLER, C. B., (U. OF NEW MEXICO) C INPUT: C ABD REAL(LDA, N) C THE OUTPUT FROM SBGCO OR SGBFA. C LDA INTEGER C THE LEADING DIMENSION OF THE ARRAY ABD . C N INTEGER C THE ORDER OF THE ORIGINAL MATRIX. C ML INTEGER C NUMBER OF DIAGONALS BELOW THE MAIN DIAGONAL. C MU INTEGER C NUMBER OF DIAGONALS ABOVE THE MAIN DIAGONAL. C IPVT INTEGER(N) C THE PIVOT VECTOR FROM SBGCO OR SGBFA. C B REAL(N) C THE RIGHT HAND SIDE VECTOR. C JOB INTEGER C = 0 TO SOLVE A*X = B , C = NONZERO TO SOLVE TRANS(A)*X = B , WHERE C TRANS(A) IS THE TRANSPOSE. C ON RETURN C B THE SOLUTION VECTOR X . C ERROR CONDITION C A DIVISION BY ZERO WILL OCCUR IF THE INPUT FACTOR CONTAINS A C ZERO ON THE DIAGONAL. TECHNICALLY, THIS INDICATES SINGULARITY, C BUT IT IS OFTEN CAUSED BY IMPROPER ARGUMENTS OR IMPROPER C SETTING OF LDA . IT WILL NOT OCCUR IF THE SUBROUTINES ARE C CALLED CORRECTLY AND IF SBGCO HAS SET RCOND .GT. 0.0 C OR SGBFA HAS SET INFO .EQ. 0 . C TO COMPUTE INVERSE(A) * C WHERE C IS A MATRIX C WITH P COLUMNS C CALL SGBCO(ABD,LDA,N,ML,MU,IPVT,RCOND,Z) C IF (RCOND IS TOO SMALL) GO TO ... C DO 10 J = 1, P C CALL SGBSL(ABD,LDA,N,ML,MU,IPVT,C(1,J),0) C 10 CONTINUE C ROUTINES CALLED: FROM BLAS: SAXPY, SDOT C FROM FORTRAN: MIN0 EXTERNAL SAXPY, SDOT INTEGER LDA, N, ML, MU, IPVT(*), JOB REAL ABD(LDA,*), B(*) REAL SDOT,T INTEGER K,KB,L,LA,LB,LM,M,NM1 M = MU + ML + 1 NM1 = N - 1 IF (JOB .EQ. 0) THEN C ** JOB = 0 , SOLVE A * X = B C ** FIRST SOLVE L*Y = B IF (ML .NE. 0) THEN DO 20 K = 1, NM1 LM = MIN0(ML, N-K) L = IPVT(K) T = B(L) IF (L .NE. K) THEN B(L) = B(K) B(K) = T ENDIF CALL SAXPY( LM, T, ABD(M+1,K), 1, B(K+1), 1 ) 20 CONTINUE ENDIF C ** NOW SOLVE U*X = Y DO 40 KB = 1, N K = N + 1 - KB B(K) = B(K) / ABD(M,K) LM = MIN0(K, M) - 1 LA = M - LM LB = K - LM T = -B(K) CALL SAXPY(LM, T, ABD(LA,K), 1, B(LB), 1) 40 CONTINUE ELSE C ** JOB = NONZERO, SOLVE TRANS(A) * X = B C ** FIRST SOLVE TRANS(U)*Y = B DO 60 K = 1, N LM = MIN0(K, M) - 1 LA = M - LM LB = K - LM T = SDOT(LM, ABD(LA,K), 1, B(LB), 1) B(K) = (B(K) - T)/ABD(M,K) 60 CONTINUE C ** NOW SOLVE TRANS(L)*X = Y IF (ML .NE. 0) THEN DO 80 KB = 1, NM1 K = N - KB LM = MIN0(ML, N-K) B(K) = B(K) + SDOT(LM, ABD(M+1,K), 1, B(K+1), 1) L = IPVT(K) IF (L .NE. K) THEN T = B(L) B(L) = B(K) B(K) = T ENDIF 80 CONTINUE ENDIF ENDIF RETURN END SUBROUTINE SGECO( A, LDA, N,IPVT, RCOND, Z ) C FACTORS A REAL MATRIX BY GAUSSIAN ELIMINATION C AND ESTIMATES THE CONDITION OF THE MATRIX. C REVISION DATE: 8/1/82 C AUTHOR: MOLER, C. B., (U. OF NEW MEXICO) C IF RCOND IS NOT NEEDED, SGEFA IS SLIGHTLY FASTER. C TO SOLVE A*X = B , FOLLOW SGECO BY SGESL. C ON ENTRY C A REAL(LDA, N) C THE MATRIX TO BE FACTORED. C LDA INTEGER C THE LEADING DIMENSION OF THE ARRAY A . C N INTEGER C THE ORDER OF THE MATRIX A . C ON RETURN C A AN UPPER TRIANGULAR MATRIX AND THE MULTIPLIERS C WHICH WERE USED TO OBTAIN IT. C THE FACTORIZATION CAN BE WRITTEN A = L*U , WHERE C L IS A PRODUCT OF PERMUTATION AND UNIT LOWER C TRIANGULAR MATRICES AND U IS UPPER TRIANGULAR. C IPVT INTEGER(N) C AN INTEGER VECTOR OF PIVOT INDICES. C RCOND REAL C AN ESTIMATE OF THE RECIPROCAL CONDITION OF A . C FOR THE SYSTEM A*X = B , RELATIVE PERTURBATIONS C IN A AND B OF SIZE EPSILON MAY CAUSE C RELATIVE PERTURBATIONS IN X OF SIZE EPSILON/RCOND . C IF RCOND IS SO SMALL THAT THE LOGICAL EXPRESSION C 1.0 + RCOND .EQ. 1.0 C IS TRUE, THEN A MAY BE SINGULAR TO WORKING C PRECISION. IN PARTICULAR, RCOND IS ZERO IF C EXACT SINGULARITY IS DETECTED OR THE ESTIMATE C UNDERFLOWS. C Z REAL(N) C A WORK VECTOR WHOSE CONTENTS ARE USUALLY UNIMPORTANT. C IF A IS CLOSE TO A SINGULAR MATRIX, THEN Z IS C AN APPROXIMATE NULL VECTOR IN THE SENSE THAT C NORM(A*Z) = RCOND*NORM(A)*NORM(Z) . C ROUTINES CALLED: FROM LINPACK: SGEFA C FROM BLAS: SAXPY, SDOT, SSCAL, SASUM C FROM FORTRAN: ABS, AMAX1, SIGN EXTERNAL SGEFA, SAXPY, SDOT, SSCAL, SASUM INTEGER LDA, N, IPVT(*) REAL A(LDA,*), Z(*) REAL RCOND REAL SDOT,EK,T,WK,WKM REAL ANORM,S,SASUM,SM,YNORM INTEGER INFO,J,K,KB,KP1,L C ** COMPUTE 1-NORM OF A ANORM = 0.0E0 DO 10 J = 1, N ANORM = AMAX1( ANORM, SASUM(N,A(1,J),1) ) 10 CONTINUE C ** FACTOR CALL SGEFA(A,LDA,N,IPVT,INFO) C RCOND = 1/(NORM(A)*(ESTIMATE OF NORM(INVERSE(A)))) . C ESTIMATE = NORM(Z)/NORM(Y) WHERE A*Z = Y AND TRANS(A)*Y = E . C TRANS(A) IS THE TRANSPOSE OF A . THE COMPONENTS OF E ARE C CHOSEN TO CAUSE MAXIMUM LOCAL GROWTH IN THE ELEMENTS OF W WHERE C TRANS(U)*W = E . THE VECTORS ARE FREQUENTLY RESCALED TO AVOID C OVERFLOW. C ** SOLVE TRANS(U)*W = E EK = 1.0E0 DO 20 J = 1, N Z(J) = 0.0E0 20 CONTINUE DO 100 K = 1, N IF (Z(K) .NE. 0.0E0) EK = SIGN(EK, -Z(K)) IF (ABS(EK-Z(K)) .GT. ABS(A(K,K))) THEN S = ABS(A(K,K)) / ABS(EK-Z(K)) CALL SSCAL(N, S, Z, 1) EK = S*EK ENDIF WK = EK - Z(K) WKM = -EK - Z(K) S = ABS(WK) SM = ABS(WKM) IF (A(K,K) .NE. 0.0E0) THEN WK = WK / A(K,K) WKM = WKM / A(K,K) ELSE WK = 1.0E0 WKM = 1.0E0 ENDIF KP1 = K + 1 IF (KP1 .LE. N) THEN DO 60 J = KP1, N SM = SM + ABS(Z(J)+WKM*A(K,J)) Z(J) = Z(J) + WK*A(K,J) S = S + ABS(Z(J)) 60 CONTINUE IF (S .LT. SM) THEN T = WKM - WK WK = WKM DO 70 J = KP1, N Z(J) = Z(J) + T*A(K,J) 70 CONTINUE ENDIF ENDIF Z(K) = WK 100 CONTINUE S = 1.0E0 / SASUM(N, Z, 1) CALL SSCAL(N, S, Z, 1) C ** SOLVE TRANS(L)*Y = W DO 120 KB = 1, N K = N + 1 - KB IF (K .LT. N) Z(K) = Z(K) + SDOT(N-K, A(K+1,K), 1, Z(K+1), 1) IF (ABS(Z(K)) .GT. 1.0E0) THEN S = 1.0E0/ABS(Z(K)) CALL SSCAL(N, S, Z, 1) ENDIF L = IPVT(K) T = Z(L) Z(L) = Z(K) Z(K) = T 120 CONTINUE S = 1.0E0 / SASUM(N, Z, 1) CALL SSCAL(N, S, Z, 1) C ** SOLVE L*V = Y YNORM = 1.0E0 DO 140 K = 1, N L = IPVT(K) T = Z(L) Z(L) = Z(K) Z(K) = T IF (K .LT. N) CALL SAXPY(N-K, T, A(K+1,K), 1, Z(K+1), 1) IF (ABS(Z(K)) .GT. 1.0E0) THEN S = 1.0E0/ABS(Z(K)) CALL SSCAL(N, S, Z, 1) YNORM = S*YNORM ENDIF 140 CONTINUE S = 1.0E0 / SASUM(N, Z, 1) CALL SSCAL(N, S, Z, 1) C ** SOLVE U*Z = V YNORM = S*YNORM DO 160 KB = 1, N K = N + 1 - KB IF (ABS(Z(K)) .GT. ABS(A(K,K))) THEN S = ABS(A(K,K))/ABS(Z(K)) CALL SSCAL(N, S, Z, 1) YNORM = S*YNORM ENDIF IF (A(K,K) .NE. 0.0E0) Z(K) = Z(K)/A(K,K) IF (A(K,K) .EQ. 0.0E0) Z(K) = 1.0E0 T = -Z(K) CALL SAXPY(K-1, T, A(1,K), 1, Z(1), 1) 160 CONTINUE C ** MAKE ZNORM = 1.0 S = 1.0E0 / SASUM(N, Z, 1) CALL SSCAL(N, S, Z, 1) YNORM = S*YNORM IF (ANORM .NE. 0.0E0) RCOND = YNORM/ANORM IF (ANORM .EQ. 0.0E0) RCOND = 0.0E0 RETURN END SUBROUTINE SGEFA( A, LDA, N, IPVT, INFO ) C FACTORS A REAL MATRIX BY GAUSSIAN ELIMINATION. C REVISION DATE: 8/1/82 C AUTHOR: MOLER, C. B., (U. OF NEW MEXICO) C SGEFA IS USUALLY CALLED BY SGECO, BUT IT CAN BE CALLED C DIRECTLY WITH A SAVING IN TIME IF RCOND IS NOT NEEDED. C (TIME FOR SGECO) = (1 + 9/N)*(TIME FOR SGEFA) . C INPUT: SAME AS 'SGECO' C ON RETURN: C A,IPVT SAME AS 'SGECO' C INFO INTEGER C = 0 NORMAL VALUE. C = K IF U(K,K) .EQ. 0.0 . THIS IS NOT AN ERROR C CONDITION FOR THIS SUBROUTINE, BUT IT DOES C INDICATE THAT SGESL OR SGEDI WILL DIVIDE BY ZERO C IF CALLED. USE RCOND IN SGECO FOR A RELIABLE C INDICATION OF SINGULARITY. C ROUTINES CALLED: FROM BLAS: SAXPY, SSCAL, ISAMAX EXTERNAL SAXPY, SSCAL, ISAMAX INTEGER LDA, N, IPVT(*), INFO REAL A(LDA,*) REAL T INTEGER ISAMAX,J,K,KP1,L,NM1 C ** GAUSSIAN ELIMINATION WITH PARTIAL PIVOTING INFO = 0 NM1 = N - 1 DO 60 K = 1, NM1 KP1 = K + 1 C ** FIND L = PIVOT INDEX L = ISAMAX( N-K+1, A(K,K), 1) + K-1 IPVT(K) = L IF (A(L,K) .EQ. 0.0E0) THEN C ** ZERO PIVOT IMPLIES THIS COLUMN C ** ALREADY TRIANGULARIZED INFO = K ELSE C ** INTERCHANGE IF NECESSARY IF (L .NE. K) THEN T = A(L,K) A(L,K) = A(K,K) A(K,K) = T ENDIF C ** COMPUTE MULTIPLIERS T = -1.0E0 / A(K,K) CALL SSCAL( N-K, T, A(K+1,K), 1 ) C ** ROW ELIMINATION WITH COLUMN INDEXING DO 30 J = KP1, N T = A(L,J) IF (L .NE. K) THEN A(L,J) = A(K,J) A(K,J) = T ENDIF CALL SAXPY( N-K, T, A(K+1,K), 1, A(K+1,J), 1 ) 30 CONTINUE ENDIF 60 CONTINUE IPVT(N) = N IF (A(N,N) .EQ. 0.0E0) INFO = N RETURN END SUBROUTINE SGESL( A, LDA, N,IPVT, B, JOB ) C SOLVES THE REAL SYSTEM C A * X = B OR TRANS(A) * X = B C USING THE FACTORS COMPUTED BY SGECO OR SGEFA. C REVISION DATE: 8/1/82 C AUTHOR: MOLER, C. B., (U. OF NEW MEXICO) C ON ENTRY C A REAL(LDA, N) C THE OUTPUT FROM SGECO OR SGEFA. C LDA INTEGER C THE LEADING DIMENSION OF THE ARRAY A . C N INTEGER C THE ORDER OF THE MATRIX A . C IPVT INTEGER(N) C THE PIVOT VECTOR FROM SGECO OR SGEFA. C B REAL(N) C THE RIGHT HAND SIDE VECTOR. C JOB INTEGER C = 0 TO SOLVE A*X = B , C = NONZERO TO SOLVE TRANS(A)*X = B WHERE C TRANS(A) IS THE TRANSPOSE. C ON RETURN C B THE SOLUTION VECTOR X . C ERROR CONDITION C A DIVISION BY ZERO WILL OCCUR IF THE INPUT FACTOR CONTAINS A C ZERO ON THE DIAGONAL. TECHNICALLY, THIS INDICATES SINGULARITY, C BUT IT IS OFTEN CAUSED BY IMPROPER ARGUMENTS OR IMPROPER C SETTING OF LDA . IT WILL NOT OCCUR IF THE SUBROUTINES ARE C CALLED CORRECTLY AND IF SGECO HAS SET RCOND .GT. 0.0 C OR SGEFA HAS SET INFO .EQ. 0 . C TO COMPUTE INVERSE(A) * C WHERE C IS A MATRIX C WITH P COLUMNS C CALL SGECO(A,LDA,N,IPVT,RCOND,Z) C IF (RCOND IS TOO SMALL) GO TO ... C DO 10 J = 1, P C CALL SGESL(A,LDA,N,IPVT,C(1,J),0) C 10 CONTINUE C ROUTINES CALLED: FROM BLAS: SAXPY, SDOT EXTERNAL SAXPY, SDOT INTEGER LDA, N, IPVT(*), JOB REAL A(LDA,*), B(*) REAL SDOT,T INTEGER K,KB,L,NM1 NM1 = N - 1 IF (JOB .EQ. 0) THEN C ** JOB = 0 , SOLVE A * X = B C ** FIRST SOLVE L*Y = B DO 20 K = 1, NM1 L = IPVT(K) T = B(L) IF (L .NE. K) THEN B(L) = B(K) B(K) = T ENDIF CALL SAXPY( N-K, T, A(K+1,K), 1, B(K+1), 1 ) 20 CONTINUE C ** NOW SOLVE U*X = Y DO 40 KB = 1, N K = N + 1 - KB B(K) = B(K) / A(K,K) T = -B(K) CALL SAXPY( K-1, T, A(1,K), 1, B(1), 1 ) 40 CONTINUE ELSE C ** JOB = NONZERO, SOLVE TRANS(A) * X = B C ** FIRST SOLVE TRANS(U)*Y = B DO 60 K = 1, N T = SDOT( K-1, A(1,K), 1, B(1), 1 ) B(K) = (B(K) - T) / A(K,K) 60 CONTINUE C ** NOW SOLVE TRANS(L)*X = Y DO 80 KB = 1, NM1 K = N - KB B(K) = B(K) + SDOT( N-K, A(K+1,K), 1, B(K+1), 1 ) L = IPVT(K) IF (L .NE. K) THEN T = B(L) B(L) = B(K) B(K) = T ENDIF 80 CONTINUE ENDIF RETURN END c REAL FUNCTION SASUM( N, SX, INCX ) C ############################## FUNCTION SASUM(N,SX,INCX) C ############################## C --INPUT-- N NUMBER OF ELEMENTS IN VECTOR TO BE SUMMED C SX SING-PREC ARRAY, LENGTH 1+(N-1)*INCX, CONTAINING VECTOR C INCX SPACING OF VECTOR ELEMENTS IN 'SX' C --OUTPUT-- SASUM SUM FROM 0 TO N-1 OF ABS(SX(1+I*INCX)) IMPLICIT NONE REAL SASUM REAL SX(*) INTEGER N, INCX INTEGER I, M SASUM = 0.0 IF( N.LE.0 ) RETURN IF( INCX.NE.1 ) THEN C ** NON-UNIT INCREMENTS DO 10 I = 1, 1+(N-1)*INCX, INCX SASUM = SASUM + ABS(SX(I)) 10 CONTINUE ELSE C ** UNIT INCREMENTS M = MOD(N,6) IF( M.NE.0 ) THEN C ** CLEAN-UP LOOP SO REMAINING VECTOR C ** LENGTH IS A MULTIPLE OF 6. DO 30 I = 1, M SASUM = SASUM + ABS(SX(I)) 30 CONTINUE ENDIF C ** UNROLL LOOP FOR SPEED DO 50 I = M+1, N, 6 SASUM = SASUM + ABS(SX(I)) + ABS(SX(I+1)) + ABS(SX(I+2)) $ + ABS(SX(I+3)) + ABS(SX(I+4)) + ABS(SX(I+5)) 50 CONTINUE ENDIF RETURN END SUBROUTINE SAXPY( N, SA, SX, INCX, SY, INCY ) C Y = A*X + Y (X, Y = VECTORS, A = SCALAR) C --INPUT-- C N NUMBER OF ELEMENTS IN INPUT VECTORS 'X' AND 'Y' C SA SINGLE PRECISION SCALAR MULTIPLIER 'A' C SX SING-PREC ARRAY CONTAINING VECTOR 'X' C INCX SPACING OF ELEMENTS OF VECTOR 'X' IN 'SX' C SY SING-PREC ARRAY CONTAINING VECTOR 'Y' C INCY SPACING OF ELEMENTS OF VECTOR 'Y' IN 'SY' C --OUTPUT-- C SY FOR I = 0 TO N-1, OVERWRITE SY(LY+I*INCY) WITH C SA*SX(LX+I*INCX) + SY(LY+I*INCY), C WHERE LX = 1 IF INCX .GE. 0, C = (-INCX)*N IF INCX .LT. 0 C AND LY IS DEFINED IN A SIMILAR WAY USING INCY. REAL SX(*), SY(*), SA IF( N.LE.0 .OR. SA.EQ.0.0 ) RETURN IF ( INCX.EQ.INCY .AND. INCX.GT.1 ) THEN DO 10 I = 1, 1+(N-1)*INCX, INCX SY(I) = SY(I) + SA * SX(I) 10 CONTINUE ELSE IF ( INCX.EQ.INCY .AND. INCX.EQ.1 ) THEN C ** EQUAL, UNIT INCREMENTS M = MOD(N,4) IF( M .NE. 0 ) THEN C ** CLEAN-UP LOOP SO REMAINING VECTOR LENGTH C ** IS A MULTIPLE OF 4. DO 20 I = 1, M SY(I) = SY(I) + SA * SX(I) 20 CONTINUE ENDIF C ** UNROLL LOOP FOR SPEED DO 30 I = M+1, N, 4 SY(I) = SY(I) + SA * SX(I) SY(I+1) = SY(I+1) + SA * SX(I+1) SY(I+2) = SY(I+2) + SA * SX(I+2) SY(I+3) = SY(I+3) + SA * SX(I+3) 30 CONTINUE ELSE C ** NONEQUAL OR NONPOSITIVE INCREMENTS. IX = 1 IY = 1 IF( INCX.LT.0 ) IX = 1 + (N-1)*(-INCX) IF( INCY.LT.0 ) IY = 1 + (N-1)*(-INCY) DO 40 I = 1, N SY(IY) = SY(IY) + SA*SX(IX) IX = IX + INCX IY = IY + INCY 40 CONTINUE ENDIF RETURN END c REAL FUNCTION SDOT( N, SX, INCX, SY, INCY ) C ############################## FUNCTION SDOT( N, SX, INCX, SY, INCY ) C ############################## C S.P. DOT PRODUCT OF VECTORS 'X' AND 'Y' C --INPUT-- C N NUMBER OF ELEMENTS IN INPUT VECTORS 'X' AND 'Y' C SX SING-PREC ARRAY CONTAINING VECTOR 'X' C INCX SPACING OF ELEMENTS OF VECTOR 'X' IN 'SX' C SY SING-PREC ARRAY CONTAINING VECTOR 'Y' C INCY SPACING OF ELEMENTS OF VECTOR 'Y' IN 'SY' C --OUTPUT-- C SDOT SUM FOR I = 0 TO N-1 OF SX(LX+I*INCX) * SY(LY+I*INCY), C WHERE LX = 1 IF INCX .GE. 0, C = (-INCX)*N IF INCX .LT. 0, C AND LY IS DEFINED IN A SIMILAR WAY USING INCY. IMPLICIT NONE INTEGER N,INCX,INCY REAL SX(*), SY(*) REAL SDOT INTEGER I,M, IX, IY SDOT = 0.0 IF( N.LE.0 ) RETURN IF ( INCX.EQ.INCY .AND. INCX.GT.1 ) THEN DO 10 I = 1, 1+(N-1)*INCX, INCX SDOT = SDOT + SX(I) * SY(I) 10 CONTINUE ELSE IF ( INCX.EQ.INCY .AND. INCX.EQ.1 ) THEN C ** EQUAL, UNIT INCREMENTS M = MOD(N,5) IF( M .NE. 0 ) THEN C ** CLEAN-UP LOOP SO REMAINING VECTOR LENGTH C ** IS A MULTIPLE OF 4. DO 20 I = 1, M SDOT = SDOT + SX(I) * SY(I) 20 CONTINUE ENDIF C ** UNROLL LOOP FOR SPEED DO 30 I = M+1, N, 5 SDOT = SDOT + SX(I)*SY(I) + SX(I+1)*SY(I+1) $ + SX(I+2)*SY(I+2) + SX(I+3)*SY(I+3) $ + SX(I+4)*SY(I+4) 30 CONTINUE ELSE C ** NONEQUAL OR NONPOSITIVE INCREMENTS. IX = 1 IY = 1 IF( INCX.LT.0 ) IX = 1 + (N-1)*(-INCX) IF( INCY.LT.0 ) IY = 1 + (N-1)*(-INCY) DO 40 I = 1, N SDOT = SDOT + SX(IX) * SY(IY) IX = IX + INCX IY = IY + INCY 40 CONTINUE ENDIF RETURN END SUBROUTINE SSCAL( N, SA, SX, INCX ) C CALCULATE X = A*X (X = VECTOR, A = SCALAR) C --INPUT-- N NUMBER OF ELEMENTS IN VECTOR C SA SINGLE PRECISION SCALE FACTOR C SX SING-PREC ARRAY, LENGTH 1+(N-1)*INCX, CONTAINING VECTOR C INCX SPACING OF VECTOR ELEMENTS IN 'SX' C --OUTPUT-- SX REPLACE SX(1+I*INCX) WITH SA * SX(1+I*INCX) C FOR I = 0 TO N-1 REAL SA, SX(*) IF( N.LE.0 ) RETURN IF( INCX.NE.1 ) THEN DO 10 I = 1, 1+(N-1)*INCX, INCX SX(I) = SA * SX(I) 10 CONTINUE ELSE M = MOD(N,5) IF( M.NE.0 ) THEN C ** CLEAN-UP LOOP SO REMAINING VECTOR LENGTH C ** IS A MULTIPLE OF 5. DO 30 I = 1, M SX(I) = SA * SX(I) 30 CONTINUE ENDIF C ** UNROLL LOOP FOR SPEED DO 50 I = M+1, N, 5 SX(I) = SA * SX(I) SX(I+1) = SA * SX(I+1) SX(I+2) = SA * SX(I+2) SX(I+3) = SA * SX(I+3) SX(I+4) = SA * SX(I+4) 50 CONTINUE ENDIF RETURN END SUBROUTINE SSWAP( N, SX, INCX, SY, INCY ) C INTERCHANGE S.P VECTORS X AND Y C --INPUT-- C N NUMBER OF ELEMENTS IN INPUT VECTORS 'X' AND 'Y' C SX SING-PREC ARRAY CONTAINING VECTOR 'X' C INCX SPACING OF ELEMENTS OF VECTOR 'X' IN 'SX' C SY SING-PREC ARRAY CONTAINING VECTOR 'Y' C INCY SPACING OF ELEMENTS OF VECTOR 'Y' IN 'SY' C --OUTPUT-- C SX INPUT VECTOR SY (UNCHANGED IF N .LE. 0) C SY INPUT VECTOR SX (UNCHANGED IF N .LE. 0) C FOR I = 0 TO N-1, INTERCHANGE SX(LX+I*INCX) AND SY(LY+I*INCY), C WHERE LX = 1 IF INCX .GE. 0, C = (-INCX)*N IF INCX .LT. 0 C AND LY IS DEFINED IN A SIMILAR WAY USING INCY. REAL SX(*), SY(*), STEMP1, STEMP2, STEMP3 IF( N.LE.0 ) RETURN IF ( INCX.EQ.INCY .AND. INCX.GT.1 ) THEN DO 10 I = 1, 1+(N-1)*INCX, INCX STEMP1 = SX(I) SX(I) = SY(I) SY(I) = STEMP1 10 CONTINUE ELSE IF ( INCX.EQ.INCY .AND. INCX.EQ.1 ) THEN C ** EQUAL, UNIT INCREMENTS M = MOD(N,3) IF( M .NE. 0 ) THEN C ** CLEAN-UP LOOP SO REMAINING VECTOR LENGTH C ** IS A MULTIPLE OF 3. DO 20 I = 1, M STEMP1 = SX(I) SX(I) = SY(I) SY(I) = STEMP1 20 CONTINUE ENDIF C ** UNROLL LOOP FOR SPEED DO 30 I = M+1, N, 3 STEMP1 = SX(I) STEMP2 = SX(I+1) STEMP3 = SX(I+2) SX(I) = SY(I) SX(I+1) = SY(I+1) SX(I+2) = SY(I+2) SY(I) = STEMP1 SY(I+1) = STEMP2 SY(I+2) = STEMP3 30 CONTINUE ELSE C ** NONEQUAL OR NONPOSITIVE INCREMENTS. IX = 1 IY = 1 IF( INCX.LT.0 ) IX = 1 + (N-1)*(-INCX) IF( INCY.LT.0 ) IY = 1 + (N-1)*(-INCY) DO 40 I = 1, N STEMP1 = SX(IX) SX(IX) = SY(IY) SY(IY) = STEMP1 IX = IX + INCX IY = IY + INCY 40 CONTINUE ENDIF RETURN END c INTEGER FUNCTION ISAMAX( N, SX, INCX ) C ############################## FUNCTION ISAMAX( N, SX, INCX ) C ############################## C --INPUT-- N NUMBER OF ELEMENTS IN VECTOR OF INTEREST C SX SING-PREC ARRAY, LENGTH 1+(N-1)*INCX, CONTAINING VECTOR C INCX SPACING OF VECTOR ELEMENTS IN 'SX' C --OUTPUT-- ISAMAX FIRST I, I = 1 TO N, TO MAXIMIZE C ABS(SX(1+(I-1)*INCX)) IMPLICIT NONE INTEGER ISAMAX, N, INCX REAL SX(*), SMAX, XMAG INTEGER II, I IF( N.LE.0 ) THEN ISAMAX = 0 ELSE IF( N.EQ.1 ) THEN ISAMAX = 1 ELSE SMAX = 0.0 II = 1 DO 20 I = 1, 1+(N-1)*INCX, INCX XMAG = ABS(SX(I)) IF( SMAX.LT.XMAG ) THEN SMAX = XMAG ISAMAX = II ENDIF II = II + 1 20 CONTINUE ENDIF RETURN END C ############################## FUNCTION D1MACH(i) C ############################## *-----------------------------------------------------------------------------* *= PURPOSE: =* *= D1MACH calculates various machine constants in single precision. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= I - INTEGER, identifies the machine constant (0<I<5) (I) =* *= D1MACH - REAL, machine constant in single precision (O) =* *= I=1 - the smallest non-vanishing normalized floating-point =* *= power of the radix, i.e., D1MACH=FLOAT(IBETA)**MINEXP =* *= I=2 - the largest finite floating-point number. In =* *= particular D1MACH=(1.0-EPSNEG)*FLOAT(IBETA)**MAXEXP =* *= Note - on some machines D1MACH will be only the =* *= second, or perhaps third, largest number, being =* *= too small by 1 or 2 units in the last digit of =* *= the significand. =* *= I=3 - A small positive floating-point number such that =* *= 1.0-D1MACH .NE. 1.0. In particular, if IBETA = 2 =* *= or IRND = 0, D1MACH = FLOAT(IBETA)**NEGEPS. =* *= Otherwise, D1MACH = (IBETA**NEGEPS)/2. Because =* *= NEGEPS is bounded below by -(IT+3), D1MACH may not =* *= be the smallest number that can alter 1.0 by =* *= subtraction. =* *= I=4 - the smallest positive floating-point number such =* *= that 1.0+D1MACH .NE. 1.0. In particular, if either =* *= IBETA = 2 or IRND = 0, D1MACH=FLOAT(IBETA)**MACHEP. =* *= Otherwise, D1MACH=(FLOAT(IBETA)**MACHEP)/2 =* *= (see routine T665D for more information on different constants) =* *-----------------------------------------------------------------------------* EXTERNAL t665d REAL(kind(0.0d0)) :: d1mach INTEGER i LOGICAL doinit DATA doinit/.TRUE./ SAVE doinit REAL(kind(0.0d0)) :: dmach(4) SAVE dmach IF (( i .GE. 1 ) .AND. ( i .LE. 4 )) THEN * compute constants at first call only IF (doinit) THEN CALL t665d(dmach) doinit = .FALSE. ENDIF d1mach = dmach(i) ELSE WRITE(0,*) '>>> ERROR (D1MACH) <<< invalid argument' STOP ENDIF *!csm *!!! over-ride by sm on 5/26/03. For some compilers than don't allow * calculation of d1mach(4). Use value found on ACD server. c if( i .eq. 4) d1mach = 2.22e-15 END C ALGORITHM 665, COLLECTED ALGORITHMS FROM ACM. C THIS WORK PUBLISHED IN TRANSACTIONS ON MATHEMATICAL SOFTWARE, C VOL. 14, NO. 4, PP. 303-311. SUBROUTINE T665D(DMACH) C----------------------------------------------------------------------- C This subroutine is a double precision version of subroutine T665R. C See code of T665R for detailed comments and explanation C----------------------------------------------------------------------- REAL(kind(0.0d0)) :: DMACH(4) INTEGER I,IBETA,IEXP,IRND,IT,ITEMP,IZ,J,K,MACHEP,MAXEXP, 1 MINEXP,MX,NEGEP,NGRD,NXRES CS REAL A,B,BETA,BETAIN,BETAH,CONV,EPS,EPSNEG,ONE,T,TEMP,TEMPA, CS 1 TEMP1,TWO,XMAX,XMIN,Y,Z,ZERO REAL(kind(0.0d0)) :: A,B,BETA,BETAIN,BETAH,CONV,EPS,EPSNEG,ONE, 1 T,TEMP,TEMPA,TEMP1,TWO,XMAX,XMIN,Y,Z,ZERO C----------------------------------------------------------------------- CS CONV(I) = REAL(I) CONV(I) = DBLE(I) ONE = CONV(1) TWO = ONE + ONE ZERO = ONE - ONE C----------------------------------------------------------------------- C Determine IBETA, BETA ala Malcolm. C----------------------------------------------------------------------- A = ONE 10 A = A + A TEMP = A+ONE TEMP1 = TEMP-A IF (TEMP1-ONE .EQ. ZERO) GO TO 10 B = ONE 20 B = B + B TEMP = A+B ITEMP = INT(TEMP-A) IF (ITEMP .EQ. 0) GO TO 20 IBETA = ITEMP BETA = CONV(IBETA) C----------------------------------------------------------------------- C Determine IT, IRND. C----------------------------------------------------------------------- IT = 0 B = ONE 100 IT = IT + 1 B = B * BETA TEMP = B+ONE TEMP1 = TEMP-B IF (TEMP1-ONE .EQ. ZERO) GO TO 100 IRND = 0 BETAH = BETA / TWO TEMP = A+BETAH IF (TEMP-A .NE. ZERO) IRND = 1 TEMPA = A + BETA TEMP = TEMPA+BETAH IF ((IRND .EQ. 0) .AND. (TEMP-TEMPA .NE. ZERO)) IRND = 2 C----------------------------------------------------------------------- C Determine NEGEP, EPSNEG. C----------------------------------------------------------------------- NEGEP = IT + 3 BETAIN = ONE / BETA A = ONE DO 200 I = 1, NEGEP A = A * BETAIN 200 CONTINUE B = A 210 TEMP = ONE-A IF (TEMP-ONE .NE. ZERO) GO TO 220 A = A * BETA NEGEP = NEGEP - 1 GO TO 210 220 NEGEP = -NEGEP EPSNEG = A IF ((IBETA .EQ. 2) .OR. (IRND .EQ. 0)) GO TO 300 A = (A*(ONE+A)) / TWO TEMP = ONE-A IF (TEMP-ONE .NE. ZERO) EPSNEG = A C----------------------------------------------------------------------- C Determine MACHEP, EPS. C----------------------------------------------------------------------- 300 MACHEP = -IT - 3 A = B 310 TEMP = ONE+A IF (TEMP-ONE .NE. ZERO) GO TO 320 A = A * BETA MACHEP = MACHEP + 1 GO TO 310 320 EPS = A TEMP = TEMPA+BETA*(ONE+EPS) IF ((IBETA .EQ. 2) .OR. (IRND .EQ. 0)) GO TO 350 A = (A*(ONE+A)) / TWO TEMP = ONE+A IF (TEMP-ONE .NE. ZERO) EPS = A C----------------------------------------------------------------------- C Determine NGRD. C----------------------------------------------------------------------- 350 NGRD = 0 TEMP = ONE+EPS IF ((IRND .EQ. 0) .AND. (TEMP*ONE-ONE .NE. ZERO)) NGRD = 1 C----------------------------------------------------------------------- C Determine IEXP, MINEXP, XMIN. C C Loop to determine largest I and K = 2**I such that C (1/BETA) ** (2**(I)) C does not underflow. C Exit from loop is signaled by an underflow. C----------------------------------------------------------------------- I = 0 K = 1 Z = BETAIN T = ONE + EPS NXRES = 0 400 Y = Z Z = Y * Y C----------------------------------------------------------------------- C Check for underflow here. C----------------------------------------------------------------------- A = Z * ONE TEMP = Z * T IF ((A+A .EQ. ZERO) .OR. (ABS(Z) .GE. Y)) GO TO 410 TEMP1 = TEMP * BETAIN IF (TEMP1*BETA .EQ. Z) GO TO 410 I = I + 1 K = K + K GO TO 400 410 IF (IBETA .EQ. 10) GO TO 420 IEXP = I + 1 MX = K + K GO TO 450 C----------------------------------------------------------------------- C This segment is for decimal machines only. C----------------------------------------------------------------------- 420 IEXP = 2 IZ = IBETA 430 IF (K .LT. IZ) GO TO 440 IZ = IZ * IBETA IEXP = IEXP + 1 GO TO 430 440 MX = IZ + IZ - 1 C----------------------------------------------------------------------- C Loop to determine MINEXP, XMIN. C Exit from loop is signaled by an underflow. C----------------------------------------------------------------------- 450 XMIN = Y Y = Y * BETAIN C----------------------------------------------------------------------- C Check for underflow here. C----------------------------------------------------------------------- A = Y * ONE TEMP = Y * T IF (((A+A) .EQ. ZERO) .OR. (ABS(Y) .GE. XMIN)) GO TO 460 K = K + 1 TEMP1 = TEMP * BETAIN IF (TEMP1*BETA .NE. Y) GO TO 450 NXRES = 3 XMIN = Y 460 MINEXP = -K C----------------------------------------------------------------------- C Determine MAXEXP, XMAX. C----------------------------------------------------------------------- IF ((MX .GT. K+K-3) .OR. (IBETA .EQ. 10)) GO TO 500 MX = MX + MX IEXP = IEXP + 1 500 MAXEXP = MX + MINEXP C----------------------------------------------------------------- C Adjust IRND to reflect partial underflow. C----------------------------------------------------------------- IRND = IRND + NXRES C----------------------------------------------------------------- C Adjust for IEEE-style machines. C----------------------------------------------------------------- IF ((IRND .EQ. 2) .OR. (IRND .EQ. 5)) MAXEXP = MAXEXP - 2 C----------------------------------------------------------------- C Adjust for non-IEEE machines with partial underflow. C----------------------------------------------------------------- IF ((IRND .EQ. 3) .OR. (IRND .EQ. 4)) MAXEXP = MAXEXP - IT C----------------------------------------------------------------- C Adjust for machines with implicit leading bit in binary C significand, and machines with radix point at extreme C right of significand. C----------------------------------------------------------------- I = MAXEXP + MINEXP IF ((IBETA .EQ. 2) .AND. (I .EQ. 0)) MAXEXP = MAXEXP - 1 IF (I .GT. 20) MAXEXP = MAXEXP - 1 IF (A .NE. Y) MAXEXP = MAXEXP - 2 XMAX = ONE - EPSNEG IF (XMAX*ONE .NE. XMAX) XMAX = ONE - BETA * EPSNEG XMAX = XMAX / (BETA * BETA * BETA * XMIN) I = MAXEXP + MINEXP + 3 IF (I .LE. 0) GO TO 520 DO 510 J = 1, I IF (IBETA .EQ. 2) XMAX = XMAX + XMAX IF (IBETA .NE. 2) XMAX = XMAX * BETA 510 CONTINUE DMACH(1) = XMIN DMACH(2) = XMAX DMACH(3) = EPSNEG DMACH(4) = EPS 520 RETURN C---------- LAST CARD OF T665D ---------- END FUNCTION R1MACH(i) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= R1MACH calculates various machine constants in single precision. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= I - INTEGER, identifies the machine constant (0<I<5) (I) =* *= R1MACH - REAL, machine constant in single precision (O) =* *= I=1 - the smallest non-vanishing normalized floating-point =* *= power of the radix, i.e., R1MACH=FLOAT(IBETA)**MINEXP =* *= I=2 - the largest finite floating-point number. In =* *= particular R1MACH=(1.0-EPSNEG)*FLOAT(IBETA)**MAXEXP =* *= Note - on some machines R1MACH will be only the =* *= second, or perhaps third, largest number, being =* *= too small by 1 or 2 units in the last digit of =* *= the significand. =* *= I=3 - A small positive floating-point number such that =* *= 1.0-R1MACH .NE. 1.0. In particular, if IBETA = 2 =* *= or IRND = 0, R1MACH = FLOAT(IBETA)**NEGEPS. =* *= Otherwise, R1MACH = (IBETA**NEGEPS)/2. Because =* *= NEGEPS is bounded below by -(IT+3), R1MACH may not =* *= be the smallest number that can alter 1.0 by =* *= subtraction. =* *= I=4 - the smallest positive floating-point number such =* *= that 1.0+R1MACH .NE. 1.0. In particular, if either =* *= IBETA = 2 or IRND = 0, R1MACH=FLOAT(IBETA)**MACHEP. =* *= Otherwise, R1MACH=(FLOAT(IBETA)**MACHEP)/2 =* *= (see routine T665R for more information on different constants) =* *-----------------------------------------------------------------------------* REAL r1mach INTEGER i LOGICAL doinit DATA doinit/.TRUE./ SAVE doinit REAL rmach(4) SAVE rmach IF (( i .GE. 1 ) .AND. ( i .LE. 4 )) THEN * compute constants at first call only IF (doinit) THEN CALL t665r(rmach) doinit = .FALSE. ENDIF r1mach = rmach(i) ELSE WRITE(0,*) '>>> ERROR (R1MACH) <<< invalid argument' STOP ENDIF END C ALGORITHM 665, COLLECTED ALGORITHMS FROM ACM. C THIS WORK PUBLISHED IN TRANSACTIONS ON MATHEMATICAL SOFTWARE, C VOL. 14, NO. 4, PP. 303-311. SUBROUTINE T665R(RMACH) C----------------------------------------------------------------------- C This Fortran 77 subroutine is intended to determine the parameters C of the floating-point arithmetic system specified below. The C determination of the first three uses an extension of an algorithm C due to M. Malcolm, CACM 15 (1972), pp. 949-951, incorporating some, C but not all, of the improvements suggested by M. Gentleman and S. C Marovich, CACM 17 (1974), pp. 276-277. An earlier version of this C program was published in the book Software Manual for the C Elementary Functions by W. J. Cody and W. Waite, Prentice-Hall, C Englewood Cliffs, NJ, 1980. C C The program as given here must be modified before compiling. If C a single (double) precision version is desired, change all C occurrences of CS (CD) in columns 1 and 2 to blanks. C C Parameter values reported are as follows: C C IBETA - the radix for the floating-point representation C IT - the number of base IBETA digits in the floating-point C significand C IRND - 0 if floating-point addition chops C 1 if floating-point addition rounds, but not in the C IEEE style C 2 if floating-point addition rounds in the IEEE style C 3 if floating-point addition chops, and there is C partial underflow C 4 if floating-point addition rounds, but not in the C IEEE style, and there is partial underflow C 5 if floating-point addition rounds in the IEEE style, C and there is partial underflow C NGRD - the number of guard digits for multiplication with C truncating arithmetic. It is C 0 if floating-point arithmetic rounds, or if it C truncates and only IT base IBETA digits C participate in the post-normalization shift of the C floating-point significand in multiplication; C 1 if floating-point arithmetic truncates and more C than IT base IBETA digits participate in the C post-normalization shift of the floating-point C significand in multiplication. C MACHEP - the largest negative integer such that C 1.0+FLOAT(IBETA)**MACHEP .NE. 1.0, except that C MACHEP is bounded below by -(IT+3) C NEGEPS - the largest negative integer such that C 1.0-FLOAT(IBETA)**NEGEPS .NE. 1.0, except that C NEGEPS is bounded below by -(IT+3) C IEXP - the number of bits (decimal places if IBETA = 10) C reserved for the representation of the exponent C (including the bias or sign) of a floating-point C number C MINEXP - the largest in magnitude negative integer such that C FLOAT(IBETA)**MINEXP is positive and normalized C MAXEXP - the smallest positive power of BETA that overflows C EPS - the smallest positive floating-point number such C that 1.0+EPS .NE. 1.0. In particular, if either C IBETA = 2 or IRND = 0, EPS = FLOAT(IBETA)**MACHEP. C Otherwise, EPS = (FLOAT(IBETA)**MACHEP)/2 C EPSNEG - A small positive floating-point number such that C 1.0-EPSNEG .NE. 1.0. In particular, if IBETA = 2 C or IRND = 0, EPSNEG = FLOAT(IBETA)**NEGEPS. C Otherwise, EPSNEG = (IBETA**NEGEPS)/2. Because C NEGEPS is bounded below by -(IT+3), EPSNEG may not C be the smallest number that can alter 1.0 by C subtraction. C XMIN - the smallest non-vanishing normalized floating-point C power of the radix, i.e., XMIN = FLOAT(IBETA)**MINEXP C XMAX - the largest finite floating-point number. In C particular XMAX = (1.0-EPSNEG)*FLOAT(IBETA)**MAXEXP C Note - on some machines XMAX will be only the C second, or perhaps third, largest number, being C too small by 1 or 2 units in the last digit of C the significand. C C Latest revision - April 20, 1987 C C Author - W. J. Cody C Argonne National Laboratory C C----------------------------------------------------------------------- REAL rmach(4) INTEGER I,IBETA,IEXP,IRND,IT,ITEMP,IZ,J,K,MACHEP,MAXEXP, 1 MINEXP,MX,NEGEP,NGRD,NXRES REAL A,B,BETA,BETAIN,BETAH,CONV,EPS,EPSNEG,ONE,T,TEMP,TEMPA, 1 TEMP1,TWO,XMAX,XMIN,Y,Z,ZERO CD REAL A,B,BETA,BETAIN,BETAH,CONV,EPS,EPSNEG,ONE, CD 1 T,TEMP,TEMPA,TEMP1,TWO,XMAX,XMIN,Y,Z,ZERO C----------------------------------------------------------------------- CONV(I) = REAL(I) CD CONV(I) = DBLE(I) ONE = CONV(1) TWO = ONE + ONE ZERO = ONE - ONE C----------------------------------------------------------------------- C Determine IBETA, BETA ala Malcolm. C----------------------------------------------------------------------- A = ONE 10 A = A + A TEMP = A+ONE TEMP1 = TEMP-A IF (TEMP1-ONE .EQ. ZERO) GO TO 10 B = ONE 20 B = B + B TEMP = A+B ITEMP = INT(TEMP-A) IF (ITEMP .EQ. 0) GO TO 20 IBETA = ITEMP BETA = CONV(IBETA) C----------------------------------------------------------------------- C Determine IT, IRND. C----------------------------------------------------------------------- IT = 0 B = ONE 100 IT = IT + 1 B = B * BETA TEMP = B+ONE TEMP1 = TEMP-B IF (TEMP1-ONE .EQ. ZERO) GO TO 100 IRND = 0 BETAH = BETA / TWO TEMP = A+BETAH IF (TEMP-A .NE. ZERO) IRND = 1 TEMPA = A + BETA TEMP = TEMPA+BETAH IF ((IRND .EQ. 0) .AND. (TEMP-TEMPA .NE. ZERO)) IRND = 2 C----------------------------------------------------------------------- C Determine NEGEP, EPSNEG. C----------------------------------------------------------------------- NEGEP = IT + 3 BETAIN = ONE / BETA A = ONE DO 200 I = 1, NEGEP A = A * BETAIN 200 CONTINUE B = A 210 TEMP = ONE-A IF (TEMP-ONE .NE. ZERO) GO TO 220 A = A * BETA NEGEP = NEGEP - 1 GO TO 210 220 NEGEP = -NEGEP EPSNEG = A IF ((IBETA .EQ. 2) .OR. (IRND .EQ. 0)) GO TO 300 A = (A*(ONE+A)) / TWO TEMP = ONE-A IF (TEMP-ONE .NE. ZERO) EPSNEG = A C----------------------------------------------------------------------- C Determine MACHEP, EPS. C----------------------------------------------------------------------- 300 MACHEP = -IT - 3 A = B 310 TEMP = ONE+A IF (TEMP-ONE .NE. ZERO) GO TO 320 A = A * BETA MACHEP = MACHEP + 1 GO TO 310 320 EPS = A TEMP = TEMPA+BETA*(ONE+EPS) IF ((IBETA .EQ. 2) .OR. (IRND .EQ. 0)) GO TO 350 A = (A*(ONE+A)) / TWO TEMP = ONE+A IF (TEMP-ONE .NE. ZERO) EPS = A C----------------------------------------------------------------------- C Determine NGRD. C----------------------------------------------------------------------- 350 NGRD = 0 TEMP = ONE+EPS IF ((IRND .EQ. 0) .AND. (TEMP*ONE-ONE .NE. ZERO)) NGRD = 1 C----------------------------------------------------------------------- C Determine IEXP, MINEXP, XMIN. C C Loop to determine largest I and K = 2**I such that C (1/BETA) ** (2**(I)) C does not underflow. C Exit from loop is signaled by an underflow. C----------------------------------------------------------------------- I = 0 K = 1 Z = BETAIN T = ONE + EPS NXRES = 0 400 Y = Z Z = Y * Y C----------------------------------------------------------------------- C Check for underflow here. C----------------------------------------------------------------------- A = Z * ONE TEMP = Z * T IF ((A+A .EQ. ZERO) .OR. (ABS(Z) .GE. Y)) GO TO 410 TEMP1 = TEMP * BETAIN IF (TEMP1*BETA .EQ. Z) GO TO 410 I = I + 1 K = K + K GO TO 400 410 IF (IBETA .EQ. 10) GO TO 420 IEXP = I + 1 MX = K + K GO TO 450 C----------------------------------------------------------------------- C This segment is for decimal machines only. C----------------------------------------------------------------------- 420 IEXP = 2 IZ = IBETA 430 IF (K .LT. IZ) GO TO 440 IZ = IZ * IBETA IEXP = IEXP + 1 GO TO 430 440 MX = IZ + IZ - 1 C----------------------------------------------------------------------- C Loop to determine MINEXP, XMIN. C Exit from loop is signaled by an underflow. C----------------------------------------------------------------------- 450 XMIN = Y Y = Y * BETAIN C----------------------------------------------------------------------- C Check for underflow here. C----------------------------------------------------------------------- A = Y * ONE TEMP = Y * T IF (((A+A) .EQ. ZERO) .OR. (ABS(Y) .GE. XMIN)) GO TO 460 K = K + 1 TEMP1 = TEMP * BETAIN IF (TEMP1*BETA .NE. Y) GO TO 450 NXRES = 3 XMIN = Y 460 MINEXP = -K C----------------------------------------------------------------------- C Determine MAXEXP, XMAX. C----------------------------------------------------------------------- IF ((MX .GT. K+K-3) .OR. (IBETA .EQ. 10)) GO TO 500 MX = MX + MX IEXP = IEXP + 1 500 MAXEXP = MX + MINEXP C----------------------------------------------------------------- C Adjust IRND to reflect partial underflow. C----------------------------------------------------------------- IRND = IRND + NXRES C----------------------------------------------------------------- C Adjust for IEEE-style machines. C----------------------------------------------------------------- IF ((IRND .EQ. 2) .OR. (IRND .EQ. 5)) MAXEXP = MAXEXP - 2 C----------------------------------------------------------------- C Adjust for non-IEEE machines with partial underflow. C----------------------------------------------------------------- IF ((IRND .EQ. 3) .OR. (IRND .EQ. 4)) MAXEXP = MAXEXP - IT C----------------------------------------------------------------- C Adjust for machines with implicit leading bit in binary C significand, and machines with radix point at extreme C right of significand. C----------------------------------------------------------------- I = MAXEXP + MINEXP IF ((IBETA .EQ. 2) .AND. (I .EQ. 0)) MAXEXP = MAXEXP - 1 IF (I .GT. 20) MAXEXP = MAXEXP - 1 IF (A .NE. Y) MAXEXP = MAXEXP - 2 XMAX = ONE - EPSNEG IF (XMAX*ONE .NE. XMAX) XMAX = ONE - BETA * EPSNEG XMAX = XMAX / (BETA * BETA * BETA * XMIN) I = MAXEXP + MINEXP + 3 IF (I .LE. 0) GO TO 520 DO 510 J = 1, I IF (IBETA .EQ. 2) XMAX = XMAX + XMAX IF (IBETA .NE. 2) XMAX = XMAX * BETA 510 CONTINUE RMACH(1) = XMIN RMACH(2) = XMAX RMACH(3) = EPSNEG RMACH(4) = EPS 520 RETURN C---------- LAST CARD OF T665R ---------- END CCC FILE rxn.f * This file contains the following subroutines, related to reading/loading * the product (cross section) x (quantum yield) for photo-reactions: * r01 through r47 * r101 through r148 * r149, r150, r151 and r152 added from original TUV code *=============================================================================* SUBROUTINE r01(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product of (cross section) x (quantum yield) for the two =* *= O3 photolysis reactions: =* *= (a) O3 + hv -> O2 + O(1D) =* *= (b) O3 + hv -> O2 + O(3P) =* *= Cross section: Combined data from WMO 85 Ozone Assessment (use 273K =* *= value from 175.439-847.5 nm) and data from Molina and =* *= Molina (use in Hartley and Huggins bans (240.5-350 nm) =* *= Quantum yield: Choice between =* *= (1) data from Michelsen et al, 1994 =* *= (2) JPL 87 recommendation =* *= (3) JPL 90/92 recommendation (no "tail") =* *= (4) data from Shetter et al., 1996 =* *= (5) JPL 97 recommendation =* *= (6) JPL 00 recommendation =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER n1, n2, n3, n4, n5 INTEGER kdata PARAMETER (kdata = 500) REAL x1(kdata), x2(kdata), x3(kdata), x4(kdata) REAL y1(kdata), y2(kdata), y3(kdata), y4(kdata) * local INTEGER mabs REAL xs(kz,kw) REAL yg(kw), yg1(kw), yg2(kw), yg3(kw), yg4(kw) REAL qy1d, qy3p REAL tau, tau2, tau3 REAL a, b, c REAL a0, a1, a2, a3, a4, a5, a6, a7 REAL xl, xl0 REAL so3 REAL dum INTEGER myld INTEGER kmich, kjpl87, kjpl92, kshet, kjpl97, kjpl00, kmats INTEGER i, iw, n, idum INTEGER ierr REAL fo3qy, fo3qy2 EXTERNAL fo3qy, fo3qy2 **************************************************************** ************* jlabel(j) = 'O3 -> O2 + O(1D)' ************* jlabel(j) = 'O3 -> O2 + O(3P)' j = j + 1 jlabel(j) = 'O3 -> O2 + O(1D)' j = j + 1 jlabel(j) = 'O3 -> O2 + O(3P)' * call cross section read/interpolate routine * cross sections from WMO 1985 Ozone Assessment * from 175.439 to 847.500 nm. Using value at 273 K. * Values are over-written in Hartly and Huggins bands, using different * options depending on value of mopt: * mabs = 1 = mostly Reims grp (Malicet, Brion) * mabs = 2 = JPL 2006 mabs = 1 CALL rdo3xs(mabs, nz,tlev,nw,wl, xs, kout) ******* quantum yield: kmich = 1 kjpl87 = 2 kjpl92 = 3 kshet = 4 kjpl97 = 5 kjpl00 = 6 kmats = 7 * choose quantum yield recommendation: * kjpl87: JPL recommendation 1987 - JPL 87, 90, 92 do not "tail" * kjpl92: JPL recommendations 1990/92 (identical) - still with no "tail" * kjpl97: JPL recommendation 1997, includes tail, similar to Shetter et al. * kmich : Michelsen et al., 1994 * kshet : Shetter et al., 1996 * kjpl00: JPL 2000 * kmats: Matsumi et al., 2002 c myld = kjpl87 c myld = kjpl92 c myld = kshet c myld = kmich c myld = kjpl97 c myld = kjpl00 myld = kmats * read parameters from JPL'97 IF (myld .EQ. kjpl97) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/YLD/O3.param_jpl97.yld', & STATUS='old') READ(UNIT=ilu,FMT=*) READ(UNIT=ilu,FMT=*) READ(UNIT=ilu,FMT=*) n1 = 21 n2 = n1 DO i = 1, n1 READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i) x2(i) = x1(i) ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),y1(1)) CALL addpnt(x1,y1,kdata,n1, 0.,y1(1)) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),y1(n1)) CALL addpnt(x1,y1,kdata,n1, 1.e+38,y1(n1)) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),y2(1)) CALL addpnt(x2,y2,kdata,n2, 0.,y2(1)) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),y2(n2)) CALL addpnt(x2,y2,kdata,n2, 1.e+38,y2(n2)) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF * read parameters from Michelsen, H. A., R.J. Salawitch, P. O. Wennber, * and J. G. Anderson, Geophys. Res. Lett., 21, 2227-2230, 1994. IF (myld .EQ. kmich) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/YLD/O3.param.yld',STATUS='old') READ(UNIT=ilu,FMT=*) READ(UNIT=ilu,FMT=*) READ(UNIT=ilu,FMT=*) n1 = 21 n2 = n1 DO i = 1, n1 READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i) x2(i) = x1(i) ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),y1(1)) CALL addpnt(x1,y1,kdata,n1, 0.,y1(1)) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),y1(n1)) CALL addpnt(x1,y1,kdata,n1, 1.e+38,y1(n1)) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),y2(1)) CALL addpnt(x2,y2,kdata,n2, 0.,y2(1)) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),y2(n2)) CALL addpnt(x2,y2,kdata,n2, 1.e+38,y2(n2)) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF * quantum yield data from * Shetter et al, J.Geophys.Res., v 101 (D9), pg. 14,631-14,641, June 20, 1996 IF (myld .EQ. kshet) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/YLD/O3_shetter.yld',STATUS='OLD') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO n = n-2 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i),y3(i),y4(i),y1(i),y2(i) x2(i) = x1(i) x3(i) = x1(i) x4(i) = x1(i) ENDDO DO i = n+1, n+2 READ(UNIT=ilu,FMT=*) x3(i),y3(i),y4(i) x4(i) = x3(i) ENDDO CLOSE(UNIT=ilu) n1 = n n2 = n n3 = n+2 n4 = n+2 * coefficients for exponential fit: CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax), y1(1)) CALL addpnt(x1,y1,kdata,n1, 0., y1(1)) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1E38,0.) CALL inter2(nw,wl,yg1, n1,x1,y1, ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),y2(1)) CALL addpnt(x2,y2,kdata,n2, 0.,y2(1)) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1E38,0.) CALL inter2(nw,wl,yg2, n2,x2,y2, ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * phi data at 298 and 230 K CALL addpnt(x3,y3,kdata,n3,x3(1)*(1.-deltax),y3(1)) CALL addpnt(x3,y3,kdata,n3, 0.,y3(1)) CALL addpnt(x3,y3,kdata,n3,x3(n3)*(1.+deltax),0.) CALL addpnt(x3,y3,kdata,n3, 1E38,0.) CALL inter2(nw,wl,yg3, n3,x3,y3, ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr,jlabel(j) STOP ENDIF CALL addpnt(x4,y4,kdata,n4,x4(1)*(1.-deltax),y4(1)) CALL addpnt(x4,y4,kdata,n4, 0.,y4(1)) CALL addpnt(x4,y4,kdata,n4,x4(n4)*(1.+deltax),0.) CALL addpnt(x4,y4,kdata,n4, 1E38,0.) CALL inter2(nw,wl,yg4, n4,x4,y4, ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr,jlabel(j) STOP ENDIF ENDIF * compute cross sections and yields at different wavelengths, altitudes: DO 10 iw = 1, nw-1 DO 20 i = 1, nz * quantum yields * coefficients from jpl 87: IF (myld .EQ. kjpl87) THEN tau = tlev(i) - 230. tau2 = tau*tau tau3 = tau2*tau xl = wc(iw) xl0 = 308.2 + 4.4871e-2*tau + 6.938e-5*tau2 - > 2.5452e-6*tau3 a = 0.9*(0.369 + 2.85e-4*tau + 1.28e-5*tau2 + > 2.57e-8*tau3) b = -0.575 + 5.59e-3*tau - 1.439e-5*tau2 - > 3.27e-8*tau3 c = 0.9*(0.518 + 9.87e-4*tau - 3.94e-5*tau2 + > 3.91e-7*tau3) qy1d = a*atan(b*(xl-xl0)) + c qy1d = amax1(0.,qy1d) qy1d = amin1(0.9,qy1d) ENDIF * from jpl90, jpl92: * (caution: error in JPL92 for first term of a3) IF (myld .EQ. kjpl92) THEN tau = 298. - tlev(i) tau2 = tau*tau xl0 = wc(iw) - 305. a0 = .94932 - 1.7039e-4*tau + 1.4072E-6*tau2 a1 = -2.4052e-2 + 1.0479e-3*tau - 1.0655e-5*tau2 a2 = 1.8771e-2 - 3.6401e-4*tau - 1.8587e-5*tau2 a3 = -1.4540e-2 - 4.7787e-5*tau + 8.1277e-6*tau2 a4 = 2.3287e-3 + 1.9891e-5*tau - 1.1801e-6*tau2 a5 = -1.4471e-4 - 1.7188e-6*tau + 7.2661e-8*tau2 a6 = 3.1830e-6 + 4.6209e-8*tau - 1.6266e-9*tau2 qy1d = a0 + a1*xl0 + a2*(xl0)**2 + a3*(xl0)**3 + > a4*(xl0)**4 + a5*(xl0)**5 + a6*(xl0)**6 IF (wc(iw) .LT. 305.) qy1d = 0.95 IF (wc(iw) .GT. 320.) qy1d = 0. IF (qy1d .LT. 0.02) qy1d = 0. ENDIF * from JPL'97 IF (myld .EQ. kjpl97) THEN IF (wc(iw) .LT. 271.) THEN qy1d = 0.87 ELSE IF (wc(iw) .GE. 271. .AND. wc(iw) .LT. 290.) THEN qy1d = 0.87 + (wc(iw)-271.)*(.95-.87)/(290.-271.) ELSE IF (wc(iw) .GE. 290. .AND. wc(iw) .LT. 305.) THEN qy1d = 0.95 ELSE IF (wc(iw) .GE. 305. .AND. wc(iw) .LE. 325.) THEN qy1d = yg1(iw) * EXP ( -yg2(iw) /tlev(i) ) ELSE qy1d = 0. ENDIF ENDIF * from Michelsen, H. A., R.J. Salawitch, P. O. Wennber, and J. G. Anderson * Geophys. Res. Lett., 21, 2227-2230, 1994. IF (myld .EQ. kmich) THEN IF (wc(iw) .LT. 271.) THEN qy1d = 0.87 ELSE IF (wc(iw) .GE. 271. .AND. wc(iw) .LT. 305.) THEN qy1d = 1.98 - 301./wc(iw) ELSE IF (wc(iw) .GE. 305. .AND. wc(iw) .LE. 325.) THEN qy1d = yg1(iw) * EXP (-yg2(iw) /(0.6951*tlev(i))) ELSE qy1d = 0. ENDIF ENDIF * Shetter et al.: * phi = A * exp(-B/T), A and B are based on meas. at 298 and 230 K * do linear interpolation between phi(298) and phi(230) for wavelengths > 321 * as phi(230)=0. for those wavelengths, so there are no A and B factors IF (myld .EQ. kshet) THEN IF (wl(iw+1) .LE. 321.) THEN qy1d = yg1(iw) * EXP(-1. * yg2(iw)/tlev(i)) ELSE qy1d = (yg3(iw) - yg4(iw))/(298.-230.) * (tlev(i)-230.) + > yg4(iw) ENDIF ENDIF * JPL 2000: IF (myld .EQ. kjpl00) THEN qy1d = fo3qy(wc(iw),tlev(i)) ENDIF * Matsumi et al. IF (myld .EQ. kmats) THEN qy1d = fo3qy2(wc(iw),tlev(i)) ENDIF * compute product sq(j-1,i,iw) = qy1d*xs(i,iw) qy3p = 1.0 - qy1d sq(j,i,iw) = qy3p*xs(i,iw) 20 CONTINUE 10 CONTINUE * declare temperature dependence tpflag(j-1) = 1 tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r02(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for NO2 =* *= photolysis: =* *= NO2 + hv -> NO + O(3P) =* *= Cross section from JPL94 (can also have Davidson et al.) =* *= Quantum yield from Gardiner, Sperry, and Calvert =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw, iw REAL wl(kw), wc(kw) INTEGER nz, iz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=200) INTEGER n1, n2 REAL x1(kdata), x2(kdata), x3(kdata) REAL y1(kdata), y2(kdata) * local REAL yg1(kw), yg2(kw) REAL no2xs(kz,kw), qy(kz,kw) REAL dum, dum1, dum2 INTEGER i, n, idum, ierr INTEGER mabs, myld **************** NO2 photodissociation j = j + 1 jlabel(j) = 'NO2 -> NO + O(3P)' * options for NO2 cross section: * 1 = Davidson et al. (1988), indepedent of T * 2 = JPL 1994 (same as JPL 1997, JPL 2002) * 3 = Harder et al. * 4 = JPL 2006, interpolating between midpoints of bins * 5 = JPL 2006, bin-to-bin interpolation mabs = 4 IF (mabs. EQ. 1) CALL no2xs_d(nz,tlev,nw,wl, no2xs, kout) IF (mabs .EQ. 2) CALL no2xs_jpl94(nz,tlev,nw,wl, no2xs, kout) IF (mabs .EQ. 3) CALL no2xs_har(nz,tlev,nw,wl, no2xs, kout) IF (mabs .EQ. 4) CALL no2xs_jpl06a(nz,tlev,nw,wl, no2xs, kout) IF (mabs .EQ. 5) CALL no2xs_jpl06b(nz,tlev,nw,wl, no2xs, kout) * quantum yields * myld = 1 NO2_calvert.yld (same as JPL2002) * myld = 2 NO2_jpl2006.yld myld = 2 IF (myld .EQ. 1) THEN * from Gardiner, Sperry, and Calvert OPEN(NEWUNIT=ilu,FILE='DATAJ1/YLD/NO2_calvert.yld',STATUS='old') DO i = 1, 8 READ(UNIT=ilu,FMT=*) ENDDO n = 66 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i),y1(i) ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),y1(1)) CALL addpnt(x1,y1,kdata,n, 0.,y1(1)) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax), 0.) CALL addpnt(x1,y1,kdata,n, 1.e+38, 0.) CALL inter2(nw,wl,yg1,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF do iw = 1, nw - 1 do iz = 1, nz qy(iz,iw) = yg1(iw) enddo enddo else if(myld. eq. 2) then * from jpl 2011 OPEN(NEWUNIT=ilu,FILE='DATAJ1/YLD/NO2_jpl11.yld',STATUS='old') DO i = 1, 2 READ(UNIT=ilu,FMT=*) ENDDO n = 25 n2 = n DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i),y1(i),y2(i) x2(i) = x1(i) ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),y1(1)) CALL addpnt(x1,y1,kdata,n, 0.,y1(1)) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax), 0.) CALL addpnt(x1,y1,kdata,n, 1.e+38, 0.) CALL inter2(nw,wl,yg1,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),y2(1)) CALL addpnt(x2,y2,kdata,n2, 0.,y2(1)) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax), 0.) CALL addpnt(x2,y2,kdata,n2, 1.e+38, 0.) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF DO iw = 1, nw - 1 DO iz = 1, nz qy(iz,iw) = yg1(iw) + $ (yg1(iw)-yg2(iw)) * (tlev(iz)-298)/50. qy(iz,iw) = amax1(qy(iz,iw),0.) ENDDO ENDDO ENDIF * combine DO iw = 1, nw - 1 DO iz = 1, nz sq(j,iz,iw) = no2xs(iz,iw)*qy(iz,iw) ENDDO ENDDO * declare temperature dependence tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r03(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (absorptioon cross section) x (quantum yield) for =* *= both channels of NO3 photolysis: =* *= (a) NO3 + hv -> NO2 + O(3P) =* *= (b) NO3 + hv -> NO + O2 =* *= Cross section combined from Graham and Johnston (<600 nm) and JPL 94 =* *= Quantum yield from Madronich (1988) =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=350) REAL x(kdata), x1(kdata) REAL y1(kdata) real q1_298(kdata), q1_230(kdata), q1_190(kdata) real q2_298(kdata), q2_230(kdata), q2_190(kdata) * local REAL yg(kw), yg1(kw) REAL qy,qy1, qy2 real yg1_298(kw), yg1_230(kw), yg1_190(kw) real yg2_298(kw), yg2_230(kw), yg2_190(kw) INTEGER irow, icol INTEGER i, iw, iz, n, idum INTEGER ierr integer mabs, myld **************** jlabel(j) = 'NO3 -> NO2 + O(3P)' **************** jlabel(j) = 'NO3 -> NO + O2' j = j + 1 jlabel(j) = 'NO3 -> NO + O2' j = j + 1 jlabel(j) = 'NO3 -> NO2 + O(3P)' * mabs = 1: Graham and Johnston 1978 * mabs = 2: JPL94 * mabs = 3: JPL11 mabs = 3 * myld = 1 from Madronich (1988) see CEC NO3 book. * myld = 2 from JPL-2011 myld = 2 * cross section IF(mabs. eq. 1) then * cross section * measurements of Graham and Johnston 1978 OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/NO3_gj78.abs',STATUS='old') DO i = 1, 9 READ(UNIT=ilu,FMT=*) ENDDO n = 305 DO irow = 1, 30 READ(UNIT=ilu,FMT=*) ( y1(10*(irow-1) + icol), icol = 1, 10 ) ENDDO READ(UNIT=ilu,FMT=*) ( y1(300 + icol), icol = 1, 5 ) CLOSE (UNIT=ilu) DO i = 1, n y1(i) = y1(i) * 1.E-19 x1(i) = 400. + 1.*FLOAT(i-1) ENDDO CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs .EQ. 2) THEN * cross section from JPL94: OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/NO3_jpl94.abs',STATUS='old') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i)*1E-20 ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg1,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * use JPL94 for wavelengths longer than 600 nm DO iw = 1, nw-1 IF(wl(iw) .GT. 600.) yg(iw) = yg1(iw) ENDDO * cross sections from JPL2011 ELSEIF(MABS .EQ. 3) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/NO3_jpl11.abs',STATUS='old') DO i = 1, 6 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, 289 READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i)*1E-20 ENDDO CLOSE (UNIT=ilu) n = 289 CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg1,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF * quantum yield: if (myld .eq. 1) then * for NO3 ->NO+O2 DO iw = 1, nw - 1 IF (wc(iw).LT.584.) THEN qy = 0. ELSEIF (wc(iw).GE.640.) THEN qy = 0. ELSEIF (wc(iw).GE.595.) THEN qy = 0.35*(1.-(wc(iw)-595.)/45.) ELSE qy = 0.35*(wc(iw)-584.)/11. ENDIF DO i = 1, nz sq(j,i,iw) = yg(iw)*qy ENDDO ENDDO * for NO3 ->NO2+O DO iw = 1, nw - 1 IF (wc(iw).LT.584.) THEN qy = 1. ELSEIF (wc(iw).GT.640.) THEN qy = 0. ELSEIF (wc(iw).GT.595.) THEN qy = 0.65*(1-(wc(iw)-595.)/45.) ELSE qy = 1.-0.35*(wc(iw)-584.)/11. ENDIF DO i = 1, nz sq(j,i,iw) = yg(iw)*qy ENDDO ENDDO * yields from JPL2011: ELSEIF(myld .EQ. 2) THEN open(newunit=ilu,file='DATAJ1/YLD/NO3_jpl2011.qy',status='old') do i = 1, 5 read(UNIT=ilu,FMT=*) enddo do i = 1, 56 read(UNIT=ilu,FMT=*) x(i), q1_298(i), q1_230(i), q1_190(i), $ q2_298(i), q2_230(i), q2_190(i) q1_298(i) = q1_298(i)/1000. q1_230(i) = q1_230(i)/1000. q1_190(i) = q1_190(i)/1000. q2_298(i) = q2_298(i)/1000. q2_230(i) = q2_230(i)/1000. q2_190(i) = q2_190(i)/1000. enddo close(UNIT=ilu) n = 56 do i = 1, n x1(i) = x(i) enddo CALL addpnt(x1,q1_298,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,q1_298,kdata,n, 0.,0.) CALL addpnt(x1,q1_298,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,q1_298,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg1_298,n,x1,q1_298,ierr) n = 56 do i = 1, n x1(i) = x(i) enddo CALL addpnt(x1,q1_230,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,q1_230,kdata,n, 0.,0.) CALL addpnt(x1,q1_230,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,q1_230,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg1_230,n,x1,q1_230,ierr) n = 56 do i = 1, n x1(i) = x(i) enddo CALL addpnt(x1,q1_190,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,q1_190,kdata,n, 0.,0.) CALL addpnt(x1,q1_190,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,q1_190,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg1_190,n,x1,q1_190,ierr) n = 56 do i = 1, n x1(i) = x(i) enddo CALL addpnt(x1,q2_298,kdata,n,x1(1)*(1.-deltax),1.) CALL addpnt(x1,q2_298,kdata,n, 0.,1.) CALL addpnt(x1,q2_298,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,q2_298,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg2_298,n,x1,q2_298,ierr) n = 56 do i = 1, n x1(i) = x(i) enddo CALL addpnt(x1,q2_230,kdata,n,x1(1)*(1.-deltax),1.) CALL addpnt(x1,q2_230,kdata,n, 0.,1.) CALL addpnt(x1,q2_230,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,q2_230,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg2_230,n,x1,q2_230,ierr) n = 56 do i = 1, n x1(i) = x(i) enddo CALL addpnt(x1,q2_190,kdata,n,x1(1)*(1.-deltax),1.) CALL addpnt(x1,q2_190,kdata,n, 0.,1.) CALL addpnt(x1,q2_190,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,q2_190,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg2_190,n,x1,q2_190,ierr) * compute T-dependent quantum yields DO iw = 1, nw-1 DO iz = 1, nz if(tlev(iz) .le. 190.) then qy1 = yg1_190(iw) qy2 = yg2_190(iw) elseif(tlev(iz) .gt. 190. .and. tlev(iz) .le. 230.) then qy1 = yg1_190(iw) + (yg1_230(iw) - yg1_190(iw))* $ (tlev(iz) - 190.)/(230.-190.) qy2 = yg2_190(iw) + (yg2_230(iw) - yg2_190(iw))* $ (tlev(iz) - 190.)/(230.-190.) elseif(tlev(iz) .gt. 230. .and. tlev(iz) .le. 298.) then qy1 = yg1_230(iw) + (yg1_298(iw) - yg1_230(iw))* $ (tlev(iz) - 230.)/(298.-230.) qy2 = yg2_230(iw) + (yg2_298(iw) - yg2_230(iw))* $ (tlev(iz) - 230.)/(298.-230.) elseif(tlev(iz) .gt. 298.) then qy1 = yg1_298(iw) qy2 = yg2_298(iw) endif sq(j-1, iz, iw) = qy1 * yg1(iw) sq(j, iz, iw) = qy2 * yg1(iw) ENDDO ENDDO ENDIF * declare temperature dependence for both channels: tpflag(j-1) = 1 tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r04(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product of (cross section) x (quantum yiels) for N2O5 photolysis =* *= reactions: =* *= (a) N2O5 + hv -> NO3 + NO + O(3P) =* *= (b) N2O5 + hv -> NO3 + NO2 =* *= Cross section from JPL97: use tabulated values up to 280 nm, use expon. =* *= expression for >285nm, linearly interpolate =* *= between s(280) and s(285,T) in between =* *= Quantum yield: Analysis of data in JPL94 (->DATAJ1/YLD/N2O5.qy) =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=200) REAL x1(kdata), x2(kdata) REAL y1(kdata), A(kdata), B(kdata) INTEGER n1, n2 * local REAL yg1(kw), yg2(kw) INTEGER i, iz, iw INTEGER ierr REAL t, xs, dum **************** N2O5 photodissociation j = j + 1 jlabel(j) = 'N2O5 -> NO3 + NO + O(3P)' j = j + 1 jlabel(j) = 'N2O5 -> NO3 + NO2' * cross section from jpl2011, at 300 K OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/N2O5_jpl11.abs',STATUS='old') DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n1 = 103 DO i = 1, n1 READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.E-20 ENDDO * read temperature dependence coefficients: DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n2 = 8 DO i = 1, n2 READ(UNIT=ilu,FMT=*) x2(i), A(i), B(i) ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata, n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata, n1, 0.,0.) CALL addpnt(x1,y1,kdata, n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata, n1, 1.E36 ,0.) CALL inter2(nw,wl,yg1, n1,x1,y1, ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr,jlabel(j) STOP ENDIF CALL addpnt(x2,B,kdata, n2,x2(1)*(1.-deltax),0.) CALL addpnt(x2,B,kdata, n2, 0.,0.) CALL addpnt(x2,B,kdata, n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,B,kdata, n2, 1.E36 ,0.) CALL inter2(nw,wl,yg2, n2,x2,B, ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr,jlabel(j) STOP ENDIF DO iw = 1, nw - 1 DO iz = 1, nz * temperature dependence only valid for 233 - 295 K. Extend to 300. t = MAX(233.,MIN(tlev(iz),300.)) * Apply temperature correction to 300K values. Do not use A-coefficients * because they are inconsistent with the values at 300K. dum = 1000.*yg2(iw)*((1./t) - (1./300.)) xs = yg1(iw) * 10.**(dum) * quantum yield = 1 for NO2 + NO3, zero for other channels sq(j-1, iz, iw) = 0. * xs sq(j , iz, iw) = 1. * xs ENDDO ENDDO * declare temperature dependence tpflag(j-1) = 1 tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r05(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for HNO2 photolysis=* *= HNO2 + hv -> NO + OH =* *= Cross section: from JPL97 =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* *= EDIT HISTORY: =* *= 05/98 Original, adapted from former JSPEC1 subroutine =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=200) REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw) REAL qy INTEGER i, iw, n INTEGER ierr INTEGER mabs **************** HNO2 photodissociation * mabs = 2: JPL 2011 recommendation * mabs = 1: earlier JPL recommendations mabs = 2 * cross section from JPL92 * (from Bongartz et al., identical to JPL94, JPL97 recommendation) j = j + 1 jlabel(j) = 'HNO2 -> OH + NO' IF(mabs .eq. 1) then OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/HNO2_jpl92.abs',STATUS='old') DO i = 1, 13 READ(UNIT=ilu,FMT=*) ENDDO n = 91 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.E-20 ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs .eq. 2) then OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/HONO_jpl11.abs',STATUS='old') DO i = 1, 3 READ(UNIT=ilu,FMT=*) ENDDO n = 192 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.E-20 ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF * quantum yield = 1 qy = 1. DO iw = 1, nw - 1 DO i = 1, nz sq(j,i,iw) = yg(iw)*qy ENDDO ENDDO * no t or p dependence tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r06(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product of (cross section) x (quantum yield) for HNO3 photolysis =* *= HNO3 + hv -> OH + NO2 =* *= Cross section: Burkholder et al., 1993 =* *= Quantum yield: Assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) INTEGER n1, n2 REAL x1(kdata), x2(kdata) REAL y1(kdata), y2(kdata) * local REAL yg1(kw), yg2(kw) INTEGER i, iw INTEGER ierr **************** HNO3 photodissociation j = j + 1 jlabel(j) = 'HNO3 -> OH + NO2' C* cross section from JPL85 C C OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/HNO3.abs',STATUS='old') C DO i = 1, 9 C READ(UNIT=ilu,FMT=*) C ENDDO C n = 29 C DO i = 1, n C READ(UNIT=ilu,FMT=*) x1(i), y1(i) C y1(i) = y1(i) * 1.E-20 C ENDDO C CLOSE (UNIT=ilu) C C CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) C CALL addpnt(x1,y1,kdata,n, 0.,0.) C CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) C CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) C CALL inter2(nw,wl,yg,n,x1,y1,ierr) C IF (ierr .NE. 0) THEN C WRITE(*,*) ierr, jlabel(j) C STOP C ENDIF C C* quantum yield = 1 C C qy = 1. C DO iw = 1, nw - 1 C DO i = 1, nz C sq(j,i,iw) = yg(iw)*qy C ENDDO C ENDDO * HNO3 cross section parameters from Burkholder et al. 1993 OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/HNO3_burk.abs',STATUS='old') DO i = 1, 6 READ(UNIT=ilu,FMT=*) END DO n1 = 83 n2 = n1 DO i = 1, n1 READ(UNIT=ilu,FMT=*) y1(i), y2(i) x1(i) = 184. + i*2. x2(i) = x1(i) END DO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),y2(1)) CALL addpnt(x2,y2,kdata,n2, 0.,y2(1)) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),y2(n2)) CALL addpnt(x2,y2,kdata,n2, 1.e+38,y2(n2)) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yield = 1 * correct for temperature dependence DO iw = 1, nw - 1 DO i = 1, nz sq(j,i,iw) = yg1(iw) * 1.E-20 $ * exp( yg2(iw)/1.e3*(tlev(i)-298.) ) ENDDO ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r07(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product of (cross section) x (quantum yield) for HNO4 photolysis =* *= HNO4 + hv -> HO2 + NO2 =* *= Cross section: from JPL97 =* *= Quantum yield: Assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) REAL x1(kdata) REAL y1(kdata) C* local REAL yg(kw) REAL qy INTEGER i, iw, n INTEGER ierr **************** HNO4 photodissociation * cross section from JPL2011 j = j + 1 jlabel(j) = 'HNO4 -> HO2 + NO2' OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/HNO4_jpl11.abs',STATUS='old') DO i = 1, 2 READ(UNIT=ilu,FMT=*) ENDDO n = 54 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.E-20 ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yield = 1 qy = 1. DO iw = 1, nw - 1 DO i = 1, nz sq(j,i,iw) = yg(iw)*qy ENDDO ENDDO * no T or P dependence tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r08(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product of (cross section) x (quantum yield) for H2O2 photolysis =* *= H2O2 + hv -> 2 OH =* *= Cross section: From JPL97, tabulated values @ 298K for <260nm, T-depend.=* *= parameterization for 260-350nm =* *= Quantum yield: Assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=600) C INTEGER n1, n2, n3, n4, n5 REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw) REAL qy REAL a0, a1, a2, a3, a4, a5, a6, a7 REAL b0, b1, b2, b3, b4 REAL xs REAL t INTEGER i, iw, n, idum INTEGER ierr REAL lambda REAL sumA, sumB, chi **************** H2O2 photodissociation * cross section from Lin et al. 1978 j = j + 1 jlabel(j) = 'H2O2 -> 2 OH' C OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/H2O2_lin.abs',STATUS='old') C DO i = 1, 7 C READ(UNIT=ilu,FMT=*) C ENDDO C n = 32 C DO i = 1, n C READ(UNIT=ilu,FMT=*) x1(i), y1(i) C y1(i) = y1(i) * 1.E-20 C ENDDO C CLOSE (UNIT=ilu) C C CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) C CALL addpnt(x1,y1,kdata,n, 0.,0.) C CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) C CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) C CALL inter2(nw,wl,yg,n,x1,y1,ierr) C IF (ierr .NE. 0) THEN C WRITE(*,*) ierr, jlabel(j) C STOP C ENDIF * cross section from JPL94 (identical to JPL97) * tabulated data up to 260 nm OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/H2O2_jpl94.abs',STATUS='old') READ(UNIT=ilu,FMT=*) idum,n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.E-20 ENDDO CLOSE (UNIT=ilu) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/H2O2_Kahan.abs',STATUS='old') DO i = 1, 494 n = n + 1 READ(UNIT=ilu,FMT=*) x1(n), y1(n) ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF A0 = 6.4761E+04 A1 = -9.2170972E+02 A2 = 4.535649 A3 = -4.4589016E-03 A4 = -4.035101E-05 A5 = 1.6878206E-07 A6 = -2.652014E-10 A7 = 1.5534675E-13 B0 = 6.8123E+03 B1 = -5.1351E+01 B2 = 1.1522E-01 B3 = -3.0493E-05 B4 = -1.0924E-07 * quantum yield = 1 qy = 1. DO iw = 1, nw - 1 * Parameterization (JPL94) * Range 260-350 nm; 200-400 K IF ((wl(iw) .GE. 260.) .AND. (wl(iw) .LT. 350.)) THEN lambda = wc(iw) sumA = ((((((A7*lambda + A6)*lambda + A5)*lambda + > A4)*lambda +A3)*lambda + A2)*lambda + > A1)*lambda + A0 sumB = (((B4*lambda + B3)*lambda + B2)*lambda + > B1)*lambda + B0 DO i = 1, nz t = MIN(MAX(tlev(i),200.),400.) chi = 1./(1.+EXP(-1265./t)) xs = (chi * sumA + (1.-chi)*sumB)*1E-21 sq(j,i,iw) = xs*qy ENDDO ELSE DO i = 1, nz sq(j,i,iw) = yg(iw)*qy ENDDO ENDIF ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r09(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product of (cross section) x (quantum yield) for CHBr3 photolysis=* *= CHBr3 + hv -> Products =* *= Cross section: Choice of data from Atlas (?Talukdar???) or JPL97 =* *= Quantum yield: Assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=200) INTEGER n1, n2, n3, n4, n5 REAL x1(kdata), x2(kdata), x3(kdata), x4(kdata), x5(kdata) REAL y1(kdata), y2(kdata), y3(kdata), y4(kdata), y5(kdata) * local REAL yg(kw), yg1(kw), yg2(kw), yg3(kw), yg4(kw), yg5(kw) real t real qy INTEGER i, iw, n INTEGER ierr INTEGER iz integer kopt *_______________________________________________________________________ DO 5, iw = 1, nw - 1 wc(iw) = (wl(iw) + wl(iw+1))/2. 5 CONTINUE **************** CHBr3 photodissociation j = j + 1 jlabel(j) = 'CHBr3 -> Products' * option: * kopt = 1: cross section from Elliot Atlas, 1997 * kopt = 2: cross section from JPL 1997 kopt = 2 if (kopt .eq. 1) then OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/CHBr3.abs',STATUS='old') DO i = 1, 5 READ(UNIT=ilu,FMT=*) ENDDO n5 = 25 n4 = 27 n3 = 29 n2 = 31 n1 = 39 DO i = 1, n5 READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i), y3(i), y4(i), y5(i) ENDDO do i = n5 + 1, n4 READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i), y3(i), y4(i) enddo do i = n4 + 1, n3 READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i), y3(i) enddo do i = n3 + 1, n2 READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i) enddo do i = n2 + 1, n1 READ(UNIT=ilu,FMT=*) x1(i), y1(i) enddo CLOSE (UNIT=ilu) do i = 1, n1 y1(i) = y1(i) * 1.e-23 enddo do i = 1, n2 x2(i) = x1(i) y2(i) = y2(i) * 1.e-23 enddo do i = 1, n3 x3(i) = x1(i) y3(i) = y3(i) * 1.e-23 enddo do i = 1, n4 x4(i) = x1(i) y4(i) = y4(i) * 1.e-23 enddo do i = 1, n5 x5(i) = x1(i) y5(i) = y5(i) * 1.e-23 enddo CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),y1(1)) CALL addpnt(x1,y1,kdata,n1, 0.,y1(1)) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),y2(1)) CALL addpnt(x2,y2,kdata,n2, 0.,y2(1)) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1.e+38,0.) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x3,y3,kdata,n3,x3(1)*(1.-deltax),y3(1)) CALL addpnt(x3,y3,kdata,n3, 0.,y3(1)) CALL addpnt(x3,y3,kdata,n3,x3(n3)*(1.+deltax),0.) CALL addpnt(x3,y3,kdata,n3, 1.e+38,0.) CALL inter2(nw,wl,yg3,n3,x3,y3,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) ENDIF CALL addpnt(x4,y4,kdata,n4,x4(1)*(1.-deltax),y4(1)) CALL addpnt(x4,y4,kdata,n4, 0.,y4(1)) CALL addpnt(x4,y4,kdata,n4,x4(n4)*(1.+deltax),0.) CALL addpnt(x4,y4,kdata,n4, 1.e+38,0.) CALL inter2(nw,wl,yg4,n4,x4,y4,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x5,y5,kdata,n5,x5(1)*(1.-deltax),y5(1)) CALL addpnt(x5,y5,kdata,n5, 0.,y5(1)) CALL addpnt(x5,y5,kdata,n5,x5(n5)*(1.+deltax),0.) CALL addpnt(x5,y5,kdata,n5, 1.e+38,0.) CALL inter2(nw,wl,yg5,n5,x5,y5,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yield = 1 qy = 1. DO iw = 1, nw - 1 DO iz = 1, nz t = tlev(iz) if (t .ge. 296.) then yg(iw) = yg1(iw) else if(t .ge. 286.) then yg(iw) = yg1(iw) + (t-286.)*(yg2(iw)-yg1(iw))/10. else if(t .ge. 276.) then yg(iw) = yg2(iw) + (t-276.)*(yg3(iw)-yg2(iw))/10. else if(t .ge. 266.) then yg(iw) = yg3(iw) + (t-266.)*(yg4(iw)-yg3(iw))/10. else if(t .ge. 256.) then yg(iw) = yg4(iw) + (t-256.)*(yg5(iw)-yg4(iw))/10. else if(t .lt. 256.) then yg(iw) = yg5(iw) endif sq(j,iz,iw) = yg(iw)*qy ENDDO ENDDO * jpl97, with temperature dependence formula, *w = 290 nm to 340 nm, *T = 210K to 300 K *sigma, cm2 = exp((0.06183-0.000241*w)*(273.-T)-(2.376+0.14757*w)) ELSEIF (kopt .EQ. 2) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/CHBr3.jpl97',STATUS='old') DO i = 1, 6 READ(UNIT=ilu,FMT=*) ENDDO n1 = 87 DO i = 1, n1 READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),y1(1)) CALL addpnt(x1,y1,kdata,n1, 0.,y1(1)) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yield = 1 qy = 1. DO iw = 1, nw - 1 DO iz = 1, nz t = tlev(iz) yg(iw) = yg1(iw) IF (wc(iw) .GT. 290. .AND. wc(iw) .LT. 340. $ .AND. t .GT. 210 .AND. t .LT. 300) THEN yg(iw) = EXP((0.06183-0.000241*wc(iw))*(273.-T)- $ (2.376+0.14757*wc(iw))) ENDIF sq(j,iz,iw) = yg(iw)*qy ENDDO ENDDO ENDIF tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r10(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product of (cross section) x (quantum yield) for CH2O photolysis =* *= (a) CH2O + hv -> H + HCO =* *= (b) CH2O + hv -> H2 + CO =* *= Cross section: Choice between =* *= 1) Bass et al., 1980 (resolution: 0.025 nm) =* *= 2) Moortgat and Schneider (resolution: 1 nm) =* *= 3) Cantrell et al. (orig res.) for > 301 nm, =* *= IUPAC 92, 97 elsewhere =* *= 4) Cantrell et al. (2.5 nm res.) for > 301 nm, =* *= IUPAC 92, 97 elsewhere =* *= 5) Rogers et al., 1990 =* *= 6) new NCAR recommendation, based on averages of =* *= Cantrell et al., Moortgat and Schneider, and Rogers =* *= et al. =* *= Quantum yield: Choice between =* *= 1) Evaluation by Madronich 1991 (unpublished) =* *= 2) IUPAC 89, 92, 97 =* *= 3) Madronich, based on 1), updated 1998. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) INTEGER kdata PARAMETER(kdata=16000) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j, iz, iw * data arrays INTEGER n real x(kdata), y(kdata) real xl(kdata), xc(kdata), xu(kdata) INTEGER n1, n2, n3, n4, n5 REAL x1(kdata), x2(kdata), x3(kdata), x4(kdata), x5(kdata) REAL y1(kdata), y2(kdata), y3(kdata), y4(kdata), y5(kdata) * local REAL yg(kw), yg1(kw), yg2(kw), yg3(kw), yg4(kw), yg5(kw) REAL a, b, c REAL a0, a1, a2, a3, a4, a5, a6, a7 REAL b0, b1, b2, b3, b4 REAL phi1, phi2, phi20, ak300, akt REAL qy, qy1, qy2, qy3 REAL sigma, sig, slope REAL xs REAL t REAL dum INTEGER idum INTEGER i INTEGER irow, icol, irev INTEGER ierr INTEGER mopt1, mopt2 *_______________________________________________________________________ DO 5, iw = 1, nw - 1 wc(iw) = (wl(iw) + wl(iw+1))/2. 5 CONTINUE **************************************************************** **************** CH2O photodissociatation j = j+1 jlabel(j) = 'CH2O -> H + HCO' j = j+1 jlabel(j) = 'CH2O -> H2 + CO' * working grid arrays: * yg1 = cross section at a specific temperature * yg2, yg3 = cross sections at different temp or slope, for calculating * temperature depedence * yg4 = quantum yield data for radical channel * yg5 = quantum yield data for molecular channel * Input data options: * mopt1 for absorption: * 1: DATAJ1/CH2O/CH2O_nbs.abs' * from Bass et al., Planet. Space. Sci. 28, 675, 1980. * over 258.750-359.525 in 0.025 nm steps * 2: DATAJ1/CH2O_iupac1.abs * Moortgat and Schneider, personal communication as reported in IUPAC 89, 92, 97 * at 285K. Over 240-360 nm in 1 nm bins (note that IUPAC 89,92,97 incorectly * claims 0.5 nm intervals in footnote) * 3: DATAJ1/CH2O/ch2o_can_hr.abs for wc > 301 nm, temperature dependent * DATAJ1/CH2O/ch2o_iupac1.abs elsewhere * from Cantrell et al. 1990 for wc > 301 nm. Original data from Cantrell, * at high resolution * 4: DATAJ1/CH2O/CH2O_can_lr.abs for wc > 301 nm, temperature dependent * DATAJ1/CH2O/CH2O_iupac1.abs elsewhere * from Cantrell et al. 1990 for wc > 301 nm. Data from Cantrell et al., as * reported by IUPAC'92,'97. On 2.5 nm intervals. * 5: DATAJ1/CH2O/CH2O_rog.abs' * from Rogers et al., J. Phys. Chem. 94, 4011, 1990. * 6: DATAJ2/CH2O_ncar.abs * new NCAR recommendation, based on averages of Moortgat and Schneider, Cantrell et al., * and Rogers. * mopt2 for quantum yields: * 1: DATAJ1/CH2O/CH2O_i_mad.yld and * DATAJ1/CH2O/CH2O_ii_mad.yld * evaluated by Madronich, 1991, unpublished * 2: DATAJ1/CH2O/CH2O_iupac.yld * from IUPAC'89, '92, '97 * 3: DATAJ1/CH2O/CH2O_jpl97.dat' * based on Madronich 1991 unpublished evaluation, updated Jan 1998. mopt1 = 6 mopt2 = 1 IF (mopt1 .EQ. 1) THEN * read NBS/Bass data OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH2O/CH2O_nbs.abs' $ ,STATUS='old') n = 4032 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,n, 0.,0.) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg1,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j-1) STOP ENDIF ELSEIF (mopt1 .EQ. 2 .OR. mopt1 .EQ. 3 .OR. mopt1 .EQ. 4) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH2O_iupac1.abs',STATUS='old') DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n = 121 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) y(i) = y(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,n, 0.,0.) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg1,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j-1) STOP ENDIF IF(mopt1 .EQ. 3) THEN * data are on wavenumber grid (cm-1), so convert to wavelength in nm: * grid was on increasing wavenumbers, so need to reverse to get increasing * wavelengths * cross section assumed to be zero for wavelengths longer than 360 nm * if y1 < 0, then make = 0 (some negative cross sections, actually 273 K intercepts * are in the original data, Here, make equal to zero) OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH2O/CH2O_can_hr.abs', & STATUS='old') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i) x1(i) = 1./x1(i) * 1E7 IF (x1(i) .GT. 360.) THEN y1(i) = 0. y2(i) = 0. ENDIF ENDDO CLOSE(UNIT=ilu) DO i = 1, n/2 irev = n+1-i dum = x1(i) x1(i) = x1(irev) x1(irev) = dum dum = y1(i) y1(i) = y1(irev) y1(irev) = dum dum = y2(i) y2(i) = y2(irev) y2(irev) = dum ENDDO DO i = 1, n x2(i) = x1(i) y1(i) = max(y1(i),0.) ENDDO n1 = n n2 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1E38,0.) CALL inter2(nw,wl,yg2,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1E38,0.) CALL inter2(nw,wl,yg3,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mopt1 .eq. 4) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH2O/CH2O_can_lr.abs', $ STATUS='old') DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n = 23 DO i = 1, n READ(UNIT=ilu,FMT=*) x2(i), y2(i), y3(i), dum, dum x3(i) = x2(i) ENDDO CLOSE(UNIT=ilu) n2 = n n3 = n CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1E38,0.) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x3,y3,kdata,n3,x3(1)*(1.-deltax),0.) CALL addpnt(x3,y3,kdata,n3, 0.,0.) CALL addpnt(x3,y3,kdata,n3,x3(n3)*(1.+deltax),0.) CALL addpnt(x3,y3,kdata,n3, 1E38,0.) CALL inter2(nw,wl,yg3,n3,x3,y3,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF ELSEIF (mopt1 .EQ. 5) THEN * read Rodgers data OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH2O/CH2O_rog.abs' $ ,STATUS='old') DO i = 1, 10 READ(UNIT=ilu,FMT=*) ENDDO n = 261 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i), dum y(i) = y(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,n, 0.,0.) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg1,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j-1) STOP ENDIF ELSEIF(mopt1 .EQ. 6) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH2O/CH2O_ncar.abs', & STATUS='old') DO i = 1, 3 READ(UNIT=ilu,FMT=*) ENDDO n = 126 DO i = 1, n READ(UNIT=ilu,FMT=*) x2(i), y2(i), y3(i) x3(i) = x2(i) ENDDO CLOSE(UNIT=ilu) n2 = n n3 = n CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1E38,0.) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x3,y3,kdata,n3,x3(1)*(1.-deltax),0.) CALL addpnt(x3,y3,kdata,n3, 0.,0.) CALL addpnt(x3,y3,kdata,n3,x3(n3)*(1.+deltax),0.) CALL addpnt(x3,y3,kdata,n3, 1E38,0.) CALL inter2(nw,wl,yg3,n3,x3,y3,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF * quantum yield IF (mopt2 .EQ. 1) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH2O/CH2O_i_mad.yld', & STATUS='old') DO i = 1, 11 READ(UNIT=ilu,FMT=*) ENDDO n = 20 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),y(1)) CALL addpnt(x,y,kdata,n, 0.,y(1)) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg4,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j-1) STOP ENDIF OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH2O/CH2O_ii_mad.yld', & STATUS='old') DO i = 1, 9 READ(UNIT=ilu,FMT=*) ENDDO n = 33 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),y(1)) CALL addpnt(x,y,kdata,n, 0.,y(1)) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg5,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mopt2 .EQ. 2) then OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH2O/CH2O_iupac.yld', & STATUS='old') DO i = 1, 7 READ(UNIT=ilu,FMT=*) ENDDO n = 13 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i) x2(i) = x1(i) ENDDO CLOSE(UNIT=ilu) n1 = n n2 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),y1(1)) CALL addpnt(x1,y1,kdata,n1, 0.,y1(1)) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg4,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),y2(1)) CALL addpnt(x2,y2,kdata,n2, 0.,y2(1)) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1.e+38,0.) CALL inter2(nw,wl,yg5,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * box-filling interpolation. c DO i = 1, n c READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i) c x1(i) = x1(i) - 5.0 c x2(i) = x1(i) c ENDDO c n = n + 1 c x1(n) = x1(n-1) + 5.0 c x2(n) = x1(n) c CLOSE(UNIT=ilu) c DO i = 1, n-1 c y1(i) = y1(i) * (x1(i+1)-x1(i)) c ENDDO c CALL inter3(nw,wl,yg4,n,x1,y1,0) c DO iw = 1, nw-1 c yg4(iw) = yg4(iw)/(wl(iw+1)-wl(iw)) c ENDDO c DO i = 1, n-1 c y2(i) = y2(i) * (x2(i+1)-x2(i)) c ENDDO c CALL inter3(nw,wl,yg5,n,x2,y2,0) c DO iw = 1, nw-1 c yg5(iw) = yg5(iw)/(wl(iw+1)-wl(iw)) c ENDDO ELSE IF(mopt2 .EQ. 3) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH2O/CH2O_jpl97.dat', & STATUS='old') DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n = 23 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), dum, dum, dum, dum, y1(i), y2(i) x2(i) = x1(i) ENDDO CLOSE(UNIT=ilu) n1 = n n2 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),y1(1)) CALL addpnt(x1,y1,kdata,n1, 0.,y1(1)) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg4,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),y2(1)) CALL addpnt(x2,y2,kdata,n2, 0.,y2(1)) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1.e+38,0.) CALL inter2(nw,wl,yg5,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF * combine * y1 = xsect * y2 = xsect(223), Cantrell et al. * y3 = xsect(293), Cantrell et al. * y4 = qy for radical channel * y5 = qy for molecular channel * pressure and temperature dependent for w > 330. DO iw = 1, nw - 1 IF (mopt1 .eq. 6) THEN sig = yg2(iw) ELSE sig = yg1(iw) ENDIF DO i = 1, nz * correct cross section for temperature dependence for > 301. nm IF (wl(iw) .GE. 301.) THEN t = MAX(223.15, MIN(tlev(i), 293.15)) IF (mopt1 .EQ. 3 .OR. mopt1 .EQ. 6) THEN sig = yg2(iw) + yg3(iw) * (t - 273.15) ELSEIF (mopt1 .EQ. 4) THEN slope = (yg3(iw) - yg2(iw)) / (293. - 223.) sig = yg2(iw) + slope * (t - 223.) ENDIF ENDIF sig = MAX(sig, 0.) * quantum yields: * temperature and pressure dependence beyond 330 nm qy1 = yg4(iw) IF ( (wc(iw) .GE. 330.) .AND. (yg5(iw) .GT. 0.) ) THEN phi1 = yg4(iw) phi2 = yg5(iw) phi20 = 1. - phi1 ak300=((1./phi2)-(1./phi20))/2.54E+19 akt=ak300*(1.+61.69*(1.-tlev(i)/300.)*(wc(iw)/329.-1.)) qy2 = 1. / ( (1./phi20) + airden(i)*akt) ELSE qy2 = yg5(iw) ENDIF qy2 = MAX(0.,qy2) qy2 = MIN(1.,qy2) sq(j-1,i,iw) = sig * qy1 sq(j ,i,iw) = sig * qy2 ENDDO ENDDO * declare T and P dependence tpflag(j) = 3 RETURN END *=============================================================================* SUBROUTINE r11(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for CH3CHO photolysis: =* *= (a) CH3CHO + hv -> CH3 + HCO =* *= (b) CH3CHO + hv -> CH4 + CO =* *= (c) CH3CHO + hv -> CH3CO + H =* *= Cross section: Choice between =* *= (1) IUPAC 97 data, from Martinez et al. =* *= (2) Calvert and Pitts =* *= (3) Martinez et al., Table 1 scanned from paper =* *= (4) KFA tabulations =* *= Quantum yields: Choice between =* *= (1) IUPAC 97, pressure correction using Horowith and =* *= Calvert, 1982 =* *= (2) NCAR data file, from Moortgat, 1986 =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=150) INTEGER i, n INTEGER n1, n2 REAL x1(kdata), x2(kdata) REAL y1(kdata), y2(kdata) * local REAL yg(kw), yg1(kw), yg2(kw), yg3(kw), yg4(kw) REAL qy1, qy2, qy3 REAL sig REAL dum INTEGER ierr INTEGER iz, iw REAL qy1_n0, qy1_0, x INTEGER mabs, myld **************************************************************** ************************* CH3CHO photolysis * 1: CH3 + HCO * 2: CH4 + CO * 3: CH3CO + H j = j+1 jlabel(j) = 'CH3CHO -> CH3 + HCO' j = j+1 jlabel(j) = 'CH3CHO -> CH4 + CO' j = j+1 jlabel(j) = 'CH3CHO -> CH3CO + H' * options * mabs for cross sections * myld for quantum yields * Absorption: * 1: IUPAC-97 data, from Martinez et al. * 2: Calvert and Pitts * 3: Martinez et al., Table 1 scanned from paper * 4: KFA tabulations, 6 choices, see file OPEN statements * 5: JPL2011 * Quantum yield * 1: DATAJ1/CH3CHO/CH3CHO_iup.yld * pressure correction using Horowitz and Calvert 1982, based on slope/intercept * of Stern-Volmer plots * 2: ncar data file, from Moortgat 1986. * DATAJ1/CH3CHO/d021_i.yld * DATAJ1/CH3CHO/d021_i.yld * DATAJ1/CH3CHO/d021_i.yld mabs = 5 myld = 1 IF (mabs .EQ. 1) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3CHO/CH3CHO_iup.abs', & STATUS='old') do i = 1, 4 read(UNIT=ilu,FMT=*) enddo n = 106 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs .EQ. 2) THEN * cross section from Calvert and Pitts OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3CHO/d021_cp.abs', & STATUS='old') DO i = 1, 14 READ(UNIT=ilu,FMT=*) ENDDO n = 54 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) x1(i) = x1(i)/10. y1(i) = y1(i) * 3.82E-21 ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs .EQ. 3) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3CHO/CH3CHO_mar.abs', & STATUS='old') DO i = 1, 3 READ(UNIT=ilu,FMT=*) ENDDO n = 106 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs .EQ. 4) THEN * cross section from KFA tables * ch3cho.001 - Calvert and Pitts 1966 * ch3cho.002 - Meyrahn thesis 1984 * ch3cho.003 - Schneider and Moortgat, priv comm. MPI Mainz 1989, 0.012 nm resol. * ch3cho.004 - Schneider and Moortgat, priv comm. MPI Mainz 1989, 0.08 nm resol. * ch3cho.005 - IUPAC'92 * ch3cho.006 - Libuda, thesis Wuppertal 1992 c OPEN(NEWUNIT=ilu,FILE='DATAJ2/KFA/ch3cho.001',STATUS='old') C n = 217 c OPEN(NEWUNIT=ilu,FILE='DATAJ2/KFA/ch3cho.002',STATUS='old') c n = 63 c OPEN(NEWUNIT=ilu,FILE='DATAJ2/KFA/ch3cho.003',STATUS='old') c n = 13738 c OPEN(NEWUNIT=ilu,FILE='DATAJ2/KFA/ch3cho.004',STATUS='old') c n = 2053 OPEN(NEWUNIT=ilu,FILE='DATAJ2/KFA/ch3cho.005',STATUS='old') n = 18 c OPEN(NEWUNIT=ilu,FILE='DATAJ2/KFA/ch3cho.006',STATUS='old') c n = 1705 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF (mabs .EQ. 5) THEN OPEN(NEWUNIT=ilu, $ FILE='DATAJ1/CH3CHO/CH3CHO_jpl11.abs',STATUS='old') do i = 1, 2 read(UNIT=ilu,FMT=*) enddo n = 101 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF * quantum yields IF (myld .EQ. 1) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3CHO/CH3CHO_iup.yld', & STATUS='old') do i = 1, 4 read(UNIT=ilu,FMT=*) enddo n = 12 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y2(i), y1(i) x2(i) = x1(i) ENDDO CLOSE(UNIT=ilu) n1 = n n2 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1.e+38,0.) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF DO iw = 1, nw-1 yg3(iw) = 0. ENDDO ELSEIF (myld .EQ. 2) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3CHO/d021_i.yld',STATUS='old') DO i = 1, 18 READ(UNIT=ilu,FMT=*) ENDDO n = 10 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),y1(1)) CALL addpnt(x1,y1,kdata,n, 0.,y1(1)) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg1,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3CHO/d021_ii.yld', & STATUS='old') DO i = 1, 10 READ(UNIT=ilu,FMT=*) ENDDO n = 9 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),y1(1)) CALL addpnt(x1,y1,kdata,n, 0.,y1(1)) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg2,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3CHO/d021_iii.yld', & STATUS='old') DO i = 1, 10 READ(UNIT=ilu,FMT=*) ENDDO n = 9 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),y1(1)) CALL addpnt(x1,y1,kdata,n, 0.,y1(1)) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg3,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF * pressure-dependence parameters OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3CHO/CH3CHO_press.yld', $ STATUS='old') do i = 1, 4 read(UNIT=ilu,FMT=*) enddo n = 5 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), dum, dum, y1(i) ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg4,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * combine: DO iw = 1, nw - 1 sig = yg(iw) * quantum yields: * input yields at n0 = 1 atm qy1_n0 = yg1(iw) qy2 = yg2(iw) qy3 = yg3(iw) * Pressure correction for CH3 + CHO channel: * Assume pressure-dependence only for qy1, not qy2 or qy2. * Assume total yield 1 at zero pressure qy1_0 = 1. - qy2 - qy3 * compute coefficient: * Stern-Volmer: 1/q = 1/q0 + k N and N0 = 1 atm, * then x = K N0 q0 = qy_0/qy_N0 - 1 if (qy1_n0 .gt. 0.) then x = qy1_0/qy1_n0 - 1. else x = 0. endif * use instead slope/intercept ratio from Horowitz and Calvert 1982, c x = yg4(iw) DO i = 1, nz qy1 = qy1_n0 * (1. + x) / (1. + x * airden(i)/2.465E19 ) qy1 = MIN(1., qy1) qy1 = MAX(0., qy1) sq(j-2,i,iw) = sig * qy1 sq(j-1,i,iw) = sig * qy2 sq(j ,i,iw) = sig * qy3 ENDDO ENDDO * declare P dependence for channel 1 tpflag(j-2) = 2 tpflag(j) = 0 tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r12(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for C2H5CHO =* *= photolysis: =* *= C2H5CHO + hv -> C2H5 + HCO =* *= =* *= Cross section: Choice between =* *= (1) IUPAC 97 data, from Martinez et al. =* *= (2) Calvert and Pitts, as tabulated by KFA =* *= Quantum yield: IUPAC 97 recommendation =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=150) INTEGER i, n INTEGER n1 REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw), yg1(kw) REAL qy1 REAL sig INTEGER ierr INTEGER iw INTEGER mabs, myld ************************* C2H5CHO photolysis * 1: C2H5 + HCO j = j+1 jlabel(j) = 'C2H5CHO -> C2H5 + HCO' * options * mabs for cross sections * myld for quantum yields * Absorption: * 1: IUPAC-97 data, from Martinez et al. * 2: Calvert and Pitts, as tabulated by KFA. * Quantum yield * 1: IUPAC-97 data mabs = 1 myld = 1 IF (mabs .EQ. 1) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/C2H5CHO/C2H5CHO_iup.abs', $ STATUS='old') do i = 1, 4 read(UNIT=ilu,FMT=*) enddo n = 106 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs .EQ. 2) THEN * cross section from KFA tables * c2h5cho.001 - Calvert and Pitts 1966 OPEN(NEWUNIT=ilu,FILE='DATAJ2/KFA/c2h5cho.001',STATUS='old') n = 83 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF * quantum yields IF (myld .EQ. 1) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/C2H5CHO/C2H5CHO_iup.yld', $ STATUS='old') do i = 1, 4 read(UNIT=ilu,FMT=*) enddo n = 5 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE(UNIT=ilu) n1 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,340.,0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF (myld .EQ. 2) THEN STOP ENDIF * combine: DO iw = 1, nw - 1 DO i = 1, nz sig = yg(iw) * quantum yields: * use Ster-Volmer pressure dependence: IF (yg1(iw) .LT. pzero) THEN qy1 = 0. ELSE qy1 = 1./(1. + (1./yg1(iw) - 1.)*airden(i)/2.45e19) ENDIF qy1 = MIN(qy1,1.) sq(j,i,iw) = sig * qy1 ENDDO ENDDO tpflag(j) = 2 RETURN END *=============================================================================* SUBROUTINE r13(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for CHOCHO =* *= photolysis: =* *= CHOCHO + hv -> Products =* *= =* *= Cross section: Choice between =* *= (1) Plum et al., as tabulated by IUPAC 97 =* *= (2) Plum et al., as tabulated by KFA. =* *= (3) Orlando et al. =* *= (4) Horowitz et al., 2001 =* *= Quantum yield: IUPAC 97 recommendation =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=500) INTEGER i, n, n1, n2, n3 REAL x(kdata), x1(kdata), x2(kdata), x3(kdata) REAL y1(kdata), y2(kdata), y3(kdata) * local REAL yg(kw), yg1(kw), yg2(kw), yg3(kw) REAL qyI, qyII, qyIII REAL sig, dum INTEGER ierr INTEGER iw INTEGER mabs, myld ************************* CHOCHO photolysis * see review by Madronich, Chapter VII in "The Mechansims of * Atmospheric Oxidation of the Alkanes, Calvert et al, Oxford U. * Press, 2000. * Four possible channels: * I H2 + 2 CO * II 2 HCO * III HCHO + CO * IV HCO + H + CO * * Based on that review, the following quantum yield assignments are made: * * qy_I = 0 * qy_II = 0.63 for radiation between 280 and 380 nm * qy_III = 0.2 for radiation between 280 and 380 nm * qy_IV = 0 * The yields for channels II and III were determined by Bauerle et al. (personal * communication from G. Moortgat, still unpublished as of Dec 2000). * Bauerle et al. used broad-band irradiation 280-380 nm. * According to Zhu et al., the energetic threshold (for II) is 417 nm. Therefore, * here the quantum yields were set to zero for wc > 417. Furthermore, the * qys of Bauerle et al. were reduced to give the same J values when using full solar * spectrum. The reduction factor was calculated by comparing the J-values (for * high sun) using the 380 and 417 cut offs. The reduction factor is 7.1 j = j+1 jlabel(j) = 'CHOCHO -> HCO + HCO' j = j + 1 jlabel(j) = 'CHOCHO -> H2 + 2CO' j = j + 1 jlabel(j) = 'CHOCHO -> CH2O + CO' * options * mabs for cross sections * myld for quantum yields * Absorption: * 1: Plum et al., as tabulated by IUPAC-97 * 2: Plum et al., as tabulated by KFA. * 3: Orlando, J. J.; G. S. Tyndall, 2001: The atmospheric chemistry of the * HC(O)CO radical. Int. J. Chem. Kinet., 33, 149-156. * 4: Horowitz, A., R. Meller, and G. K. Moortgat, * The UV-VIS absorption cross sectiono of the a-dicarbonyl compounds: * pyruvic acid, biacetyl, and glyoxal. * J. Photochem. Photobiol. A:Chemistry, v.146, pp.19-27, 2001. * 5: From JPL 2011, derived mostly from Volkamer et al. * Quantum yield * 1: IUPAC-97 data * 2: JPL 2011 mabs = 5 myld = 2 IF (mabs .EQ. 1) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CHOCHO/CHOCHO_iup.abs', $ STATUS='old') DO i = 1, 4 read(UNIT=ilu,FMT=*) ENDDO n = 110 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs .EQ. 2) THEN * cross section from KFA tables * chocho.001 - Plum et al. 1983 OPEN(NEWUNIT=ilu,FILE='DATAJ2/KFA/chocho.001',STATUS='old') n = 219 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs .EQ. 3) THEN * cross section from Orlando et la. * Orlando, J. J.; G. S. Tyndall, 2001: The atmospheric chemistry of the * HC(O)CO radical. Int. J. Chem. Kinet., 33, 149-156. OPEN(NEWUNIT=ilu, $ FILE='DATAJ1/CHOCHO/glyoxal_orl.abs',STATUS='old') do i = 1, 6 read(UNIT=ilu,FMT=*) enddo n = 481 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs .EQ. 4) THEN OPEN(NEWUNIT=ilu, $ FILE='DATAJ1/CHOCHO/glyoxal_horowitz.abs',STATUS='old') DO i = 1, 8 read(UNIT=ilu,FMT=*) ENDDO n = 270 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.e-20 ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs .eq. 5) then open(newunit=ilu, $ FILE='DATAJ1/CHOCHO/glyoxal_jpl11.abs',STATUS='old') DO i = 1, 2 read(UNIT=ilu,FMT=*) ENDDO n = 277 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.e-20 ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF * quantum yields IF(myld .eq. 2) then open(newunit=ilu, $ FILE='DATAJ1/CHOCHO/glyoxal_jpl11.qy',STATUS='old') DO i = 1, 3 read(UNIT=ilu,FMT=*) ENDDO n = 40 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), dum, y1(i), y2(i), y3(i) ENDDO CLOSE (UNIT=ilu) n1 = n do i = 1, n x1(i) = x(i) enddo CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),y1(1)) CALL addpnt(x1,y1,kdata,n1, 0.,y1(1)) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF n2 = n do i = 1, n x1(i) = x(i) enddo CALL addpnt(x1,y2,kdata,n2,x1(1)*(1.-deltax),y2(1)) CALL addpnt(x1,y2,kdata,n2, 0.,y2(1)) CALL addpnt(x1,y2,kdata,n2,x1(n2)*(1.+deltax),0.) CALL addpnt(x1,y2,kdata,n2, 1.e+38,0.) CALL inter2(nw,wl,yg2,n2,x1,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF n3 = n do i = 1, n x1(i) = x(i) enddo CALL addpnt(x1,y3,kdata,n3,x1(1)*(1.-deltax),y3(1)) CALL addpnt(x1,y3,kdata,n3, 0.,y3(1)) CALL addpnt(x1,y3,kdata,n3,x1(n3)*(1.+deltax),0.) CALL addpnt(x1,y3,kdata,n3, 1.e+38,0.) CALL inter2(nw,wl,yg3,n3,x1,y3,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF * combine: DO iw = 1, nw - 1 sig = yg(iw) * quantum yields: IF(myld .EQ. 1) THEN * Use values from Bauerle, but corrected to cutoff at 417 rather than 380. * this correction is a reduction by 7.1. * so that qyI = 0.63/7.1 and qyII = 0.2/7.1 qyII = 0. if(wc(iw) .lt. 417. ) then qyI = 0.089 qyIII = 0.028 else qyI = 0. qyIII = 0. endif DO i = 1, nz sq(j-2,i,iw) = sig * qyI sq(j-1,i,iw) = sig * qyII sq(j, i,iw) = sig * qyIII ENDDO ELSEIF(myld .EQ. 2) THEN DO i = 1, nz sq(j-2,i,iw) = sig * yg1(iw) sq(j-1,i,iw) = sig * yg2(iw) sq(j, i,iw) = sig * yg3(iw) ENDDO ENDIF ENDDO tpflag(j-2) = 0 tpflag(j-1) = 0 tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r14(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for CH3COCHO =* *= photolysis: =* *= CH3COCHO + hv -> CH3CO + HCO =* *= =* *= Cross section: Choice between =* *= (1) from Meller et al., 1991, as tabulated by IUPAC 97 =* *= 5 nm resolution (table 1) for < 402 nm =* *= 2 nm resolution (table 2) for > 402 nm =* *= (2) average at 1 nm of Staffelbach et al., 1995, and =* *= Meller et al., 1991 =* *= (3) Plum et al., 1983, as tabulated by KFA =* *= (4) Meller et al., 1991 (0.033 nm res.), as tab. by KFA =* *= (5) Meller et al., 1991 (1.0 nm res.), as tab. by KFA =* *= (6) Staffelbach et al., 1995, as tabulated by KFA =* *= Quantum yield: Choice between =* *= (1) Plum et al., fixed at 0.107 =* *= (2) Plum et al., divided by 2, fixed at 0.0535 =* *= (3) Staffelbach et al., 0.45 for < 300 nm, 0 for > 430 nm=* *= linear interp. in between =* *= (4) Koch and Moortgat, prv. comm., 1997 =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=500) INTEGER i, n INTEGER n1, n2 REAL x1(kdata), x2(kdata) REAL y1(kdata), y2(kdata) real x(kdata), y(kdata) * local REAL yg(kw), yg1(kw), yg2(kw) REAL qy REAL sig INTEGER ierr INTEGER iw INTEGER mabs, myld REAL phi0, kq ************************* CH3COCHO photolysis * 1: CH3COCHO j = j+1 jlabel(j) = 'CH3COCHO -> CH3CO + HCO' * options * mabs for cross sections * myld for quantum yields * Absorption: * 1: from Meller et al. (1991), as tabulated by IUPAC-97 * for wc < 402, use coarse data (5 nm, table 1) * for wc > 402, use finer data (2 nm, table 2) * 2: average at 1nm of Staffelbach et al. 1995 and Meller et al. 1991 * Cross section from KFA tables: * 3: ch3cocho.001 - Plum et al. 1983 * 4: ch3cocho.002 - Meller et al. 1991, 0.033 nm resolution * 5: ch3cocho.003 - Meller et al. 1991, 1.0 nm resolution * 6: ch3cocho.004 - Staffelbach et al. 1995 * 7: use synthetic spectrum, average of CHOCHO and CH3COCOCH3: * 8: cross section from JPL2011 * Quantum yield * 1: Plum et al., 0.107 * 2: Plum et al., divided by two = 0.0535 * 3: Staffelbach et al., 0.45 at wc .le. 300, 0 for wc .gt. 430, linear * interpl in between * 4: Koch and Moortgat, prv. comm. 1997. - pressure-dependent * 5: Chen, Y., W. Wang, and L. Zhu, Wavelength-dependent photolysis of methylglyoxal * in the 290-440 nm region, J Phys Chem A, 104, 11126-11131, 2000. mabs = 8 myld = 5 IF (mabs .EQ. 1) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3COCHO/CH3COCHO_iup1.abs', $ STATUS='old') do i = 1, 4 read(UNIT=ilu,FMT=*) enddo n = 38 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg1,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3COCHO/CH3COCHO_iup2.abs', $ STATUS='old') do i = 1, 4 read(UNIT=ilu,FMT=*) enddo n = 75 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg2,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF DO iw = 1, nw-1 IF(wc(iw) .LT. 402.) THEN yg(iw) = yg1(iw) ELSE yg(iw) = yg2(iw) ENDIF ENDDO ELSEIF(mabs .EQ. 2) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3COCHO/CH3COCHO_ncar.abs', $ STATUS='old') n = 271 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs .GT. 2 .and. mabs .lt. 7) THEN * cross section from KFA tables * ch3cocho.001 - Plum et al. 1983 * ch3cocho.002 - Meller et al. 1991, 0.033 nm resolution * ch3cocho.003 - Meller et al. 1991, 1.0 nm resolution * ch3cocho.004 - Staffelbach et al. 1995 IF(mabs .EQ. 3) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ2/KFA/ch3cocho.001', & STATUS='old') n = 136 ELSEIF(mabs .EQ. 4) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ2/KFA/ch3cocho.002', & STATUS='old') n = 8251 ELSEIF(mabs .EQ. 5) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ2/KFA/ch3cocho.003', & STATUS='old') n = 275 ELSEIF(mabs .EQ. 6) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ2/KFA/ch3cocho.004', & STATUS='old') n = 162 ENDIF DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs .EQ. 7) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3COCOCH3/biacetyl_plum.abs', $ STATUS='old') DO i = 1, 7 READ(UNIT=ilu,FMT=*) ENDDO n = 55 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) y(i) = y(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,n, 0.,0.) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg1,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF OPEN(NEWUNIT=ilu, $ FILE='DATAJ1/CHOCHO/glyoxal_orl.abs',STATUS='old') do i = 1, 6 read(UNIT=ilu,FMT=*) enddo n = 481 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg2,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF do iw = 1, nw-1 yg(iw) = 0.5*(yg1(iw) + yg2(iw)) enddo ELSEIF(mabs .eq. 8) then OPEN(NEWUNIT=ilu, $ FILE='DATAJ1/CH3COCHO/CH3COCHO_jpl11.abs',STATUS='old') do i = 1, 2 read(UNIT=ilu,FMT=*) enddo n = 294 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.e-20 ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF * quantum yields IF(myld .EQ. 4) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3COCHO/CH3COCHO_km.yld', $ STATUS='old') DO i = 1, 5 READ(UNIT=ilu,FMT=*) ENDDO n = 5 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i) x2(i) = x1(i) ENDDO CLOSE (UNIT=ilu) n1 = n n2 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),1.) CALL addpnt(x1,y1,kdata,n1, 0.,1.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),1.) CALL addpnt(x2,y2,kdata,n2, 0.,1.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1.e+38,0.) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF * combine: DO iw = 1, nw - 1 sig = yg(iw) DO i = 1, nz * quantum yields: IF (myld .EQ. 1) THEN qy = 0.107 ELSEIF(myld .EQ. 2) THEN qy = 0.107/2. ELSEIF(myld .EQ. 3) THEN IF(wc(iw) .LE. 300.) THEN qy = 0.45 ELSE IF (wc(iw) .GE. 430.) THEN qy = 0. ELSE qy = 0.45 + (0-0.45)*(wc(iw)-300.)/(430.-300.) ENDIF ELSEIF(myld .EQ. 4) THEN IF (yg1(iw) .GT. 0.) THEN qy = yg2(iw)/( 1. + (airden(i)/2.465E19) $ * ( (yg2(iw)/yg1(iw)) - 1.)) ELSE qy = 0. ENDIF ELSEIF(myld .EQ. 5) THEN * zero pressure yield: * 1.0 for wc < 380 nm * 0.0 for wc > 440 nm * linear in between: phi0 = 1. - (wc(iw) - 380.)/60. phi0 = MIN(phi0,1.) phi0 = MAX(phi0,0.) * Pressure correction: quenching coefficient, torr-1 * in air, Koch and Moortgat: kq = 1.36e8 * EXP(-8793/wc(iw)) * in N2, Chen et al: c kq = 1.93e4 * EXP(-5639/wc(iw)) IF(phi0 .GT. 0.) THEN IF (wc(iw) .GE. 380. .AND. wc(iw) .LE. 440.) THEN qy = phi0 / (phi0 + kq * airden(i) * 760./2.456E19) ELSE qy = phi0 ENDIF ELSE qy = 0. ENDIF ENDIF sq(j,i,iw) = sig * qy ENDDO ENDDO tpflag(j) = 2 RETURN END *=============================================================================* SUBROUTINE r15(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for CH3COCH3 photolysis=* *= CH3COCH3 + hv -> Products =* *= =* *= Cross section: Choice between =* *= (1) Calvert and Pitts =* *= (2) Martinez et al., 1991, alson in IUPAC 97 =* *= (3) NOAA, 1998, unpublished as of 01/98 =* *= Quantum yield: Choice between =* *= (1) Gardiner et al, 1984 =* *= (2) IUPAC 97 =* *= (3) McKeen et al., 1997 =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=150) INTEGER i, n INTEGER n1, n2, n3, n4 REAL x1(kdata), x2(kdata), x3(kdata), x4(kdata) REAL y1(kdata), y2(kdata), y3(kdata), y4(kdata) * local REAL yg(kw), yg1(kw), yg2(kw), yg3(kw), yg4(kw) REAL qy REAL sig INTEGER ierr INTEGER iw REAL a, b, t, m, w real fco, fac INTEGER mabs, myld **************** CH3COCH3 photodissociation j = j + 1 jlabel(j) = 'CH3COCH3 -> CH3CO + CH3' * options * mabs for cross sections * myld for quantum yields * Absorption: * 1: cross section from Calvert and Pitts * 2: Martinez et al. 1991, also in IUPAC'97 * 3: NOAA 1998, unpublished as of Jan 98. * 4: JPL-2011 * Quantum yield * 1: Gardiner et al. 1984 * 2: IUPAC 97 * 3: McKeen, S. A., T. Gierczak, J. B. Burkholder, P. O. Wennberg, T. F. Hanisco, * E. R. Keim, R.-S. Gao, S. C. Liu, A. R. Ravishankara, and D. W. Fahey, * The photochemistry of acetone in the upper troposphere: a source of * odd-hydrogen radicals, Geophys. Res. Lett., 24, 3177-3180, 1997. * 4: Blitz, M. A., D. E. Heard, M. J. Pilling, S. R. Arnold, and M. P. Chipperfield * (2004), Pressure and temperature-dependent quantum yields for the * photodissociation of acetone between 279 and 327.5 nm, Geophys. * Res. Lett., 31, L06111, doi:10.1029/2003GL018793. mabs = 4 myld = 4 IF (mabs .EQ. 1) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3COCH3/CH3COCH3_cp.abs', $ STATUS='old') DO i = 1, 6 READ(UNIT=ilu,FMT=*) ENDDO n = 35 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 3.82E-21 ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs .EQ. 2) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3COCH3/CH3COCH3_iup.abs', $ STATUS='old') DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n = 96 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.e-20 ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs .EQ. 3) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3COCH3/CH3COCH3_noaa.abs', $ STATUS='old') DO i = 1, 12 READ(UNIT=ilu,FMT=*) ENDDO n = 135 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i), y3(i) x2(i) = x1(i) x3(i) = x1(i) ENDDO CLOSE (UNIT=ilu) n1 = n n2 = n n3 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1.e+38,0.) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x3,y3,kdata,n3,x3(1)*(1.-deltax),0.) CALL addpnt(x3,y3,kdata,n3, 0.,0.) CALL addpnt(x3,y3,kdata,n3,x3(n3)*(1.+deltax),0.) CALL addpnt(x3,y3,kdata,n3, 1.e+38,0.) CALL inter2(nw,wl,yg3,n3,x3,y3,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs.eq.4) then OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3COCH3/CH3COCH3_jpl11.abs', $ STATUS='old') DO i = 1, 5 READ(UNIT=ilu,FMT=*) ENDDO n = 135 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i), y3(i), y4(i) x2(i) = x1(i) x3(i) = x1(i) x4(i) = x1(i) y1(i) = y1(i) * 1.e-20 y2(i) = y2(i) / 1.e3 y3(i) = y3(i) / 1.e5 y4(i) = y4(i) / 1.e8 ENDDO CLOSE (UNIT=ilu) n1 = n n2 = n n3 = n n4 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1.e+38,0.) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x3,y3,kdata,n3,x3(1)*(1.-deltax),0.) CALL addpnt(x3,y3,kdata,n3, 0.,0.) CALL addpnt(x3,y3,kdata,n3,x3(n3)*(1.+deltax),0.) CALL addpnt(x3,y3,kdata,n3, 1.e+38,0.) CALL inter2(nw,wl,yg3,n3,x3,y3,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x4,y4,kdata,n4,x4(1)*(1.-deltax),0.) CALL addpnt(x4,y4,kdata,n4, 0.,0.) CALL addpnt(x4,y4,kdata,n4,x4(n4)*(1.+deltax),0.) CALL addpnt(x4,y4,kdata,n4, 1.e+38,0.) CALL inter2(nw,wl,yg4,n4,x4,y4,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF IF (myld .EQ. 2) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3COCH3/CH3COCH3_iup.yld', $ STATUS='old') DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n = 9 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg1,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF DO iw = 1, nw - 1 DO i = 1, nz sig = yg(iw) IF(mabs .EQ. 3) THEN *!!! this definition of t is not consistent with JPL2011 t = 298. - tlev(i) t = MIN(t, 298.-235.) t = MAX(t, 0.) sig = yg(iw)*(1. + yg2(iw)*t + yg3(iw)*t*t $ + yg4(iw)*t*t*t) ELSEIF (mabs .eq. 4)THEN t = MIN(MAX(tlev(i), 235.),298.) sig = yg(iw)*(1. + yg2(iw)*t + yg3(iw)*t*t $ + yg4(iw)*t*t*t) ENDIF IF (myld .EQ. 1) THEN qy = 0.0766 + 0.09415*EXP(-airden(i)/3.222e18) ELSEIF (myld .EQ. 2) THEN qy = yg1(iw) ELSEIF (myld .EQ. 3) THEN IF (wc(iw) .LE. 292.) THEN qy = 1. ELSEIF (wc(iw) .GE. 292. .AND. wc(iw) .LT. 308. ) THEN a = -15.696 + 0.05707*wc(iw) b = EXP(-88.81+0.15161*wc(iw)) qy = 1./(a + b*airden(i)) ELSEIF (wc(iw) .GE. 308. .AND. wc(iw) .LT. 337. ) THEN a = -130.2 + 0.42884*wc(iw) b = EXP(-55.947+0.044913*wc(iw)) qy = 1./(a + b*airden(i)) ELSEIF (wc(iw) .GE. 337.) THEN qy = 0. ENDIF qy = max(0., qy) qy = min(1., qy) ELSEIF (myld .eq. 4) then w = wc(iw) t = tlev(i) m = airden(i) CALL qyacet(w, t, m, fco, fac) qy = min(1., max(0.,fac)) ENDIF sq(j,i,iw) = sig*qy ENDDO ENDDO * both T and P tpflag(j) = 3 RETURN END *=============================================================================* SUBROUTINE r16(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for CH3OOH photolysis: =* *= CH3OOH + hv -> CH3O + OH =* *= =* *= Cross section: Choice between =* *= (1) JPL 97 recommendation (based on Vaghjiana and =* *= Ravishankara, 1989), 10 nm resolution =* *= (2) IUPAC 97 (from Vaghjiana and Ravishankara, 1989), =* *= 5 nm resolution =* *= (3) Cox and Tyndall, 1978; only for wavelengths < 280 nm =* *= (4) Molina and Arguello, 1979; might be 40% too high =* *= Quantum yield: Assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) INTEGER i, n REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw) REAL qy INTEGER ierr INTEGER idum INTEGER iw INTEGER mabs **************** CH3OOH photodissociation j = j + 1 jlabel(j) = 'CH3OOH -> CH3O + OH' * mabs: Absorption cross section options: * 1: JPL data base (1985,92,94,97). 1997 is from Vaghjiani and Ravishankara (1989), at * 10 nm resolution * 2: IUPAC97 (from Vaghjiani and Ravishankara (1989) at 5 nm resolution). * 3: Cox and Tyndall (1978), only for wavelengths < 280 nm * 4: Molina and Arguello (1979). According to Vaghjiani and Ravishankara (1989), * Molina and Arguello had a problem measuring CH3OOH, cross sections 40% too high. * 5: JPL2011 mabs = 5 IF (mabs .EQ. 1) THEN c OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3OOH/CH3OOH_jpl85.abs', c $ STATUS='old') c OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3OOH/CH3OOH_jpl92.abs', c $ STATUS='old') c OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3OOH/CH3OOH_jpl94.abs', c $ STATUS='old') OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3OOH/CH3OOH_jpl94.abs', $ STATUS='old') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.E-20 ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF (mabs .EQ. 2) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3OOH/CH3OOH_iup.abs', $ STATUS='old') DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n = 32 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.E-20 ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF (mabs .EQ. 3) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3OOH/CH3OOH_ct.abs', $ STATUS='old') DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n = 12 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF (mabs .EQ. 4) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3OOH/CH3OOH_ma.abs', $ STATUS='old') DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n = 15 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF (mabs .EQ. 5) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3OOH/CH3OOH_jpl11.abs', $ STATUS='old') DO i = 1, 2 READ(UNIT=ilu,FMT=*) ENDDO n = 40 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.e-20 ENDDO CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF * quantum yield = 1 qy = 1. DO iw = 1, nw - 1 DO i = 1, nz sq(j,i,iw) = yg(iw)*qy ENDDO ENDDO * no T or P dep tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r17(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for CH3ONO2 =* *= photolysis: =* *= CH3ONO2 + hv -> CH3O + NO2 =* *= =* *= Cross section: Choice between =* *= (1) Calvert and Pitts, 1966 =* *= (2) Talukdar, Burkholder, Hunter, Gilles, Roberts, =* *= Ravishankara, 1997 =* *= (3) IUPAC 97, table of values for 198K =* *= (4) IUPAC 97, temperature-dependent equation =* *= (5) Taylor et al, 1980 =* *= (6) fit from Roberts and Fajer, 1989 =* *= (7) Rattigan et al., 1992 =* *= (8) Libuda and Zabel, 1995 =* *= Quantum yield: Assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER (kdata = 2000) INTEGER i, n INTEGER iw INTEGER n1, n2 REAL x1(kdata), x2(kdata) REAL y1(kdata), y2(kdata) * local REAL yg(kw), yg1(kw) REAL qy REAL sig INTEGER ierr INTEGER mabs, myld **************** CH3ONO2 photodissociation j = j + 1 jlabel(j) = 'CH3ONO2 -> CH3O + NO2' * mabs: absorption cross section options: * 1: Calvert and Pitts 1966 * 2: Talukdar, Burkholder, Hunter, Gilles, Roberts, Ravishankara, 1997. * 3: IUPAC-97, table of values for 298K. * 4: IUPAC-97, temperature-dependent equation * 5: Taylor et al. 1980 * 6: fit from Roberts and Fajer, 1989 * 7: Rattigan et al. 1992 * 8: Libuda and Zabel 1995 * 9: JPL2011 including T-dependence mabs = 9 IF (mabs .EQ. 1) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/RONO2/CH3ONO2_cp.abs', & STATUS='old') DO i = 1, 3 READ(UNIT=ilu,FMT=*) ENDDO n = 15 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE (UNIT=ilu) n1 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs .EQ. 2) THEN * sigma(T,lambda) = sigma(298,lambda) * exp(B * (T-298)) OPEN(NEWUNIT=ilu,FILE='DATAJ1/RONO2/CH3ONO2_tal.abs', & STATUS='old') DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n = 55 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i) x2(i) = x1(i) y1(i) = y1(i) * 1.e-20 ENDDO CLOSE (UNIT=ilu) n1 = n n2 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),y2(1)) CALL addpnt(x2,y2,kdata,n2, 0.,y2(1)) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),y2(n2)) CALL addpnt(x2,y2,kdata,n2, 1.e+38,y2(n2)) CALL inter2(nw,wl,yg1,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF (mabs .EQ. 3) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/RONO2/CH3ONO2_iup1.abs', $ STATUS='old') DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n = 13 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i)*1e-20 ENDDO CLOSE (UNIT=ilu) n1 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs .EQ. 4) THEN * sigma(T,lambda) = sigma(298,lambda) * 10**(B * T) OPEN(NEWUNIT=ilu,FILE='DATAJ1/RONO2/CH3ONO2_iup2.abs', $ STATUS='old') DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n = 7 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i) x2(i) = x1(i) y1(i) = y1(i) * 1.e-21 y2(i) = y2(i) * 1.e-3 ENDDO CLOSE (UNIT=ilu) n1 = n n2 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),-36.) CALL addpnt(x1,y1,kdata,n1, 0.,-36.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),-36.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,-36.) CALL inter2(nw,wl,yg,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),y2(1)) CALL addpnt(x2,y2,kdata,n2, 0.,y2(1)) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),y2(n2)) CALL addpnt(x2,y2,kdata,n2, 1.e+38,y2(n2)) CALL inter2(nw,wl,yg1,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF (mabs .EQ. 5) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/RONO2/CH3ONO2_tay.abs', $ STATUS='old') DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n = 13 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE (UNIT=ilu) n1 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF (mabs .EQ. 6) THEN DO iw = 1, nw-1 IF(wc(iw) .GT. 284.) THEN yg(iw) = EXP(-1.044e-3*wc(iw)*wc(iw) + $ 0.5309*wc(iw) - 112.4) ELSE yg(iw) = 0. ENDIF ENDDO ELSEIF (mabs .EQ. 7) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/RONO2/CH3ONO2_rat.abs', $ STATUS='old') DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n = 24 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE (UNIT=ilu) n1 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF (mabs .EQ. 8) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/RONO2/CH3ONO2_lib.abs', $ STATUS='old') DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n = 1638 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE (UNIT=ilu) n1 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF (mabs. eq. 9) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/RONO2/CH3ONO2_jpl11.abs', $ STATUS='old') DO i = 1, 2 READ(UNIT=ilu,FMT=*) ENDDO n = 65 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i) y1(i) = y1(i) * 1.e-20 x2(i) = x1(i) y2(i) = y2(i) * 1.e-3 ENDDO CLOSE (UNIT=ilu) n1 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF n2 = n CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1.e+38,0.) CALL inter2(nw,wl,yg1,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF * quantum yield = 1 qy = 1. DO iw = 1, nw - 1 sig = yg(iw) DO i = 1, nz IF(mabs .EQ. 2 .OR. mabs .EQ. 9) THEN sig = yg(iw) * exp (yg1(iw) * (tlev(i)-298.)) ELSEIF (mabs .EQ. 4) THEN sig = yg(iw)*10.**(yg1(iw)*tlev(i)) ENDIF sq(j,i,iw) = qy * sig ENDDO ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r18(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for PAN photolysis: =* *= PAN + hv -> Products =* *= =* *= Cross section: from Talukdar et al., 1995 =* *= Quantum yield: Assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) INTEGER iw INTEGER i, n INTEGER n2 REAL x1(kdata), x2(kdata) REAL y1(kdata), y2(kdata) * local REAL yg(kw), yg2(kw) real qyNO2, qyNO3 REAL sig INTEGER ierr **************** PAN photodissociation j = j+1 jlabel(j) = 'CH3CO(OONO2) -> CH3CO(OO) + NO2' j = j+1 jlabel(j) = 'CH3CO(OONO2) -> CH3CO(O) + NO3' * cross section from Senum et al., 1984, J.Phys.Chem. 88/7, 1269-1270 C OPEN(NEWUNIT=ilu,FILE='DATAJ1/RONO2/PAN_senum.abs',STATUS='OLD') C DO i = 1, 14 C READ(UNIT=ilu,FMT=*) C ENDDO C n = 21 C DO i = 1, n C READ(UNIT=ilu,FMT=*) x1(i), y1(i) C y1(i) = y1(i) * 1.E-20 C ENDDO C CLOSE(UNIT=ilu) C CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) C CALL addpnt(x1,y1,kdata,n, 0.,0.) C CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) C CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) C CALL inter2(nw,wl,yg,n,x1,y1,ierr) C IF (ierr .NE. 0) THEN C WRITE(*,*) ierr, jlabel(j) C STOP C ENDIF * cross section from * Talukdar et al., 1995, J.Geophys.Res. 100/D7, 14163-14174 OPEN(NEWUNIT=ilu,FILE='DATAJ1/RONO2/PAN_talukdar.abs', & STATUS='old') DO i = 1, 14 READ(UNIT=ilu,FMT=*) ENDDO n = 78 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i) y1(i) = y1(i) * 1.E-20 y2(i) = y2(i) * 1E-3 x2(i) = x1(i) ENDDO n2 = n CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1.e+38,0.) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yield: * from JPL 2011 values for >300 nm. qyNO2 = 0.7 qyNO3 = 0.3 DO iw = 1, nw-1 DO i = 1, nz sig = yg(iw) * EXP(yg2(iw)*(tlev(i)-298.)) sq(j-1,i,iw) = qyNO2 * sig sq(j,i,iw) = qyNO3 * sig ENDDO ENDDO tpflag(j-1) = 1 tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r19(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for CCl2O photolysis: =* *= CCl2O + hv -> Products =* *= =* *= Cross section: JPL 94 recommendation =* *= Quantum yield: Unity (Calvert and Pitts) =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw) REAL qy INTEGER i, iw, n, idum INTEGER ierr INTEGER iz ************* CCl2O photodissociation j = j+1 jlabel(j) = 'CCl2O -> Products' *** cross sections from JPL94 recommendation OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/CCl2O_jpl94.abs',STATUS='OLD') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1E38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF *** quantum yield unity (Calvert and Pitts) qy = 1. DO iw = 1, nw-1 DO iz = 1, nz sq(j,iz,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r20(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for CCl4 photolysis: =* *= CCl4 + hv -> Products =* *= Cross section: from JPL 97 recommendation =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw) REAL qy INTEGER i, iw, n, idum INTEGER ierr INTEGER iz INTEGER mabs REAL b0, b1, b2, b3, b4, tcoeff, sig REAL w1, w2, w3, w4, temp ************************************************************** ************* CCl4 photodissociation j = j+1 jlabel(j) = 'CCl4 -> Products' * mabs = 1: jpl 1997 recommendation * mabs = 2: jpl 2011 recommendation, with T dependence mabs = 2 *** cross sections from JPL97 recommendation (identical to 94 data) IF(mabs .EQ. 1) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/CCl4_jpl94.abs',STATUS='OLD') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1E38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs .EQ. 2) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/CCl4_jpl11.abs',STATUS='OLD') DO i = 1, 5 READ(UNIT=ilu,FMT=*) ENDDO n = 44 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1E38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF * compute temperature correction factors: b0 = 1.0739 b1 = -1.6275e-2 b2 = 8.8141e-5 b3 = -1.9811e-7 b4 = 1.5022e-10 *** quantum yield assumed to be unity qy = 1. DO iw = 1, nw-1 * compute temperature correction coefficients: tcoeff = 0. IF(wc(iw) .GT. 194. .AND. wc(iw) .LT. 250.) THEN w1 = wc(iw) w2 = w1**2 w3 = w1**3 w4 = w1**4 tcoeff = b0 + b1*w1 + b2*w2 + b3*w3 + b4*w4 ENDIF DO iz = 1, nz IF(mabs .EQ. 1) THEN sig = yg(iw) ELSEIF (mabs .EQ. 2) THEN temp = tlev(iz) temp = min(max(temp,210.),300.) sig = yg(iw) * 10.**(tcoeff*(temp-295.)) ENDIF sq(j,iz,iw) = qy * sig ENDDO ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r21(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for CClFO photolysis: =* *= CClFO + hv -> Products =* *= Cross section: from JPL 97 =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw) REAL qy INTEGER i, iw, n, idum INTEGER ierr INTEGER iz ************************************************************** ************* CClFO photodissociation j = j+1 jlabel(j) = 'CClFO -> Products' *** cross sections from JPL97 recommendation (identical to 94 recommendation) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/CClFO_jpl94.abs',STATUS='OLD') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1E38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF *** quantum yield unity qy = 1. DO iw = 1, nw-1 DO iz = 1, nz sq(j,iz,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r22(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for CF2O photolysis: =* *= CF2O + hv -> Products =* *= Cross section: from JPL 97 recommendation =* *= Quantum yield: unity (Nolle et al.) =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw) REAL qy INTEGER i, iw, n, idum INTEGER ierr INTEGER iz ************************************************************** ************* CF2O photodissociation j = j+1 jlabel(j) = 'CF2O -> Products' **** cross sections from JPL97 recommendation (identical to 94 recommendation) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/CF2O_jpl94.abs',STATUS='OLD') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1E38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF *** quantum yield unity (Nolle et al.) qy = 1. DO iw = 1, nw-1 DO iz = 1, nz sq(j,iz,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r23(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for CFC-113 photolysis:=* *= CF2ClCFCl2 + hv -> Products =* *= Cross section: from JPL 97 recommendation, linear interp. between =* *= values at 210 and 295K =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) INTEGER n1, n2 REAL x1(kdata), x2(kdata) REAL y1(kdata), y2(kdata) * local REAL yg1(kw), yg2(kw) REAL qy REAL t INTEGER i, iw, n, idum INTEGER iz INTEGER ierr REAL slope ************************************************************** ************* CF2ClCFCl2 (CFC-113) photodissociation j = j+1 jlabel(j) = 'CF2ClCFCl2 (CFC-113) -> Products' *** cross sections from JPL97 recommendation (identical to 94 recommendation) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/CFC-113_jpl94.abs',STATUS='OLD') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i) y1(i) = y1(i) * 1E-20 y2(i) = y2(i) * 1E-20 x2(i) = x1(i) ENDDO CLOSE(UNIT=ilu) n1 = n n2 = n ** sigma @ 295 K CALL addpnt(x1,y1,kdata,n1, x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1E38,0.) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * sigma @ 210 K CALL addpnt(x2,y2,kdata,n2, x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1E38,0.) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF *** quantum yield assumed to be unity qy = 1. DO iz = 1, nz t = MAX(210.,MIN(tlev(iz),295.)) slope = (t-210.)/(295.-210.) DO iw = 1, nw-1 sq(j,iz,iw) = qy * (yg2(iw) + slope*(yg1(iw)-yg2(iw))) ENDDO ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r24(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for CFC-144 photolysis:=* *= CF2ClCF2Cl + hv -> Products =* *= Cross section: from JPL 97 recommendation, linear interp. between values =* *= at 210 and 295K =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) INTEGER n1, n2 REAL x1(kdata), x2(kdata) REAL y1(kdata), y2(kdata) * local REAL yg1(kw), yg2(kw) REAL qy REAL t INTEGER i, iw, n, idum INTEGER ierr INTEGER iz REAL slope ************************************************************** ************* CF2ClCF2Cl (CFC-114) photodissociation j = j+1 jlabel(j) = 'CF2ClCF2Cl (CFC-114) -> Products' **** cross sections from JPL97 recommendation (identical to 94 recommendation) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/CFC-114_jpl94.abs',STATUS='OLD') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i) y1(i) = y1(i) * 1E-20 y2(i) = y2(i) * 1E-20 x2(i) = x1(i) ENDDO CLOSE(UNIT=ilu) n1 = n n2 = n ** sigma @ 295 K CALL addpnt(x1,y1,kdata,n1, x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1E38,0.) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * sigma @ 210 K CALL addpnt(x2,y2,kdata,n2, x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1E38,0.) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF *** quantum yield assumed to be unity qy = 1. DO iz = 1, nz t = MAX(210.,MIN(tlev(iz),295.)) slope = (t-210.)/(295.-210.) DO iw = 1, nw-1 sq(j,iz,iw) = qy * (yg2(iw) + slope*(yg1(iw)-yg2(iw))) ENDDO ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r25(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for CFC-115 photolysis =* *= CF3CF2Cl + hv -> Products =* *= Cross section: from JPL 97 recommendation =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw) REAL qy INTEGER i, iw, n, idum INTEGER ierr INTEGER iz ************************************************************** ************* CF3CF2Cl (CFC-115) photodissociation j = j+1 jlabel(j) = 'CF3CF2Cl (CFC-115) -> Products' **** cross sections from JPL97 recommendation (identical to 94 recommendation) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/CFC-115_jpl94.abs',STATUS='OLD') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1E38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF **** quantum yield assumed to be unity qy = 1. DO iw = 1, nw-1 DO iz = 1, nz sq(j,iz,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r26(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for CFC-111 photolysis =* *= CCl3F + hv -> Products =* *= Cross section: from JPL 97 recommendation =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw) REAL qy REAL t INTEGER i, iw, n, idum INTEGER ierr INTEGER iz ************************************************************** ************* CCl3F (CFC-11) photodissociation j = j+1 jlabel(j) = 'CCl3F (CFC-11) -> Products' **** cross sections from JPL97 recommendation (identical to 94 recommendation) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/CFC-11_jpl94.abs',STATUS='OLD') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1E-20 ENDDO CLOSE(UNIT=ilu) ** sigma @ 298 K CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1E38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF **** quantum yield assumed to be unity qy = 1. DO iz = 1, nz t = 1E-04 * (tlev(iz)-298.) DO iw = 1, nw-1 sq(j,iz,iw) = qy * yg(iw) * EXP((wc(iw)-184.9) * t) ENDDO ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r27(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for CFC-112 photolysis:=* *= CCl2F2 + hv -> Products =* *= Cross section: from JPL 97 recommendation =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw) REAL qy REAL t INTEGER i, iw, n, idum INTEGER ierr INTEGER iz ************************************************************** ************* CCl2F2 (CFC-12) photodissociation j = j+1 jlabel(j) = 'CCl2F2 (CFC-12) -> Products' **** cross sections from JPL97 recommendation (identical to 94 recommendation) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/CFC-12_jpl94.abs',STATUS='OLD') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1E-20 ENDDO CLOSE(UNIT=ilu) ** sigma @ 298 K CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1E38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF **** quantum yield assumed to be unity qy = 1. DO iz = 1, nz t = 1E-04 * (tlev(iz)-298.) DO iw = 1, nw-1 sq(j,iz,iw) = qy * yg(iw) * EXP((wc(iw)-184.9) * t) ENDDO ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r28(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for CH3Br photolysis: =* *= CH3Br + hv -> Products =* *= Cross section: from JPL 97 recommendation =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw) REAL qy INTEGER i, iw, n, idum INTEGER ierr INTEGER iz ************************************************************** ************* CH3Br photodissociation * data from JPL97 (identical to 94 recommendation) j = j+1 jlabel(j) = 'CH3Br -> Products' OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/CH3Br_jpl94.abs',STATUS='OLD') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1E38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF **** quantum yield assumed to be unity qy = 1. DO iw = 1, nw-1 DO iz = 1, nz sq(j,iz,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r29(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for CH3CCl3 photolysis =* *= CH3CCl3 + hv -> Products =* *= Cross section: from JPL 97 recommendation, piecewise linear interp. =* *= of data at 210, 250, and 295K =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) INTEGER n1, n2, n3 REAL x1(kdata), x2(kdata), x3(kdata) REAL y1(kdata), y2(kdata), y3(kdata) * local REAL yg(kw), yg1(kw), yg2(kw), yg3(kw) REAL qy REAL t INTEGER i, iw, n, idum INTEGER ierr INTEGER iz REAL slope ************************************************************** ************* CH3CCl3 photodissociation j = j+1 jlabel(j) = 'CH3CCl3 -> Products' **** cross sections from JPL97 recommendation (identical to 94 recommendation) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/CH3CCl3_jpl94.abs',STATUS='OLD') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i), y3(i) y1(i) = y1(i) * 1E-20 y2(i) = y2(i) * 1E-20 y3(i) = y3(i) * 1E-20 x2(i) = x1(i) x3(i) = x1(i) ENDDO CLOSE(UNIT=ilu) n1 = n n2 = n n3 = n ** sigma @ 295 K CALL addpnt(x1,y1,kdata,n1, x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1E38,0.) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ** sigma @ 250 K CALL addpnt(x2,y2,kdata,n2, x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1E38,0.) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ** sigma @ 210 K CALL addpnt(x3,y3,kdata,n3, x3(1)*(1.-deltax),0.) CALL addpnt(x3,y3,kdata,n3, 0.,0.) CALL addpnt(x3,y3,kdata,n3,x3(n3)*(1.+deltax),0.) CALL addpnt(x3,y3,kdata,n3, 1E38,0.) CALL inter2(nw,wl,yg3,n3,x3,y3,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF **** quantum yield assumed to be unity qy = 1. DO iz = 1, nz t = MIN(295.,MAX(tlev(iz),210.)) IF (t .LE. 250.) THEN slope = (t-210.)/(250.-210.) DO iw = 1, nw-1 sq(j,iz,iw) = qy * (yg3(iw) + slope*(yg2(iw)-yg3(iw))) ENDDO ELSE slope = (t-250.)/(295.-250.) DO iw = 1, nw-1 sq(j,iz,iw) = qy * (yg2(iw) + slope*(yg1(iw)-yg2(iw))) ENDDO ENDIF ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r30(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for CH3Cl photolysis: =* *= CH3Cl + hv -> Products =* *= Cross section: from JPL 97 recommendation, piecewise linear interp. =* *= from values at 255, 279, and 296K =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) INTEGER n1, n2, n3 REAL x1(kdata), x2(kdata), x3(kdata) REAL y1(kdata), y2(kdata), y3(kdata) * local REAL yg(kw), yg1(kw), yg2(kw), yg3(kw) REAL qy REAL t INTEGER i, iw, n, idum INTEGER ierr INTEGER iz REAL slope ************************************************************** ************* CH3Cl photodissociation j = j+1 jlabel(j) = 'CH3Cl -> Products' **** cross sections from JPL97 recommendation (identical to 94 recommendation) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/CH3Cl_jpl94.abs',STATUS='OLD') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i), y3(i) y1(i) = y1(i) * 1E-20 y2(i) = y2(i) * 1E-20 y3(i) = y3(i) * 1E-20 x2(i) = x1(i) x3(i) = x1(i) ENDDO CLOSE(UNIT=ilu) n1 = n n2 = n n3 = n ** sigma @ 296 K CALL addpnt(x1,y1,kdata,n1, x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1E38,0.) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ** sigma @ 279 K CALL addpnt(x2,y2,kdata,n2, x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1E38,0.) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ** sigma @ 255 K CALL addpnt(x3,y3,kdata,n3, x3(1)*(1.-deltax),0.) CALL addpnt(x3,y3,kdata,n3, 0.,0.) CALL addpnt(x3,y3,kdata,n3,x3(n3)*(1.+deltax),0.) CALL addpnt(x3,y3,kdata,n3, 1E38,0.) CALL inter2(nw,wl,yg3,n3,x3,y3,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF **** quantum yield assumed to be unity qy = 1. DO iz = 1, nz t = MAX(255.,MIN(tlev(i),296.)) IF (t .LE. 279.) THEN slope = (t-255.)/(279.-255.) DO iw = 1, nw-1 sq(j,iz,iw) = qy * (yg3(iw)+slope*(yg2(iw)-yg3(iw))) ENDDO ELSE slope = (t-279.)/(296.-279.) DO iw = 1, nw-1 sq(j,iz,iw) = qy * (yg2(iw)+slope*(yg1(iw)-yg2(iw))) ENDDO ENDIF ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r31(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for ClOO photolysis: =* *= ClOO + hv -> Products =* *= Cross section: from JPL 97 recommendation =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) C INTEGER n1, n2, n3, n4, n5 REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw) REAL qy INTEGER i, iw, n, idum INTEGER ierr INTEGER iz ************************************************************** ************* ClOO photodissociation j = j+1 jlabel(j) = 'ClOO -> Products' **** cross sections from JPL97 recommendation (identical to 94 recommendation) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/ClOO_jpl94.abs',STATUS='OLD') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1E38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF **** quantum yield assumed to be unity qy = 1. DO iw = 1, nw-1 DO iz = 1, nz sq(j,iz,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r32(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for HCFC-123 photolysis=* *= CF3CHCl2 + hv -> Products =* *= Cross section: from Orlando et al., 1991 =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * local REAL qy REAL t INTEGER i, iw, idum INTEGER iz, k REAL lambda, sum CHARACTER*120 inline REAL coeff(4,3), TBar, LBar ************************************************************** ************* CF3CHCl2 (HCFC-123) photodissociation j = j+1 jlabel(j) = 'CF3CHCl2 (HCFC-123) -> Products' **** cross sections from JPL94 recommendation C OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/HCFC-123_jpl94.abs',STATUS='OLD') C READ(UNIT=ilu,FMT=*) idum, n C DO i = 1, idum-2 C READ(UNIT=ilu,FMT=*) C ENDDO C DO i = 1, n C READ(UNIT=ilu,FMT=*) x1(i), y1(i) C y1(i) = y1(i) * 1E-20 C ENDDO C CLOSE(UNIT=ilu) C CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) C CALL addpnt(x1,y1,kdata,n, 0.,0.) C CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) C CALL addpnt(x1,y1,kdata,n, 1E38,0.) C CALL inter2(nw,wl,yg,n,x1,y1,ierr) C IF (ierr .NE. 0) THEN C WRITE(*,*) ierr, jlabel(j) C STOP C ENDIF **** quantum yield assumed to be unity C qy = 1. C DO iw = 1, nw-1 C DO iz = 1, nz C sq(j,iz,iw) = qy * yg(iw) C ENDDO C ENDDO **** cross section from Orlando et al., 1991 OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/HCFCs_orl.abs',STATUS='OLD') READ(UNIT=ilu,FMT=*) idum DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO READ(UNIT=ilu,FMT=100) inline 100 FORMAT(A120) READ(inline(6:),*) TBar,i,(coeff(i,k),k=1,3) READ(UNIT=ilu,FMT=*) i,(coeff(i,k),k=1,3) READ(UNIT=ilu,FMT=*) i,(coeff(i,k),k=1,3) READ(UNIT=ilu,FMT=*) i,(coeff(i,k),k=1,3) CLOSE(UNIT=ilu) LBar = 206.214 **** quantum yield assumed to be unity qy = 1. DO iw = 1, nw-1 lambda = wc(iw) C use parameterization only up to 220 nm, as the error bars associated with C the measurements beyond 220 nm are very large (Orlando, priv.comm.) IF (lambda .GE. 190. .AND. lambda .LE. 220.) THEN DO iz = 1, nz t = MIN(295.,MAX(tlev(i),203.))-TBar sum = 0. DO i = 1, 4 sum = (coeff(i,1)+t*(coeff(i,2)+t*coeff(i,3))) * > (lambda-LBar)**(i-1) + sum ENDDO sq(j,iz,iw) = qy * EXP(sum) ENDDO ELSE DO iz = 1, nz sq(j,iz,iw) = 0. ENDDO ENDIF ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r33(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for HCFC-124 photolysis=* *= CF3CHFCl + hv -> Products =* *= Cross section: from Orlando et al., 1991 =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays * local REAL qy REAL t INTEGER i, iw, n, idum INTEGER iz, k REAL lambda, sum CHARACTER*120 inline REAL coeff(4,3), TBar, LBar ************************************************************** ************* CF3CHFCl (HCFC-124) photodissociation j = j+1 jlabel(j) = 'CF3CHFCl (HCFC-124) -> Products' **** cross sections from JPL94 recommendation C OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/HCFC-124_jpl94.abs',STATUS='OLD') C READ(UNIT=ilu,FMT=*) idum, n C DO i = 1, idum-2 C READ(UNIT=ilu,FMT=*) C ENDDO C DO i = 1, n C READ(UNIT=ilu,FMT=*) x1(i), y1(i) C y1(i) = y1(i) * 1E-20 C ENDDO C CLOSE(UNIT=ilu) C CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) C CALL addpnt(x1,y1,kdata,n, 0.,0.) C CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) C CALL addpnt(x1,y1,kdata,n, 1E38,0.) C CALL inter2(nw,wl,yg,n,x1,y1,ierr) C IF (ierr .NE. 0) THEN C WRITE(*,*) ierr, jlabel(j) C STOP C ENDIF **** quantum yield assumed to be unity C qy = 1. C DO iw = 1, nw-1 C DO iz = 1, nz C sq(j,iz,iw) = qy * yg(iw) C ENDDO C ENDDO **** cross section from Orlando et al., 1991 OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/HCFCs_orl.abs',STATUS='OLD') READ(UNIT=ilu,FMT=*) idum idum = idum+5 DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO READ(UNIT=ilu,FMT=100) inline 100 FORMAT(A120) READ(inline(6:),*) TBar,i,(coeff(i,k),k=1,3) READ(UNIT=ilu,FMT=*) i,(coeff(i,k),k=1,3) READ(UNIT=ilu,FMT=*) i,(coeff(i,k),k=1,3) READ(UNIT=ilu,FMT=*) i,(coeff(i,k),k=1,3) CLOSE(UNIT=ilu) LBar = 206.214 **** quantum yield assumed to be unity qy = 1. DO iw = 1, nw-1 lambda = wc(iw) IF (lambda .GE. 190. .AND. lambda .LE. 230.) THEN DO iz = 1, nz t = MIN(295.,MAX(tlev(i),203.))-TBar sum = 0. DO i = 1, 4 sum = (coeff(i,1)+t*(coeff(i,2)+t*coeff(i,3))) * > (lambda-LBar)**(i-1) + sum ENDDO sq(j,iz,iw) = qy * EXP(sum) ENDDO ELSE DO iz = 1, nz sq(j,iz,iw) = 0. ENDDO ENDIF ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r34(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for HCFC-141b =* *= photolysis: =* *= CH3CFCl2 + hv -> Products =* *= Cross section: from JPL97 recommendation =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw) REAL qy INTEGER i, iw, n, idum INTEGER ierr INTEGER iz ************************************************************** ************* CH3CFCl2 (HCFC-141b) photodissociation j = j+1 jlabel(j) = 'CH3CFCl2 (HCFC-141b) -> Products' **** cross sections from JPL97 recommendation (identical to 94 recommendation) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/HCFC-141b_jpl94.abs', & STATUS='old') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1E38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF **** quantum yield assumed to be unity qy = 1. DO iw = 1, nw-1 DO iz = 1, nz sq(j,iz,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r35(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for HCFC-142b =* *= photolysis: =* *= CH3CF2Cl + hv -> Products =* *= Cross section: from Orlando et al., 1991 =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * local REAL qy REAL t INTEGER i, iw, n, idum INTEGER ierr INTEGER iz, k REAL lambda, sum CHARACTER*80 inline REAL coeff(4,3), TBar, LBar ************************************************************** ************* CH3CF2Cl (HCFC-142b) photodissociation j = j+1 jlabel(j) = 'CH3CF2Cl (HCFC-142b) -> Products' **** cross sections from JPL94 recommendation C OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/HCFC-142b_jpl94.abs',STATUS='OLD') C READ(UNIT=ilu,FMT=*) idum, n C DO i = 1, idum-2 C READ(UNIT=ilu,FMT=*) C ENDDO C DO i = 1, n C READ(UNIT=ilu,FMT=*) x1(i), y1(i) C y1(i) = y1(i) * 1E-20 C ENDDO C CLOSE(UNIT=ilu) C CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) C CALL addpnt(x1,y1,kdata,n, 0.,0.) C CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) C CALL addpnt(x1,y1,kdata,n, 1E38,0.) C CALL inter2(nw,wl,yg,n,x1,y1,ierr) C IF (ierr .NE. 0) THEN C WRITE(*,*) ierr, jlabel(j) C STOP C ENDIF **** quantum yield assumed to be unity C qy = 1. C DO iw = 1, nw-1 C DO iz = 1, nz C sq(j,iz,iw) = qy * yg(iw) C ENDDO C ENDDO **** cross section from Orlando et al., 1991 OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/HCFCs_orl.abs',STATUS='OLD') READ(UNIT=ilu,FMT=*) idum idum = idum+10 DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO READ(UNIT=ilu,FMT=100) inline 100 FORMAT(A80) READ(inline(6:),*) TBar,i,(coeff(i,k),k=1,3) READ(UNIT=ilu,FMT=*) i,(coeff(i,k),k=1,3) READ(UNIT=ilu,FMT=*) i,(coeff(i,k),k=1,3) READ(UNIT=ilu,FMT=*) i,(coeff(i,k),k=1,3) CLOSE(UNIT=ilu) LBar = 206.214 **** quantum yield assumed to be unity qy = 1. DO iw = 1, nw-1 lambda = wc(iw) IF (lambda .GE. 190. .AND. lambda .LE. 230.) THEN DO iz = 1, nz t = MIN(295.,MAX(tlev(i),203.))-TBar sum = 0. DO i = 1, 4 sum = (coeff(i,1)+t*(coeff(i,2)+t*coeff(i,3))) * > (lambda-LBar)**(i-1) + sum ENDDO * offeset exponent by 40 (exp(-40.) = 4.248e-18) to prevent exp. underflow errors * on some machines. c sq(j,iz,iw) = qy * EXP(sum) sq(j,iz,iw) = qy * 4.248e-18 * EXP(sum + 40.) ENDDO ELSE DO iz = 1, nz sq(j,iz,iw) = 0. ENDDO ENDIF ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r36(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for HCFC-225ca =* *= photolysis: =* *= CF3CF2CHCl2 + hv -> Products =* *= Cross section: from JPL 97 recommendation =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw) REAL qy INTEGER i, iw, n, idum INTEGER ierr INTEGER iz ************************************************************** ************* CF3CF2CHCl2 (HCFC-225ca) photodissociation j = j+1 jlabel(j) = 'CF3CF2CHCl2 (HCFC-225ca) -> Products' **** cross sections from JPL97 recommendation (identical to 94 recommendation) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/HCFC-225ca_jpl94.abs', & STATUS='OLD') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1E38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF **** quantum yield assumed to be unity qy = 1. DO iw = 1, nw-1 DO iz = 1, nz sq(j,iz,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r37(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for HCFC-225cb =* *= photolysis: =* *= CF2ClCF2CHFCl + hv -> Products =* *= Cross section: from JPL 97 recommendation =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw) REAL qy INTEGER i, iw, n, idum INTEGER ierr INTEGER iz ************************************************************** ************* CF2ClCF2CHFCl (HCFC-225cb) photodissociation j = j+1 jlabel(j) = 'CF2ClCF2CHFCl (HCFC-225cb) -> Products' **** cross sections from JPL97 recommendation (identical to 94 recommendation) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/HCFC-225cb_jpl94.abs', & STATUS='OLD') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1E38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF **** quantum yield assumed to be unity qy = 1. DO iw = 1, nw-1 DO iz = 1, nz sq(j,iz,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r38(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for HCFC-22 photolysis =* *= CHClF2 + hv -> Products =* *= Cross section: from JPL 97 recommendation, piecewise linear interp. =* *= from values at 210, 230, 250, 279, and 295 K =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) INTEGER n1, n2, n3, n4, n5 REAL x1(kdata), x2(kdata), x3(kdata), x4(kdata), x5(kdata) REAL y1(kdata), y2(kdata), y3(kdata), y4(kdata), y5(kdata) * local REAL yg(kw), yg1(kw), yg2(kw), yg3(kw), yg4(kw), yg5(kw) REAL qy REAL t INTEGER i, iw, n, idum INTEGER ierr INTEGER iz REAL slope ************************************************************** ************* CHClF2 (HCFC-22) photodissociation j = j+1 jlabel(j) = 'CHClF2 (HCFC-22) -> Products' **** cross sections from JPL97 recommendation (identical to 94 recommendation) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/HCFC-22_jpl94.abs',STATUS='OLD') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i), y3(i), y4(i), y5(i) y1(i) = y1(i) * 1E-20 y2(i) = y2(i) * 1E-20 y3(i) = y3(i) * 1E-20 y4(i) = y4(i) * 1E-20 y5(i) = y5(i) * 1E-20 x2(i) = x1(i) x3(i) = x1(i) x4(i) = x1(i) x5(i) = x1(i) ENDDO CLOSE(UNIT=ilu) n1 = n n2 = n n3 = n n4 = n n5 = n ** sigma @ 295 K CALL addpnt(x1,y1,kdata,n1, x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1E38,0.) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ** sigma @ 270 K CALL addpnt(x2,y2,kdata,n2, x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1E38,0.) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ** sigma @ 250 K CALL addpnt(x3,y3,kdata,n3, x3(1)*(1.-deltax),0.) CALL addpnt(x3,y3,kdata,n3, 0.,0.) CALL addpnt(x3,y3,kdata,n3,x3(n3)*(1.+deltax),0.) CALL addpnt(x3,y3,kdata,n3, 1E38,0.) CALL inter2(nw,wl,yg3,n3,x3,y3,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ** sigma @ 230 K CALL addpnt(x4,y4,kdata,n4, x4(1)*(1.-deltax),0.) CALL addpnt(x4,y4,kdata,n4, 0.,0.) CALL addpnt(x4,y4,kdata,n4,x4(n4)*(1.+deltax),0.) CALL addpnt(x4,y4,kdata,n4, 1E38,0.) CALL inter2(nw,wl,yg4,n4,x4,y4,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ** sigma @ 210 K CALL addpnt(x5,y5,kdata,n5, x5(1)*(1.-deltax),0.) CALL addpnt(x5,y5,kdata,n5, 0.,0.) CALL addpnt(x5,y5,kdata,n5,x5(n5)*(1.+deltax),0.) CALL addpnt(x5,y5,kdata,n5, 1E38,0.) CALL inter2(nw,wl,yg5,n5,x5,y5,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF **** quantum yield assumed to be unity qy = 1. DO iz = 1, nz t = MIN(295.,MAX(tlev(iz),210.)) IF (t .LE. 230.) THEN slope = (t-210.)/(230.-210.) DO iw = 1, nw-1 sq(j,iz,iw) = qy * (yg5(iw)+slope*(yg4(iw)-yg5(iw))) ENDDO ELSEIF (t .LE. 250.) THEN slope = (t-230.)/(250.-230.) DO iw = 1, nw-1 sq(j,iz,iw) = qy * (yg4(iw)+slope*(yg3(iw)-yg4(iw))) ENDDO ELSEIF (t .LE. 270.) THEN slope = (t-250.)/(270.-250.) DO iw = 1, nw-1 sq(j,iz,iw) = qy * (yg3(iw)+slope*(yg2(iw)-yg3(iw))) ENDDO ELSE slope = (t-270.)/(295.-270.) DO iw = 1, nw-1 sq(j,iz,iw) = qy * (yg2(iw)+slope*(yg1(iw)-yg2(iw))) ENDDO ENDIF ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r39(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for HO2 photolysis: =* *= HO2 + hv -> OH + O =* *= Cross section: from JPL 97 recommendation =* *= Quantum yield: assumed shape based on work by Lee, 1982; normalized =* *= to unity at 248 nm =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw) REAL qy INTEGER i, iw, n, idum INTEGER ierr INTEGER iz ************************************************************** ************* HO2 photodissociation j = j+1 jlabel(j) = 'HO2 -> OH + O' **** cross sections from JPL11 recommendation OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/HO2_jpl11.abs',STATUS='OLD') DO i = 1, 10 READ(UNIT=ilu,FMT=*) ENDDO n = 15 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1E38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF **** quantum yield: absolute quantum yield has not been reported yet, but **** Lee measured a quantum yield for O(1D) production at 248 **** nm that was 15 time larger than at 193 nm **** here: a quantum yield of unity is assumed at 248 nm and beyond, for **** shorter wavelengths a linear decrease with lambda is assumed DO iw = 1, nw-1 IF (wc(iw) .GE. 248.) THEN qy = 1. ELSE qy = 1./15. + (wc(iw)-193.)*(14./15.)/(248.-193.) qy = MAX(qy,0.) ENDIF DO iz = 1, nz sq(j,iz,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r40(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) Halon-1202 photolysis: =* *= CF2Br2 + hv -> Products =* *= Cross section: from JPL 97 recommendation =* *= Quantum yield: unity (Molina and Molina) =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw) REAL qy INTEGER i, iw, n, idum INTEGER ierr INTEGER iz ************************************************************** ************* CF2Br2 (Halon-1202) photodissociation j = j+1 jlabel(j) = 'CF2Br2 (Halon-1202) -> Products' **** cross sections from JPL97 recommendation (identical to 94 recommendation) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/Halon-1202_jpl97.abs', & STATUS='OLD') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1E38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF **** quantum yield unity (Molina and Molina) qy = 1. DO iw = 1, nw-1 DO iz = 1, nz sq(j,iz,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r41(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for Halon-1211 =* *= photolysis: =* *= CF2ClBr + hv -> Products =* *= Cross section: from JPL 97 recommendation =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw) REAL qy INTEGER i, iw, n, idum INTEGER ierr INTEGER iz ************************************************************** ************* CF2BrCl (Halon-1211) photodissociation j = j+1 jlabel(j) = 'CF2BrCl (Halon-1211) -> Products' **** cross sections from JPL97 recommendation (identical to 94 recommendation) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/Halon-1211_jpl97.abs', & STATUS='OLD') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1E38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF **** quantum yield assumed to be unity qy = 1. DO iw = 1, nw-1 DO iz = 1, nz sq(j,iz,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r42(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for Halon-1301 =* *= photolysis: =* *= CF3Br + hv -> Products =* *= Cross section: from JPL 97 recommendation =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw) REAL qy INTEGER i, iw, n, idum INTEGER ierr INTEGER iz ************************************************************** ************* CF3Br (Halon-1301) photodissociation j = j+1 jlabel(j) = 'CF3Br (Halon-1301) -> Products' **** cross sections from JPL97 recommendation (identical to 94 recommendation) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/Halon-1301_jpl97.abs', & STATUS='OLD') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1E38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF **** quantum yield assumed to be unity qy = 1. DO iw = 1, nw-1 DO iz = 1, nz sq(j,iz,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r43(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for Halon-2402 =* *= photolysis: =* *= CF2BrCF2Br + hv -> Products =* *= Cross section: from JPL 97 recommendation =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw) REAL qy INTEGER i, iw, n, idum INTEGER ierr INTEGER iz ************************************************************** ************* CF2BrCF2Br (Halon-2402) photodissociation j = j+1 jlabel(j) = 'CF2BrCF2Br (Halon-2402) -> Products' **** cross sections from JPL97 recommendation (identical to 94 recommendation) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/Halon-2402_jpl97.abs', & STATUS='OLD') READ(UNIT=ilu,FMT=*) idum, n DO i = 1, idum-2 READ(UNIT=ilu,FMT=*) ENDDO DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1E38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF **** quantum yield assumed to be unity qy = 1. DO iw = 1, nw-1 DO iz = 1, nz sq(j,iz,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r44(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for N2O photolysis: =* *= N2O + hv -> N2 + O(1D) =* *= Cross section: from JPL 97 recommendation =* *= Quantum yield: assumed to be unity, based on Greenblatt and Ravishankara =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * local REAL qy REAL a, b, c REAL a0, a1, a2, a3, a4 REAL b0, b1, b2, b3 REAL t INTEGER iw, iz REAL lambda ************************************************************** ************* N2O photodissociation j = j+1 jlabel(j) = 'N2O -> N2 + O(1D)' **** cross sections according to JPL97 recommendation (identical to 94 rec.) **** see file DATAJ1/ABS/N2O_jpl94.abs for detail A0 = 68.21023 A1 = -4.071805 A2 = 4.301146E-02 A3 = -1.777846E-04 A4 = 2.520672E-07 B0 = 123.4014 B1 = -2.116255 B2 = 1.111572E-02 B3 = -1.881058E-05 **** quantum yield of N(4s) and NO(2Pi) is less than 1% (Greenblatt and **** Ravishankara), so quantum yield of O(1D) is assumed to be unity qy = 1. DO iw = 1, nw-1 lambda = wc(iw) IF (lambda .GE. 173. .AND. lambda .LE. 240.) THEN DO iz = 1, nz t = MAX(194.,MIN(tlev(iz),320.)) A = (((A4*lambda+A3)*lambda+A2)*lambda+A1)*lambda+A0 B = (((B3*lambda+B2)*lambda+B1)*lambda+B0) B = (t-300.)*EXP(B) sq(j,iz,iw) = qy * EXP(A+B) ENDDO ELSE DO iz = 1, nz sq(j,iz,iw) = 0. ENDDO ENDIF ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r45(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for ClONO2 photolysis: =* *= ClONO2 + hv -> Products =* *= =* *= Cross section: JPL 97 recommendation =* *= Quantum yield: JPL 97 recommendation =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=150) REAL x1(kdata),x2(kdata),x3(kdata) REAL y1(kdata),y2(kdata),y3(kdata) INTEGER n1, n2, n3 * local REAL yg1(kw), yg2(kw), yg3(kw) REAL qy1, qy2 REAL xs INTEGER i, iw, n, idum INTEGER ierr INTEGER iz ************* ClONO2 photodissociation j = j+1 jlabel(j) = 'ClONO2 -> Cl + NO3' j = j+1 jlabel(j) = 'ClONO2 -> ClO + NO2' *** cross sections from JPL97 recommendation. Same in JPL-2011. OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/ClONO2_jpl97.abs',STATUS='OLD') n = 119 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i), y3(i) y1(i) = y1(i) * 1E-20 x2(i) = x1(i) x3(i) = x1(i) ENDDO CLOSE(UNIT=ilu) n1 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1E38,0.) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF n2 = n CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1E38,0.) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF n3 = n CALL addpnt(x3,y3,kdata,n3,x3(1)*(1.-deltax),0.) CALL addpnt(x3,y3,kdata,n3, 0.,0.) CALL addpnt(x3,y3,kdata,n3,x3(n3)*(1.+deltax),0.) CALL addpnt(x3,y3,kdata,n3, 1E38,0.) CALL inter2(nw,wl,yg3,n3,x3,y3,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF DO iw = 1, nw-1 *** quantum yields (from jpl97, same in jpl2011) IF( wc(iw) .LT. 308.) THEN qy1 = 0.6 ELSEIF( (wc(iw) .GE. 308) .AND. (wc(iw) .LE. 364.) ) THEN qy1 = 7.143e-3 * wc(iw) - 1.6 ELSEIF( wc(iw) .GT. 364. ) THEN qy1 = 1.0 ENDIF qy2 = 1. - qy1 * compute T-dependent cross section DO iz = 1, nz xs = yg1(iw)*( 1. + $ yg2(iw)*(tlev(iz)-296) + $ yg3(iw)*(tlev(iz)-296)*(tlev(iz)-296)) sq(j-1,iz,iw) = qy1 * xs sq(j,iz,iw) = qy2 * xs ENDDO ENDDO tpflag(j-1) = 1 tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r46(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for BrONO2 photolysis: =* *= BrONO2 + hv -> Products =* *= =* *= Cross section: JPL 03 recommendation =* *= Quantum yield: JPL 03 recommendation =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) REAL x1(kdata) REAL y1(kdata) INTEGER n1, n2, n3 * local REAL yg1(kw) REAL qyNO2, qyNO3 INTEGER i, iw, n, idum INTEGER ierr INTEGER iz ************* BrONO2 photodissociation j = j+1 jlabel(j) = 'BrONO2 -> BrO + NO2' j = j+1 jlabel(j) = 'BrONO2 -> Br + NO3' *** cross sections from JPL03 recommendation OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/BrONO2_jpl03.abs',STATUS='OLD') DO i = 1, 13 READ(UNIT=ilu,FMT=*) ENDDO n = 61 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1E-20 ENDDO CLOSE(UNIT=ilu) n1 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1E38,0.) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF *** quantum yields (from jpl97) qyNO2 = 0.15 qyNO3 = 0.85 DO iw = 1, nw-1 DO iz = 1, nz sq(j-1,iz,iw) = qyNO2 * yg1(iw) sq(j,iz,iw) = qyNO3 * yg1(iw) ENDDO ENDDO tpflag(j-1) = 0 tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r47(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for Cl2 photolysis: =* *= Cl2 + hv -> 2 Cl =* *= =* *= Cross section: JPL 97 recommendation =* *= Quantum yield: 1 (Calvert and Pitts, 1966) =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=150) INTEGER i, n REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw) REAL qy INTEGER iz, iw INTEGER ierr integer mabs real aa, bb, ex1, ex2, sig, alpha(kz) ************* CL2 photodissociation j = j+1 jlabel(j) = 'Cl2 -> Cl + Cl' * mabs = 1: Finlayson-Pitts and Pitts * mabs = 2: JPL2011 formula mabs = 2 IF (mabs .EQ. 1) THEN *** cross sections from JPL97 recommendation (as tab by Finlayson-Pitts * and Pitts, 1999. OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/CL2_fpp.abs',STATUS='OLD') do i = 1, 5 read(UNIT=ilu,FMT=*) enddo n = 22 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1E38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs .EQ. 2) THEN DO iz = 1, nz aa = 402.7/tlev(iz) bb = exp(aa) alpha(iz) = (bb - 1./bb) / (bb + 1./bb) ENDDO ENDIF *** quantum yield = 1 (Calvert and Pitts, 1966) qy = 1. DO iw = 1, nw-1 if(mabs .eq. 1) sig = yg(iw) DO iz = 1, nz if (mabs .eq. 2) then ex1 = 27.3 * exp(-99.0 * alpha(iz) * (log(329.5/wc(iw)))**2) ex2 = 0.932 * exp(-91.5 * alpha(iz) * (log(406.5/wc(iw)))**2) sig = 1e-20 * alpha(iz)**0.5 * (ex1 + ex2) ENDIF sq(j,iz,iw) = qy * sig ENDDO ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r101(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for CH2(OH)CHO =* *= (glycolaldehye, hydroxy acetaldehyde) photolysis: =* *= CH2(OH)CHO + hv -> Products =* *= =* *= Cross section from =* *= The Atmospheric Chemistry of Glycolaldehyde, C. Bacher, G. S. Tyndall =* *= and J. J. Orlando, J. Atmos. Chem., 39 (2001) 171-189. =* *= =* *= Quantum yield about 50% =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=300) INTEGER i, n REAL x(kdata), y(kdata) * local REAL yg(kw) REAL qy INTEGER ierr INTEGER iw INTEGER mabs real qy1, qy2, qy3 ************************* CH2(OH)CHO photolysis * 1: CH2(OH)CHO j = j+1 jlabel(j) = 'HOCH2CHO -> CH2OH + HCO' j = j+1 jlabel(j) = 'HOCH2CHO -> CH3OH + CO' j = j+1 jlabel(j) = 'HOCH2CHO -> CH2CHO + OH' mabs = 2 IF(mabs .EQ. 1) THEN *= Cross section from =* *= The Atmospheric Chemistry of Glycolaldehyde, C. Bacher, G. S. Tyndall =* *= and J. J. Orlando, J. Atmos. Chem., 39 (2001) 171-189. =* OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH2OHCHO/glycolaldehyde.abs', $ STATUS='old') DO i = 1, 15 READ(UNIT=ilu,FMT=*) ENDDO n = 131 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,n, 0.,0.) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs .EQ. 2) THEN OPEN(NEWUNIT=ilu, $ FILE='DATAJ1/CH2OHCHO/glycolaldehyde_jpl11.abs', $ STATUS='old') DO i = 1, 2 READ(UNIT=ilu,FMT=*) ENDDO n = 63 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) y(i) = y(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,n, 0.,0.) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF * combine: qy1 = 0.83 qy2 = 0.10 qy3 = 0.07 DO iw = 1, nw - 1 DO i = 1, nz sq(j-2,i,iw) = yg(iw) * qy1 sq(j-1,i,iw) = yg(iw) * qy2 sq(j ,i,iw) = yg(iw) * qy3 ENDDO ENDDO tpflag(j-2) = 0 tpflag(j-1) = 0 tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r102(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for CH3COCOCH3 =* *= (biacetyl) photolysis: =* *= CH3COCOCH3 + hv -> Products =* *= =* *= Cross section from either =* *= 1. Plum et al., Environ. Sci. Technol., Vol. 17, No. 8, 1983, p.480 =* *= 2. Horowitz et al., J. Photochem Photobio A, 146, 19-27, 2001. =* *= =* *= Quantum yield =0.158 =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=300) INTEGER i, n REAL x(kdata), y(kdata) * local REAL yg(kw) REAL qy INTEGER ierr INTEGER iw INTEGER mabs ************************* CH3COCOCH3 photolysis * 1: CH3COCOCH3 * Cross section data bases: * mabs = 1 Plum et al. * mabs = 2 Horowitz et al. mabs = 2 j = j+1 jlabel(j) = 'CH3COCOCH3 -> Products' IF( mabs. EQ. 1) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3COCOCH3/biacetyl_plum.abs', $ STATUS='old') DO i = 1, 7 READ(UNIT=ilu,FMT=*) ENDDO n = 55 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) y(i) = y(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,n, 0.,0.) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs. EQ. 2) THEN OPEN(NEWUNIT=ilu, $ FILE='DATAJ1/CH3COCOCH3/biacetyl_horowitz.abs', $ STATUS='old') DO i = 1, 8 READ(UNIT=ilu,FMT=*) ENDDO n = 287 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) y(i) = y(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,n, 0.,0.) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF * quantum yield from Plum et al. qy = 0.158 DO iw = 1, nw - 1 DO i = 1, nz sq(j,i,iw) = yg(iw) * qy ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r103(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for CH3COCHCH2 =* *= Methyl vinyl ketone photolysis: =* *= CH3COCHCH2 + hv -> Products =* *= =* *= Cross section from =* *= W. Schneider and G. K. Moorgat, priv. comm, MPI Mainz 1989 as reported by =* *= Roeth, E.-P., R. Ruhnke, G. Moortgat, R. Meller, and W. Schneider, =* *= UV/VIS-Absorption Cross Sections and QUantum Yields for Use in =* *= Photochemistry and Atmospheric Modeling, Part 2: Organic Substances, =* *= Forschungszentrum Julich, Report Jul-3341, 1997. =* *= =* *= Quantum yield assumed unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=20000) INTEGER i, n REAL x(kdata), y(kdata) * local REAL yg(kw) REAL qy INTEGER ierr INTEGER iw INTEGER mabs ************************* CH3COCHCH2 photolysis j = j+1 jlabel(j) = 'CH3COCHCH2 -> Products' * mabs = 1: Schneider and moortgat * mabs = 2: jpl 2011 mabs = 2 IF(mabs .EQ. 1) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/MVK_schneider.abs', $ STATUS='old') DO i = 1, 9 READ(UNIT=ilu,FMT=*) ENDDO n = 19682 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,n, 0.,0.) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs .EQ. 2) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/MVK_jpl11.abs', $ STATUS='old') DO i = 1, 2 READ(UNIT=ilu,FMT=*) ENDDO n = 146 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) y(i) = y(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,n, 0.,0.) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF * quantum yield from * Gierczak, T., J. B. Burkholder, R. K. Talukdar, A. Mellouki, S. B. Barone, * and A. R. Ravishankara, Atmospheric fate of methyl vinyl ketone and methacrolein, * J. Photochem. Photobiol A: Chemistry, 110 1-10, 1997. * depends on pressure and wavelength, set upper limit to 1.0 DO iw = 1, nw - 1 DO i = 1, nz qy = exp(-0.055*(wc(iw)-308.)) / $ (5.5 + 9.2e-19*airden(i)) qy = min(qy, 1.) sq(j,i,iw) = yg(iw) * qy ENDDO ENDDO tpflag(j) = 2 RETURN END *=============================================================================* SUBROUTINE r104(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for CH2=C(CH3)CHO =* *= (methacrolein) photolysis: =* *= CH2=C(CH3)CHO + hv -> Products =* *= =* *= Cross section: from JPL 2006 (originally from Gierczak et al. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=150) INTEGER iw INTEGER i, n INTEGER n2 REAL x1(kdata), x2(kdata) REAL y1(kdata), y2(kdata) * local REAL yg(kw), yg2(kw) real qy REAL sig INTEGER ierr **************** methacrolein photodissociation j = j+1 jlabel(j) = 'CH2=C(CH3)CHO -> Products' * cross section from * JPL 2006 (originally from Gierczak et al.) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/Methacrolein_jpl11.abs', $ STATUS='OLD') DO i = 1, 7 READ(UNIT=ilu,FMT=*) ENDDO n = 146 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields assumed to be 0.01 (upper limit) qy = 0.01 DO iw = 1, nw-1 DO i = 1, nz sig = yg(iw) sq(j,i,iw) = qy * sig ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r105(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for CH3COCO(OH) =* *= pyruvic acid photolysis: =* *= CH3COCO(OH) + hv -> Products =* *= =* *= Cross section from =* *= Horowitz, A., R. Meller, and G. K. Moortgat, The UV-VIS absorption cross =* *= section of the a-dicarbonyl compounds: pyruvic acid, biacetyl, and =* *= glyoxal. J. Photochem. Photobiol. A:Chemistry, v.146, pp.19-27, 2001. =* *= =* *= Quantum yield assumed unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=20000) INTEGER i, n REAL x(kdata), y(kdata) * local REAL yg(kw) REAL qy INTEGER ierr INTEGER iw, mabs ************************* CH3COCO(OH) photolysis j = j+1 jlabel(j) = 'CH3COCO(OH) -> Products' mabs = 2 * mabs = 1: Horowitz et al. * mabs = 2: JPL2011 IF (mabs .EQ. 1) THEN OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3COCOOH/pyruvic_horowitz.abs', $ STATUS='old') DO i = 1, 8 READ(UNIT=ilu,FMT=*) ENDDO n = 148 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) y(i) = y(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,n, 0.,0.) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF (mabs .eq. 2) then OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH3COCOOH/pyruvic_jpl11.abs', $ STATUS='old') DO i = 1, 2 READ(UNIT=ilu,FMT=*) ENDDO n = 139 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) y(i) = y(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,n, 0.,0.) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF * quantum yield = 1 (sum of all channels) qy = 1. DO iw = 1, nw - 1 DO i = 1, nz sq(j,i,iw) = yg(iw) * qy ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r106(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for CH3CH2ONO2 =* *= ethyl nitrate photolysis: =* *= CH3CH2ONO2 + hv -> CH3CH2O + NO2 =* *= =* *= Absorption cross sections of several organic from =* *= Talukdar, R. K., J. B. Burkholder, M. Hunter, M. K. Gilles, =* *= J. M Roberts, and A. R. Ravishankara, Atmospheric fate of several =* *= alkyl nitrates, J. Chem. Soc., Faraday Trans., 93(16) 2797-2805, 1997. =* *= =* *= Quantum yield assumed unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=200) INTEGER i, n1, n2 REAL x1(kdata), y1(kdata) REAL x2(kdata), y2(kdata) * local REAL dum REAL yg1(kw), yg2(kw) REAL qy, sig INTEGER ierr INTEGER iw ************************* CH3CH2ONO2 photolysis j = j+1 jlabel(j) = 'CH3CH2ONO2 -> CH3CH2O + NO2' OPEN(NEWUNIT=ilu,FILE='DATAJ1/RONO2/RONO2_talukdar.abs', $ STATUS='old') DO i = 1, 10 READ(UNIT=ilu,FMT=*) ENDDO n1 = 0 n2 = 0 DO i = 1, 63 READ(UNIT=ilu,FMT=*) x1(i), dum, dum, y1(i), y2(i), dum, dum if (y1(i) .gt. 0.) n1 = n1 + 1 if (y2(i) .gt. 0.) n2 = n2 + 1 x2(i) = x1(i) y1(i) = y1(i) * 1.e-20 y2(i) = y2(i) * 1.e-3 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x2,y2,kdata,n2, 0.,y2(1)) CALL addpnt(x2,y2,kdata,n2, 1.e+38,y2(n2)) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yield = 1 qy = 1. DO iw = 1, nw - 1 DO i = 1, nz sig = yg1(iw)*exp(yg2(iw)*(tlev(i)-298.)) sq(j,i,iw) = sig * qy ENDDO ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r107(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for CH3CHONO2CH3 =* *= isopropyl nitrate photolysis: =* *= CH3CHONO2CH3 + hv -> CH3CHOCH3 + NO2 =* *= =* *= Absorption cross sections of several organic from =* *= Talukdar, R. K., J. B. Burkholder, M. Hunter, M. K. Gilles, =* *= J. M Roberts, and A. R. Ravishankara, Atmospheric fate of several =* *= alkyl nitrates, J. Chem. Soc., Faraday Trans., 93(16) 2797-2805, 1997. =* *= =* *= Quantum yield assumed unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=200) INTEGER i, n1, n2 REAL x1(kdata), y1(kdata) REAL x2(kdata), y2(kdata) * local REAL dum REAL yg1(kw), yg2(kw) REAL qy, sig INTEGER ierr INTEGER iw ************************* CH3CHONO2CH3 photolysis j = j+1 jlabel(j) = 'CH3CHONO2CH3 -> CH3CHOCH3 + NO2' OPEN(NEWUNIT=ilu,FILE='DATAJ1/RONO2/RONO2_talukdar.abs', $ STATUS='old') DO i = 1, 10 READ(UNIT=ilu,FMT=*) ENDDO n1 = 0 n2 = 0 DO i = 1, 63 READ(UNIT=ilu,FMT=*) x1(i), dum, dum, dum, dum, y1(i), y2(i) if (y1(i) .gt. 0.) n1 = n1 + 1 if (y2(i) .gt. 0.) n2 = n2 + 1 x2(i) = x1(i) y1(i) = y1(i) * 1.e-20 y2(i) = y2(i) * 1.e-3 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x2,y2,kdata,n2, 0.,y2(1)) CALL addpnt(x2,y2,kdata,n2, 1.e+38,y2(n2)) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yield = 1 qy = 1. DO iw = 1, nw - 1 DO i = 1, nz sig = yg1(iw)*exp(yg2(iw)*(tlev(i)-298.)) sq(j,i,iw) = sig * qy ENDDO ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r108(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for =* *= nitroxy ethanol CH2(OH)CH2(ONO2) + hv -> CH2(OH)CH2(O.) + NO2 =* *= =* *= Cross section from Roberts, J. R. and R. W. Fajer, UV absorption cross =* *= sections of organic nitrates of potential atmospheric importance and =* *= estimation of atmospheric lifetimes, Env. Sci. Tech., 23, 945-951, =* *= 1989. *= =* *= Quantum yield assumed unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * local REAL qy, sig INTEGER iw, i REAL a, b, c ************************* CH2(OH)CH2(ONO2) photolysis j = j+1 jlabel(j) = 'CH2(OH)CH2(ONO2) -> CH2(OH)CH2(O.) + NO2' * coefficients from Roberts and Fajer 1989, over 270-306 nm a = -2.359E-3 b = 1.2478 c = -210.4 * quantum yield = 1 qy = 1. DO iw = 1, nw - 1 IF (wc(iw) .GE. 270. .AND. wc(iw) .LE. 306.) THEN sig = EXP(a*wc(iw)*wc(iw) + b*wc(iw) + c) ELSE sig = 0. ENDIF DO i = 1, nz sq(j,i,iw) = sig * qy ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r109(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for =* *= nitroxy acetone CH3COCH2(ONO2) + hv -> CH3COCH2(O.) + NO2 =* *= =* *= Cross section from Roberts, J. R. and R. W. Fajer, UV absorption cross =* *= sections of organic nitrates of potential atmospheric importance and =* *= estimation of atmospheric lifetimes, Env. Sci. Tech., 23, 945-951, =* *= 1989. *= =* *= Quantum yield assumed unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * local REAL qy, sig INTEGER iw, i REAL a, b, c ************************* CH3COCH2(ONO2) photolysis j = j+1 jlabel(j) = 'CH3COCH2(ONO2) -> CH3COCH2(O.) + NO2' * coefficients from Roberts and Fajer 1989, over 284-335 nm a = -1.365E-3 b = 0.7834 c = -156.8 * quantum yield = 1 qy = 1. DO iw = 1, nw - 1 IF (wc(iw) .GE. 284. .AND. wc(iw) .LE. 335.) THEN sig = EXP(a*wc(iw)*wc(iw) + b*wc(iw) + c) ELSE sig = 0. ENDIF DO i = 1, nz sq(j,i,iw) = sig * qy ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r110(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for =* *= t-butyl nitrate C(CH3)3(ONO2) + hv -> C(CH3)(O.) + NO2 =* *= =* *= Cross section from Roberts, J. R. and R. W. Fajer, UV absorption cross =* *= sections of organic nitrates of potential atmospheric importance and =* *= estimation of atmospheric lifetimes, Env. Sci. Tech., 23, 945-951, =* *= 1989. *= =* *= Quantum yield assumed unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * local REAL qy, sig INTEGER iw, i REAL a, b, c ************************* C(CH3)3(ONO2) photolysis j = j+1 jlabel(j) = 'C(CH3)3(ONO2) -> C(CH3)3(O.) + NO2' * coefficients from Roberts and Fajer 1989, over 270-330 nm a = -0.993E-3 b = 0.5307 c = -115.5 * quantum yield = 1 qy = 1. DO iw = 1, nw - 1 IF (wc(iw) .GE. 270. .AND. wc(iw) .LE. 330.) THEN sig = EXP(a*wc(iw)*wc(iw) + b*wc(iw) + c) ELSE sig = 0. ENDIF DO i = 1, nz sq(j,i,iw) = sig * qy ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r111(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for ClOOCl =* *= ClO dimer photolysis: =* *= ClOOCl + hv -> Cl + ClOO =* *= =* *= Cross section from JPL2002 =* *= =* *= Quantum yield assumed unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=20000) INTEGER i, n REAL x(kdata), y(kdata) * local REAL yg(kw) REAL qy INTEGER ierr INTEGER iw ************************* ClOOCl photolysis * from JPL-2011 j = j+1 jlabel(j) = 'ClOOCl -> Cl + ClOO' OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/CLOOCL_jpl11.abs', $ STATUS='old') DO i = 1, 3 READ(UNIT=ilu,FMT=*) ENDDO n = 111 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) y(i) = y(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,n, 0.,0.) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yield = 1 qy = 1. DO iw = 1, nw - 1 DO i = 1, nz sq(j,i,iw) = yg(iw) * qy ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r112(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for hydroxyacetone =* *= CH2(OH)COCH3 photolysis: =* *= CH2(OH)COCH3 -> CH3CO + CH2OH *= -> CH2(OH)CO + CH3 =* *= =* *= Cross section from Orlando et al. (1999) =* *= =* *= Quantum yield assumed 0.325 for each channel (J. Orlando, priv.comm.2003)=* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=20000) INTEGER i, n REAL x(kdata), y(kdata) * local REAL yg(kw) REAL qy INTEGER ierr INTEGER iw, mabs ************************* CH2(OH)COCH3 photolysis * from Orlando et al. 1999 j = j+1 jlabel(j) = 'CH2(OH)COCH3 -> CH3CO + CH2(OH)' j = j+1 jlabel(j) = 'CH2(OH)COCH3 -> CH2(OH)CO + CH3' * mabs = 1: from Orlando et al. 1999 * mabs = 2: from jpl 2011 mabs = 2 if (mabs.eq.1) then OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/Hydroxyacetone.abs', $ STATUS='old') DO i = 1, 8 READ(UNIT=ilu,FMT=*) ENDDO n = 101 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,n, 0.,0.) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ELSEIF(mabs .eq. 2) then OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/Hydroxyacetone_jpl11.abs', $ STATUS='old') DO i = 1, 2 READ(UNIT=ilu,FMT=*) ENDDO n = 96 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) y(i) = y(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,n, 0.,0.) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF ENDIF * Total quantum yield = 0.65, from Orlando et al. Assume equal for each of * the two channels qy = 0.325 DO iw = 1, nw - 1 DO i = 1, nz sq(j-1,i,iw) = yg(iw) * qy sq(j,i,iw) = yg(iw) * qy ENDDO ENDDO tpflag(j-1) = 0 tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r113(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for HOBr =* *= HOBr -> OH + Br =* *= Cross section from JPL 2003 =* *= Quantum yield assumed unity as in JPL2003 =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j, i * data arrays * local REAL qy, sig INTEGER iw ************************* HOBr photolysis * from JPL2003 j = j+1 jlabel(j) = 'HOBr -> OH + Br' qy = 1. DO iw = 1, nw - 1 sig = 24.77 * EXP( -109.80*(LOG(284.01/wc(iw)))**2 ) + $ 12.22 * exp( -93.63*(LOG(350.57/wc(iw)))**2 ) + $ 2.283 * exp(- 242.40*(LOG(457.38/wc(iw)))**2 ) sig = sig * 1.e-20 IF(wc(iw) .LT. 250. .OR. wc(iw) .GT. 550.) sig = 0. DO i = 1, nz sq(j,i,iw) = sig * qy ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r114(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for BrO =* *= BrO -> Br + O =* *= Cross section from JPL 2003 =* *= Quantum yield assumed unity as in JPL2003 =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * output weighting functions INTEGER j CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * data arrays INTEGER n, i REAL x(20), y(20) * local INTEGER iw REAL qy, yg(kw), dum ************************* HOBr photolysis * from JPL2003 j = j+1 jlabel(j) = 'BrO -> Br + O' OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/BrO.jpl03', $ STATUS='old') DO i = 1, 14 READ(UNIT=ilu,FMT=*) ENDDO n = 15 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), dum, y(i) y(i) = y(i) * 1.e-20 ENDDO n = n + 1 x(n) = dum CLOSE(UNIT=ilu) * use bin-to-bin interpolation CALL inter4(nw,wl,yg,n,x,y,1) qy = 1. DO iw = 1, nw - 1 DO i = 1, nz sq(j,i,iw) = yg(iw) * qy ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r115(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for BrO =* *= Br2 -> Br + Br =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * output weighting functions INTEGER j CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * data arrays INTEGER kdata PARAMETER(kdata=50) INTEGER n, i REAL x(kdata), y(kdata) * local INTEGER iw, ierr REAL qy, yg(kw) ************************* Br2 photolysis j = j + 1 jlabel(j) = 'Br2 -> Br + Br' * Absorption cross section from: * Seery, D.J. and D. Britton, The continuous absorption spectra of chlorine, * bromine, bromine chloride, iodine chloride, and iodine bromide, J. Phys. * Chem. 68, p. 2263 (1964). OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/Br2.abs', $ STATUS='old') DO i = 1, 6 READ(UNIT=ilu,FMT=*) ENDDO n = 29 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,n, 0.,0.) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF qy = 1. DO iw = 1, nw - 1 DO i = 1, nz sq(j,i,iw) = yg(iw) * qy ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r118(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= NO3-(aq) photolysis for snow simulations =* *= a) NO3-(aq) + hv -> NO2 + O- =* *= b) NO3-(aq) + hv -> NO2- + O(3P) =* *= Cross section: =* *= Burley & Johnston, Geophys. Res. Lett., 19, 1359-1362 (1992) =* *= Quantum yield: =* *= Warneck & Wurzinger, J. Phys. Chem., 92, 6278-6283 (1988) =* *= Chu & Anastasio, J. Phys. Chem. A, 107, 9594-9602 (2003) =* *-----------------------------------------------------------------------------* *= NOTE: user may have to manually add these reactions to the end of the =* *= reaction list in file usrinp to include these reactions for a snow run: =* *= T 74 NO3-(aq) -> NO2 + O- =* *= T 75 NO3-(aq) -> NO2- + O(3P) =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw,nz REAL wl(kw), wc(kw), tlev(kz), airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=50) REAL x1(kdata),x2(kdata) REAL y1(kdata),y2(kdata) ! y1 = 20'C, y2 = -20'C * local REAL yg(kw),yg1(kw),yg2(kw), dum REAL qy1(kz), qy2, qy3 INTEGER i, iw, n, n1, n2, idum, ierr, iz integer mabs *** NO3-(aq) quantum yields * O- (OH and NO2) production j = j + 1 jlabel(j) = 'NO3-(aq) -> NO2(aq) + O-' DO iz = 1, nz * qy1(iz) = 9.3e-3 ! Warneck & Wurzinger 1988 qy1(iz) = exp(-2400./tlev(iz) + 3.6) ! Chu & Anastasio, 2003 ENDDO * O(3P) (NO2-(aq) ....> NO) production j = j + 1 jlabel(j) = 'NO3-(aq) -> NO2-(aq) + O(3P)' qy2 = 1.1e-3 ! Warneck & Wurzinger '88 * NO2- with qy=1 j = j + 1 jlabel(j) = 'NO3-(aq) with qy=1' qy3 = 1. * options for cross section mabs = 2 if (mabs .eq. 1) then *** NO3-(aq) cross sections from Burley & Johnston (header lines = 24, * data lines = 19) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/NO3-_BJ92.abs',STATUS='OLD') n = 24 DO i = 1, n READ(UNIT=ilu,FMT=*) ENDDO n = 19 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i) x2(i) = x1(i) y1(i)=y1(i)*1e-20 y2(i)=y2(i)*1e-20 ENDDO CLOSE(UNIT=ilu) n1 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1E38,0.) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF n2 = n CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1E38,0.) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF elseif (mabs .eq. 2) then *** NO3-(aq) cross sections from Chu and Anastasio 2003: * convert from molar abs log10 to cm2 per molec OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/NO3-_CA03.abs',STATUS='OLD') n = 7 do i = 1, n read(UNIT=ilu,FMT=*) enddo n = 43 DO i = 1, n read(UNIT=ilu,FMT=*) x1(i), y1(i), dum, dum, dum, dum y1(i) = y1(i) * 3.82e-21 enddo CLOSE(UNIT=ilu) n1 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1E38,0.) CALL inter2(nw,wl,yg2,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF endif DO iw = 1, nw-1 ! yg(iw)=yg1(iw) ! for 20'C yg(iw)=yg2(iw) ! for -20'C DO iz = 1, nz sq(j-2,iz,iw) = qy1(iz)*yg(iw) sq(j-1,iz,iw) = qy2*yg(iw) sq(j, iz,iw) = qy3*yg(iw) ENDDO ENDDO * chu and anastasio qy is T dependent: tpflag(j-2) = 1 tpflag(j-1) = 1 tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r119(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for =* *= methylethylketone =* *= CH3COCH2CH3 photolysis: =* *= CH3COCH2CH3 -> CH3CO + CH2CH3 =* *= =* *= Cross section from Martinez et al. (1992) =* *= =* *= Quantum yield assumed 0.325 for each channel (J. Orlando, priv.comm.2003)=* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=20000) INTEGER i, n REAL x(kdata), y(kdata) * local REAL yg(kw), dum, ptorr REAL qy INTEGER ierr INTEGER iw ************************* CH3COCH2CH3 photolysis j = j+1 jlabel(j) = 'CH3COCH2CH3 -> CH3CO + CH2CH3' OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/Martinez.abs', $ STATUS='old') DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n = 96 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), dum, y(i), dum, dum y(i) = y(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,n, 0.,0.) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * Quantum Yields from * Raber, W.H. (1992) PhD Thesis, Johannes Gutenberg-Universitaet, Mainz, Germany. * other channels assumed negligible (less than 10%). * Total quantum yield = 0.38 at 760 Torr. * Stern-Volmer form given: 1/phi = 0.96 + 2.22e-3*P(torr) * compute local pressure in torr DO i = 1, nz ptorr = 760.*airden(i)/2.69e19 qy = 1./(0.96 + 2.22E-3*ptorr) qy = MIN(qy, 1.0) DO iw = 1, nw-1 sq(j,i,iw) = yg(iw) * qy ENDDO ENDDO tpflag(j) = 2 RETURN END *=============================================================================* SUBROUTINE r120(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for PPN photolysis: =* *= PPN + hv -> Products =* *= =* *= Cross section: from JPL 2006 (originally from Harwood et al. 2003) =* *= Quantum yield: Assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) INTEGER iw INTEGER i, n INTEGER n2 REAL x1(kdata), x2(kdata) REAL y1(kdata), y2(kdata) * local REAL yg(kw), yg2(kw) real qyNO2, qyNO3 REAL sig INTEGER ierr **************** PPN photodissociation j = j+1 jlabel(j) = 'CH3CH2CO(OONO2) -> CH3CH2CO(OO) + NO2' j = j+1 jlabel(j) = 'CH3CH2CO(OONO2) -> CH3CH2CO(O) + NO3' * cross section from * JPL 2011 (originally from Harwood et al. 2003) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/PPN_Harwood.txt',STATUS='OLD') DO i = 1, 10 READ(UNIT=ilu,FMT=*) ENDDO n = 66 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i) y1(i) = y1(i) * 1.E-20 y2(i) = y2(i) * 1E-3 x2(i) = x1(i) ENDDO n2 = n CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1.e+38,0.) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields from Harwood et al., at 308 nm qyNO2 = 0.61 qyNO3 = 0.39 DO iw = 1, nw-1 DO i = 1, nz sig = yg(iw) * EXP(yg2(iw)*(tlev(i)-298.)) sq(j-1,i,iw) = qyNO2 * sig sq(j,i,iw) = qyNO3 * sig ENDDO ENDDO tpflag(j-1) = 0 tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r121(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for CH2(OH)(OOH) =* *= (hydroxy methyl hydroperoxide) photolysis: =* *= CH2(OH)(OOH) + hv -> CH2(OH)(O.) + OH =* *= =* *= Cross section: from JPL 2006 (originally from Bauerle and Moortgat 1999 =* *= Quantum yield: Assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) INTEGER iw INTEGER i, n INTEGER n2 REAL x1(kdata), x2(kdata) REAL y1(kdata), y2(kdata) * local REAL yg(kw), yg2(kw) real qy REAL sig INTEGER ierr **************** hydroxy methyl hydroperoxide photodissociation j = j+1 jlabel(j) = 'HOCH2OOH -> HOCH2O. + OH' * cross section from * JPL 2006 (originally from Bauerle and Moortgat 1999) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/HOCH2OOH.txt',STATUS='OLD') DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n = 32 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields assumed unity qy = 1. DO iw = 1, nw-1 DO i = 1, nz sig = yg(iw) sq(j,i,iw) = qy * sig ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r122(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for CH2=CHCHO =* *= (acrolein) photolysis: =* *= CH2=CHCHO + hv -> Products =* *= =* *= Cross section: from JPL 2006 (originally from Magneron et al. =* *= Quantum yield: P-dependent, JPL 2006 orig. from Gardner et al. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) INTEGER iw INTEGER i, n INTEGER n2 REAL x1(kdata), x2(kdata) REAL y1(kdata), y2(kdata) * local REAL yg(kw), yg2(kw) real qy, qym1 REAL sig INTEGER ierr **************** acrolein photodissociation j = j+1 jlabel(j) = 'CH2=CHCHO -> Products' * cross section from * JPL 2006 (originally from Magneron et al.) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/Acrolein.txt',STATUS='OLD') DO i = 1, 6 READ(UNIT=ilu,FMT=*) ENDDO n = 55 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields are pressure dependent between air number densities * of 8e17 and 2.6e19, Gardner et al.: DO iw = 1, nw-1 DO i = 1, nz if(airden(i) .gt. 2.6e19) then qy = 0.004 elseif(airden(i) .gt. 8.e17 .and. airden(i) .lt. 2.6e19) then qym1 = 0.086 + 1.613e-17 * airden(i) qy = 0.004 + 1./qym1 elseif(airden(i) .lt. 8.e17) then qym1 = 0.086 + 1.613e-17 * 8.e17 qy = 0.004 + 1./qym1 endif sig = yg(iw) sq(j,i,iw) = qy * sig ENDDO ENDDO tpflag(j) = 2 RETURN END *=============================================================================* SUBROUTINE r123(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for peracetic acid =* *= photolysis: =* *= CH3CO(OOH) + hv -> Products =* *= =* *= Cross section: from JPL 2006 (originally from Orlando and Tyndall 2003 =* *= Quantum yield: Assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) INTEGER iw INTEGER i, n INTEGER n2 REAL x1(kdata), x2(kdata) REAL y1(kdata), y2(kdata) * local REAL yg(kw), yg2(kw) real qy REAL sig INTEGER ierr **************** peracetic acid photodissociation j = j+1 jlabel(j) = 'CH3CO(OOH) -> Products' * cross section from * JPL 2006 (originally from Orlando and Tyndall 2003) OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/Peracetic_acid.txt', & STATUS='OLD') DO i = 1, 6 READ(UNIT=ilu,FMT=*) ENDDO n = 66 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields assumed unity qy = 1. DO iw = 1, nw-1 DO i = 1, nz sig = yg(iw) sq(j,i,iw) = qy * sig ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r124(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for dimethyl nitroso =* *= amine photolysis: =* *= (CH3)2NNO + hv -> Products =* *= =* *= Cross section: from Lindley 1978 (cited by Calvert et al. 2009) *= Quantum yield: Assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=150) INTEGER iw INTEGER i, n REAL x1(kdata) REAL y1(kdata) INTEGER ierr * local REAL yg(kw) REAL qy **************** dmna photodissociation j = j+1 jlabel(j) = '(CH3)2NNO -> Products' * cross section from * Lindley (1978, PhD Thesis Ohio State U., Jack Calvert advisor), cited by Calvert et al. (2009). OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/dmna.abs',STATUS='OLD') DO i = 1, 5 READ(UNIT=ilu,FMT=*) ENDDO n = 132 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.E-19 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields assumed unity qy = 1. DO iw = 1, nw-1 DO i = 1, nz sq(j,i,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r125(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for ClO photolysis =* *= ClO + hv -> Cl + O =* *= =* *= Cross section: from Maric and Burrows 1999 =* *= Quantum yield: Assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=500) INTEGER iw INTEGER i, n REAL x1(kdata) REAL y1(kdata) INTEGER ierr * local REAL yg(kw) REAL qy1, qy2 real tmp(12), x(kdata), y(kdata,12), tx real xdum integer m, nn, ii real ygt(kw, 12), yy INTEGER m1, m2 **************** ClO photodissociation j = j+1 jlabel(j) = 'ClO -> Cl + O(1D)' j = j+1 jlabel(j) = 'ClO -> Cl + O(3P)' * cross section from * Maric D. and J.P. Burrows, J. Quantitative Spectroscopy and * Radiative Transfer 62, 345-369, 1999. Data was downloaded from * their web site on 15 Septmeber 2009. OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/ClO_spectrum.prn',STATUS='OLD') DO i = 1, 2 READ(UNIT=ilu,FMT=*) ENDDO nn = 453 DO ii = 1, nn i = nn - ii + 1 READ(UNIT=ilu,FMT=*) xdum, x(i), xdum, (y(i,m), m = 1, 12) ENDDO CLOSE(UNIT=ilu) DO m = 1, 12 tmp(m) = 190. + 10.*FLOAT(m-1) IF(m .EQ. 1) tmp(m) = 180. DO i = 1, nn x1(i) = x(i) y1(i) = y(i,m) ENDDO n = nn CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF DO iw = 1, nw-1 ygt(iw,m) = yg(iw) ENDDO ENDDO DO i = 1, nz tx = tlev(i) * locate temperature indices for interpolation: m1 = 1 + INT((tx - 190.)/10.) m1 = MAX(1 ,m1) m1 = MIN(11,m1) m2 = m1 + 1 DO iw = 1, nw-1 yy = ygt(iw,m1) + (ygt(iw,m2)-ygt(iw,m1)) $ *(tx-tmp(m1))/(tmp(m2)-tmp(m1)) * threshold for O(1D) productionis 263.4 nm: if(wc(iw) .lt. 263.4) then qy1 = 1. else qy1 = 0. endif qy2 = 1. - qy1 sq(j-1,i,iw) = qy1 * yy sq(j,i,iw) = qy2 * yy ENDDO ENDDO tpflag(j-1) = 1 tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r126(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for nitryl chloride =* *= ClNO2 -> Cl + NO2 =* *= =* *= Cross section: from JPL 2006 =* *= Quantum yield: Assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=150) INTEGER iw INTEGER i, n REAL x1(kdata) REAL y1(kdata) INTEGER ierr * local REAL yg(kw) REAL qy integer mabs **************** ClNO2 photodissociation j = j+1 jlabel(j) = 'ClNO2 -> Cl + NO2' * cross section from * mabs = 1: JPL 2006, same as JPL-2011 * mabs = 2: IUPAC 2007 mabs = 1 if(mabs.eq.1) then OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/ClNO2.abs',STATUS='OLD') DO i = 1, 2 READ(UNIT=ilu,FMT=*) ENDDO n = 26 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF elseif (mabs .eq. 2) then OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/ClNO2_iupac.abs', & STATUS='OLD') DO i = 1, 6 READ(UNIT=ilu,FMT=*) ENDDO n = 17 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF endif * quantum yields assumed unity qy = 1. DO iw = 1, nw-1 DO i = 1, nz sq(j,i,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r127(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for nitrosyl bromide =* *= BrNO -> Br + NO =* *= =* *= Cross section: from JPL 2006 =* *= Quantum yield: Assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=150) INTEGER iw INTEGER i, n REAL x1(kdata) REAL y1(kdata) INTEGER ierr * local REAL yg(kw) REAL qy ******************** BrNO photodissociation j = j+1 jlabel(j) = 'BrNO -> Br + NO' * cross section from * JPL 2006 OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/BrNO.abs',STATUS='OLD') DO i = 1, 3 READ(UNIT=ilu,FMT=*) ENDDO n = 27 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields assumed unity qy = 1. DO iw = 1, nw-1 DO i = 1, nz sq(j,i,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r128(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for bromine nitritee =* *= BrNO2 -> Br + NO2 =* *= =* *= Cross section: from JPL 2006 =* *= Quantum yield: Assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=150) INTEGER iw INTEGER i, n REAL x1(kdata) REAL y1(kdata) INTEGER ierr * local REAL yg(kw) REAL qy ******************** BrNO2 photodissociation j = j+1 jlabel(j) = 'BrNO2 -> Br + NO2' * cross section from * IUPAC (vol III) 2007 OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/BrNO2.abs',STATUS='OLD') DO i = 1, 6 READ(UNIT=ilu,FMT=*) ENDDO n = 54 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields assumed unity qy = 1. DO iw = 1, nw-1 DO i = 1, nz sq(j,i,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r129(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for bromine nitrite =* *= BrONO -> Br + NO2 =* *= BrONO -> BrO + NO =* *= =* *= Cross section: from IUPAC (vol.3) =* *= Quantum yield: Assumed to be 0.5 for each channel =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE C INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=150) INTEGER iw INTEGER i, n REAL x1(kdata) REAL y1(kdata) INTEGER ierr * local REAL yg(kw) REAL qy1, qy2 ******************** BrONO photodissociation j = j+1 jlabel(j) = 'BrONO -> Br + NO2' j = j+1 jlabel(j) = 'BrONO -> BrO + NO' * cross section from * IUPAC (vol III) 2007 OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/BrONO.abs',STATUS='OLD') DO i = 1, 8 READ(UNIT=ilu,FMT=*) ENDDO n = 32 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields assumed unity qy1 = 0.5 qy2 = 0.5 DO iw = 1, nw-1 DO i = 1, nz sq(j-1,i,iw) = qy1 * yg(iw) sq(j,i,iw) = qy2 * yg(iw) ENDDO ENDDO tpflag(j-1) = 0 tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r130(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for *= HOCl -> HO + Cl =* *= Cross section: from IUPAC (vol.3) =* *= Quantum yield: Assumed to be 1 =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=150) INTEGER iw INTEGER i, n REAL x1(kdata) REAL y1(kdata) INTEGER ierr * local REAL yg(kw) REAL qy ******************** HOCl photodissociation j = j + 1 jlabel(j) = 'HOCl -> HO + Cl' * cross section from * IUPAC (vol III) 2007 OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/HOCl.abs',STATUS='OLD') DO i = 1, 7 READ(UNIT=ilu,FMT=*) ENDDO n = 111 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields assumed unity qy = 1 DO iw = 1, nw-1 DO i = 1, nz sq(j,i,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r131(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for *= NOCl -> NO + Cl =* *= Cross section: from IUPAC (vol.3) =* *= Quantum yield: Assumed to be 1 =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=150) INTEGER iw INTEGER i, n, ii REAL x1(kdata), y1(kdata) integer nn REAL x223(kdata),x243(kdata),x263(kdata),x298(kdata), $ x323(kdata), x343(kdata) REAL y223(kdata),y243(kdata),y263(kdata),y298(kdata), $ y323(kdata), y343(kdata) INTEGER ierr * local REAL yg223(kw),yg243(kw),yg263(kw),yg298(kw), $ yg323(kw), yg343(kw) REAL qy, sig ******************** NOCl photodissociation j = j + 1 jlabel(j) = 'NOCl -> NO + Cl' * cross section from * IUPAC (vol III) 2007 OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/NOCl.abs',STATUS='OLD') DO i = 1, 7 READ(UNIT=ilu,FMT=*) ENDDO n = 80 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y223(i) = y1(i) y243(i) = y1(i) y263(i) = y1(i) y298(i) = y1(i) y323(i) = y1(i) y343(i) = y1(i) x223(i) = x1(i) x243(i) = x1(i) x263(i) = x1(i) x298(i) = x1(i) x323(i) = x1(i) x343(i) = x1(i) ENDDO READ(UNIT=ilu,FMT=*) n = 61 do i = 1, n ii = i + 80 read(UNIT=ilu,FMT=*) x1(ii), y223(ii), y243(ii), y263(ii), $ y298(ii), y323(ii), y343(ii) x223(ii) = x1(ii) x243(ii) = x1(ii) x263(ii) = x1(ii) x298(ii) = x1(ii) x323(ii) = x1(ii) x343(ii) = x1(ii) enddo n = ii CLOSE(UNIT=ilu) nn = n CALL addpnt(x223,y223,kdata,nn,x223(1)*(1.-deltax),0.) CALL addpnt(x223,y223,kdata,nn, 0.,0.) CALL addpnt(x223,y223,kdata,nn,x223(nn)*(1.+deltax),0.) CALL addpnt(x223,y223,kdata,nn, 1.e+38,0.) CALL inter2(nw,wl,yg223,nn,x223,y223,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF nn = n CALL addpnt(x243,y243,kdata,nn,x243(1)*(1.-deltax),0.) CALL addpnt(x243,y243,kdata,nn, 0.,0.) CALL addpnt(x243,y243,kdata,nn,x243(nn)*(1.+deltax),0.) CALL addpnt(x243,y243,kdata,nn, 1.e+38,0.) CALL inter2(nw,wl,yg243,nn,x243,y243,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF nn = n CALL addpnt(x263,y263,kdata,nn,x263(1)*(1.-deltax),0.) CALL addpnt(x263,y263,kdata,nn, 0.,0.) CALL addpnt(x263,y263,kdata,nn,x263(nn)*(1.+deltax),0.) CALL addpnt(x263,y263,kdata,nn, 1.e+38,0.) CALL inter2(nw,wl,yg263,nn,x263,y263,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF nn = n CALL addpnt(x298,y298,kdata,nn,x298(1)*(1.-deltax),0.) CALL addpnt(x298,y298,kdata,nn, 0.,0.) CALL addpnt(x298,y298,kdata,nn,x298(nn)*(1.+deltax),0.) CALL addpnt(x298,y298,kdata,nn, 1.e+38,0.) CALL inter2(nw,wl,yg298,nn,x298,y298,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF nn = n CALL addpnt(x323,y323,kdata,nn,x323(1)*(1.-deltax),0.) CALL addpnt(x323,y323,kdata,nn, 0.,0.) CALL addpnt(x323,y323,kdata,nn,x323(nn)*(1.+deltax),0.) CALL addpnt(x323,y323,kdata,nn, 1.e+38,0.) CALL inter2(nw,wl,yg323,nn,x323,y323,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF nn = n CALL addpnt(x343,y343,kdata,nn,x343(1)*(1.-deltax),0.) CALL addpnt(x343,y343,kdata,nn, 0.,0.) CALL addpnt(x343,y343,kdata,nn,x343(nn)*(1.+deltax),0.) CALL addpnt(x343,y343,kdata,nn, 1.e+38,0.) CALL inter2(nw,wl,yg343,nn,x343,y343,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields assumed unity qy = 1 sig = 0. DO iw = 1, nw-1 DO i = 1, nz if(tlev(i) .le. 223.) then sig = yg223(iw) elseif (tlev(i) .gt. 223. .and. tlev(i) .le. 243.) then sig = yg223(iw) + $ (yg243(iw) - yg223(iw))*(tlev(i) - 223.)/20. elseif (tlev(i) .gt. 243. .and. tlev(i) .le. 263.) then sig = yg243(iw) + $ (yg263(iw) - yg243(iw))*(tlev(i) - 243.)/20. elseif (tlev(i) .gt. 263. .and. tlev(i) .le. 298.) then sig = yg263(iw) + $ (yg298(iw) - yg263(iw))*(tlev(i) - 263.)/35. elseif (tlev(i) .gt. 298. .and. tlev(i) .le. 323.) then sig = yg298(iw) + $ (yg323(iw) - yg298(iw))*(tlev(i) - 298.)/25. elseif (tlev(i) .gt. 323. .and. tlev(i) .le. 343.) then sig = yg323(iw) + $ (yg343(iw) - yg323(iw))*(tlev(i) - 323.)/20. endif sq(j,i,iw) = qy * sig ENDDO ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r132(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for *= OClO -> Products =* *= Cross section: from Wahner et al., J. Phys. Chem. 91, 2734, 1987 =* *= Quantum yield: Assumed to be 1 =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=2000) INTEGER iw INTEGER i, n REAL x1(kdata), y1(kdata) integer nn, n204, n296, n378 REAL x204(kdata),x296(kdata),x378(kdata) REAL y204(kdata),y296(kdata),y378(kdata) INTEGER ierr * local REAL yg204(kw),yg296(kw),yg378(kw) REAL qy, sig ******************** NOCl photodissociation j = j + 1 jlabel(j) = 'OClO -> Products' * cross section from *A. Wahner, G.S. tyndall, A.R. Ravishankara, J. Phys. Chem., 91, 2734, (1987). *Supplementary Data, as quoted at: *http://www.atmosphere.mpg.de/enid/26b4b5172008b02407b2e47f08de2fa1,0/Spectra/Introduction_1rr.html OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/OClO.abs',STATUS='OLD') DO i = 1, 6 READ(UNIT=ilu,FMT=*) ENDDO n204 = 1074-6 DO i = 1, n204 READ(UNIT=ilu,FMT=*) x204(i), y204(i) ENDDO READ(UNIT=ilu,FMT=*) n296 = 1067 do i = 1, n296 read(UNIT=ilu,FMT=*) x296(i), y296(i) enddo read(UNIT=ilu,FMT=*) n378 = 1068 do i = 1, n378 read(UNIT=ilu,FMT=*) x378(i), y378(i) enddo CLOSE(UNIT=ilu) nn = n204 CALL addpnt(x204,y204,kdata,nn,x204(1)*(1.-deltax),0.) CALL addpnt(x204,y204,kdata,nn, 0.,0.) CALL addpnt(x204,y204,kdata,nn,x204(nn)*(1.+deltax),0.) CALL addpnt(x204,y204,kdata,nn, 1.e+38,0.) CALL inter2(nw,wl,yg204,nn,x204,y204,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF nn = n296 CALL addpnt(x296,y296,kdata,nn,x296(1)*(1.-deltax),0.) CALL addpnt(x296,y296,kdata,nn, 0.,0.) CALL addpnt(x296,y296,kdata,nn,x296(nn)*(1.+deltax),0.) CALL addpnt(x296,y296,kdata,nn, 1.e+38,0.) CALL inter2(nw,wl,yg296,nn,x296,y296,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF nn = n378 CALL addpnt(x378,y378,kdata,nn,x378(1)*(1.-deltax),0.) CALL addpnt(x378,y378,kdata,nn, 0.,0.) CALL addpnt(x378,y378,kdata,nn,x378(nn)*(1.+deltax),0.) CALL addpnt(x378,y378,kdata,nn, 1.e+38,0.) CALL inter2(nw,wl,yg378,nn,x378,y378,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields assumed unity qy = 1 DO iw = 1, nw-1 DO i = 1, nz if(tlev(i) .le. 204.) then sig = yg204(iw) elseif (tlev(i) .gt. 204. .and. tlev(i) .le. 296.) then sig = yg204(iw) + $ (yg296(iw) - yg204(iw))*(tlev(i) - 204.)/92. elseif (tlev(i) .gt. 296. .and. tlev(i) .le. 378.) then sig = yg296(iw) + $ (yg378(iw) - yg296(iw))*(tlev(i) - 296.)/82. elseif (tlev(i) .gt. 378.) then sig = yg378(iw) endif sq(j,i,iw) = qy * sig ENDDO ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r133(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for =* *= BrCl -> Br + Cl =* *= Cross section: from Maric et al., J. Phtoochem Photobiol. A: Chem =* *= 83, 179-192, 1994. =* *= Quantum yield: Assumed to be 1 =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=200) INTEGER iw INTEGER i, n REAL x(kdata), y(kdata) integer nn INTEGER ierr * local REAL yg(kw) REAL qy ******************** BrCl photodissociation j = j + 1 jlabel(j) = 'BrCl -> Br + Cl' * cross section from * D. Maric, J.P. Burrows, and G.K. Moortgat, "A study of the UV-visible * absorption spectra of Br2 and BrCl," J. Photochem. Photobiol. A: Chem. * 83, 179-192 (1994). OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/BrCl.abs',STATUS='OLD') DO i = 1, 9 READ(UNIT=ilu,FMT=*) ENDDO n = 81 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) ENDDO CLOSE(UNIT=ilu) nn = n CALL addpnt(x,y,kdata,nn,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,nn, 0.,0.) CALL addpnt(x,y,kdata,nn,x(nn)*(1.+deltax),0.) CALL addpnt(x,y,kdata,nn, 1.e+38,0.) CALL inter2(nw,wl,yg,nn,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields assumed unity qy = 1. DO iw = 1, nw-1 DO i = 1, nz sq(j,i,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r134(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for =* *= CH3(OONO2) -> CH3(OO) + NO2 =* *= Cross section: from *= I. Bridier, R. Lesclaux, and B. Veyret, "Flash photolysis kinetic study *= of the equilibrium CH3O2 + NO2 « CH3O2NO2," Chemical Physics Letters *= 191, 259-263 (1992). *= Quantum yield: Assumed to be 1 =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=200) INTEGER iw INTEGER i, n REAL x(kdata), y(kdata) integer nn INTEGER ierr * local REAL yg(kw) REAL qy ******************** CH3(OONO2) photodissociation j = j + 1 jlabel(j) = 'CH3(OONO2) -> CH3(OO) + NO2' * cross section from *= I. Bridier, R. Lesclaux, and B. Veyret, "Flash photolysis kinetic study *= of the equilibrium CH3O2 + NO2 « CH3O2NO2," Chemical Physics Letters *= 191, 259-263 (1992). OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/CH3OONO2.abs',STATUS='OLD') DO i = 1, 9 READ(UNIT=ilu,FMT=*) ENDDO n = 26 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) ENDDO CLOSE(UNIT=ilu) nn = n CALL addpnt(x,y,kdata,nn,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,nn, 0.,0.) CALL addpnt(x,y,kdata,nn,x(nn)*(1.+deltax),0.) CALL addpnt(x,y,kdata,nn, 1.e+38,0.) CALL inter2(nw,wl,yg,nn,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields assumed unity qy = 1. DO iw = 1, nw-1 DO i = 1, nz sq(j,i,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r135(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for t-butyl nitrite =* *= C(CH3)3(ONO) -> C(CH3)3(O) + NO =* *= Cross section: from *= V. McMillan, 1966, private communication to J.G. Calvert, J.N.Pitts, Jr., *= Photochemistry, London, 1966, p. 455. *= Quantum yield: Assumed to be 1 =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=200) INTEGER iw INTEGER i, n REAL x(kdata), y(kdata) integer nn INTEGER ierr * local REAL yg(kw) REAL qy ******************** CH3(OONO2) photodissociation j = j + 1 jlabel(j) = 'C(CH3)3(ONO) -> C(CH3)3(O) + NO' * cross section from *= V. McMillan, 1966, private communication to J.G. Calvert, J.N.Pitts, Jr., *= Photochemistry, London, 1966, p. 455. OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/t-butyl-nitrite.abs', & STATUS='OLD') DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n = 96 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) ENDDO CLOSE(UNIT=ilu) nn = n CALL addpnt(x,y,kdata,nn,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,nn, 0.,0.) CALL addpnt(x,y,kdata,nn,x(nn)*(1.+deltax),0.) CALL addpnt(x,y,kdata,nn, 1.e+38,0.) CALL inter2(nw,wl,yg,nn,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields assumed unity qy = 1. DO iw = 1, nw-1 DO i = 1, nz sq(j,i,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r136(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for ClONO =* *= ClONO -> Cl + NO2 =* *= cross section from IPUAC, orig from Molina and Molina (1977) =* *= Quantum yield: Assumed to be 1 =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=200) INTEGER iw INTEGER i, n REAL x(kdata), y(kdata) integer nn INTEGER ierr * local REAL yg(kw) REAL qy ******************** ClONO photodissociation j = j + 1 jlabel(j) = 'ClONO -> Cl + NO2' * cross section from JPL-2011 * Also published (with some minor differences) as: * R. Atkinson, D.L. Baulch, R.A. Cox, J.N. Crowley, R.F. Hampson, R.G. Hynes, M.E. Jenkin, M.J. Rossi, * and J. Troe, "Evaluated kinetic and photochemical data for atmospheric chemistry: Volume III - gas * phase reactions of inorganic halogens", Atmos. Chem. Phys. 7, 981-1191 (2007).Comments: * IUPAC (2005, 2007) recommendation: * The preferred values of the absorption cross-sections at 231 K are the values reported by * L.T. Molina and M.J. Molina, "Ultraviolet absorption spectrum of chlorine nitrite, ClONO," * Geophys. Res. Lett. 4, 83-86 (1977). OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/ClONO_jpl11.abs',STATUS='OLD') DO i = 1, 3 READ(UNIT=ilu,FMT=*) ENDDO n = 34 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) ENDDO CLOSE(UNIT=ilu) nn = n CALL addpnt(x,y,kdata,nn,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,nn, 0.,0.) CALL addpnt(x,y,kdata,nn,x(nn)*(1.+deltax),0.) CALL addpnt(x,y,kdata,nn, 1.e+38,0.) CALL inter2(nw,wl,yg,nn,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields assumed unity qy = 1. DO iw = 1, nw-1 DO i = 1, nz sq(j,i,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r137(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for HCl =* *= HCl -> H + Cl =* *= cross section from JPL2011 =* *= Quantum yield: Assumed to be 1 =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) INTEGER iw INTEGER i, n REAL x(kdata), y(kdata) integer nn INTEGER ierr * local REAL yg(kw) REAL qy, dum ******************** HCl photodissociation j = j + 1 jlabel(j) = 'HCl -> H + Cl' * cross section from JPL2011 OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/HCl_jpl11.abs',STATUS='OLD') DO i = 1, 3 READ(UNIT=ilu,FMT=*) ENDDO n = 31 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i), dum y(i) = y(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) nn = n CALL addpnt(x,y,kdata,nn,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,nn, 0.,0.) CALL addpnt(x,y,kdata,nn,x(nn)*(1.+deltax),0.) CALL addpnt(x,y,kdata,nn, 1.e+38,0.) CALL inter2(nw,wl,yg,nn,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields assumed unity qy = 1. DO iw = 1, nw-1 DO i = 1, nz sq(j,i,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *-----------------------------------------------------------------------------* SUBROUTINE pxCH2O(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= JPL 2011 recommendation. =* *= Provide product of (cross section) x (quantum yield) for CH2O photolysis =* *= (a) CH2O + hv -> H + HCO =* *= (b) CH2O + hv -> H2 + CO =* *= written by s. madronich march 2013 *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) INTEGER kdata PARAMETER(kdata=200) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER i, j, iz, iw * data arrays INTEGER n, n1, n2 REAL x1(kdata), x2(kdata) REAL y298(kdata), tcoef(kdata) REAL qr(kdata), qm(kdata) * local REAL yg1(kw), yg2(kw), yg3(kw), yg4(kw) REAL ak300, akt, sig real qyr300, qym300, qymt INTEGER ierr *_______________________________________________________________________ DO 5, iw = 1, nw - 1 wc(iw) = (wl(iw) + wl(iw+1))/2. 5 CONTINUE **************************************************************** **************** CH2O photodissociatation j = j+1 jlabel(j) = 'CH2O -> H + HCO' j = j+1 jlabel(j) = 'CH2O -> H2 + CO' * read JPL2011 cross section data: OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH2O/CH2O_jpl11.abs' $ ,STATUS='old') do i = 1, 4 read(UNIT=ilu,FMT=*) enddo n = 150 n1 = n n2 = n DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y298(i), tcoef(i) x2(i) = x1(i) y298(i) = y298(i) * 1.e-20 tcoef(i) = tcoef(i) * 1.e-24 ENDDO CLOSE(UNIT=ilu) * terminate endpoints and interpolate to working grid CALL addpnt(x1,y298,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y298,kdata,n1, 0.,0.) CALL addpnt(x1,y298,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y298,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg1,n1,x1,y298,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j-1) STOP ENDIF CALL addpnt(x2,tcoef,kdata,n2,x2(1)*(1.-deltax),0.) CALL addpnt(x2,tcoef,kdata,n2, 0.,0.) CALL addpnt(x2,tcoef,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,tcoef,kdata,n2, 1.e+38,0.) CALL inter2(nw,wl,yg2,n2,x2,tcoef,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j-1) STOP ENDIF * quantum yields: Read, terminate, interpolate: OPEN(NEWUNIT=ilu,FILE='DATAJ1/CH2O/CH2O_jpl11.yld',STATUS='old') DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n = 112 n1 = n n2 = n DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), qr(i), qm(i) x2(i) = x1(i) ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,qr,kdata,n1,x1(1)*(1.-deltax),qr(1)) CALL addpnt(x1,qr,kdata,n1, 0.,qr(1)) CALL addpnt(x1,qr,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,qr,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg3,n1,x1,qr,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j-1) STOP ENDIF CALL addpnt(x2,qm,kdata,n2,x2(1)*(1.-deltax),qm(1)) CALL addpnt(x2,qm,kdata,n2, 0.,qm(1)) CALL addpnt(x2,qm,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,qm,kdata,n2, 1.e+38,0.) CALL inter2(nw,wl,yg4,n2,x2,qm,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j-1) STOP ENDIF * combine gridded quantities: * yg1 = cross section at 298K * yg2 = temperature correction coefficient for cross section * yg3 = quantum yields for radical channel, H + HCO * yg4 = quantum yields for molecular channel, H2 + CO. DO iz = 1, nz DO iw = 1, nw - 1 * correct cross section for temperature dependence: sig = yg1(iw) + yg2(iw) * (tlev(iz) - 298.) * assign room temperature quantum yields for radical and molecular channels qyr300 = yg3(iw) qym300 = yg4(iw) qymt = qym300 * between 330 ande 360 nm, molecular channel is pressure and temperature dependent. IF (wc(iw) .ge. 330. .and. wc(iw) .lt. 360. .and. $ qym300 .gt. 0.) then ak300 = 1./qym300 - 1./(1. - qyr300) ak300 = ak300/2.45e19 akt = ak300 * (1. + 0.05 * (wc(iw) - 329.) * $ (300. - tlev(iz))/80.) qymt = 1./(1./(1.-qyr300) + akt*airden(iz)) ENDIF sq(j-1,iz,iw) = sig * qyr300 sq(j ,iz,iw) = sig * qymt ENDDO ENDDO tpflag(j-1) = 1 tpflag(j) = 3 RETURN END *=============================================================================* SUBROUTINE r138(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for acetic acid =* *= CH3COOH -> CH3 + COOH =* *= cross section from JPL2011 =* *= Quantum yield: Assumed to be 0.55 =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) INTEGER iw INTEGER i, n REAL x(kdata), y(kdata) integer nn INTEGER ierr * local REAL yg(kw) REAL qy, dum ******************** acetic acid photodissociation j = j + 1 jlabel(j) = 'CH3COOH -> CH3 + COOH' * cross section from JPL2011 OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/CH3COOH_jpl11.abs',STATUS='OLD') DO i = 1, 2 READ(UNIT=ilu,FMT=*) ENDDO n = 18 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) y(i) = y(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) nn = n CALL addpnt(x,y,kdata,nn,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,nn, 0.,0.) CALL addpnt(x,y,kdata,nn,x(nn)*(1.+deltax),0.) CALL addpnt(x,y,kdata,nn, 1.e+38,0.) CALL inter2(nw,wl,yg,nn,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields assumed unity qy = 0.55 DO iw = 1, nw-1 DO i = 1, nz sq(j,i,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r139(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x(quantum yield) for methyl hypochlorite =* *= CH3OCl -> CH3O + Cl =* *= cross section from JPL2011 =* *= Quantum yield: Assumed to be 1 =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) INTEGER iw INTEGER i, n REAL x(kdata), y(kdata) integer nn INTEGER ierr * local REAL yg(kw) REAL qy, dum ******************** methyl hypochlorite photodissociation j = j + 1 jlabel(j) = 'CH3OCl -> CH3O + Cl' * cross section from JPL2011 OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/CH3OCl_jpl11.abs',STATUS='OLD') DO i = 1, 3 READ(UNIT=ilu,FMT=*) ENDDO n = 83 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) y(i) = y(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) nn = n CALL addpnt(x,y,kdata,nn,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,nn, 0.,0.) CALL addpnt(x,y,kdata,nn,x(nn)*(1.+deltax),0.) CALL addpnt(x,y,kdata,nn, 1.e+38,0.) CALL inter2(nw,wl,yg,nn,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields assumed unity qy = 1. DO iw = 1, nw-1 DO i = 1, nz sq(j,i,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r140(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for CHCl3 photolysis: =* *= CHCL3 + hv -> Products =* *= Cross section: from JPL 2011 recommendation =* *= Quantum yield: assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) REAL x1(kdata) REAL y1(kdata) * local REAL yg(kw) REAL qy INTEGER i, iw, n, idum INTEGER ierr INTEGER iz INTEGER mabs REAL b0, b1, b2, b3, b4, tcoeff, sig REAL w1, w2, w3, w4, temp ************************************************************** ************* CHCl3 photodissociation j = j+1 jlabel(j) = 'CHCl3 -> Products' OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/CHCl3_jpl11.abs',STATUS='OLD') DO i = 1, 3 READ(UNIT=ilu,FMT=*) ENDDO n = 39 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1E-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1E38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * compute temperature correction factors: b0 = 3.7973 b1 = -7.0913e-2 b2 = 4.9397e-4 b3 = -1.5226e-6 b4 = 1.7555e-9 *** quantum yield assumed to be unity qy = 1. DO iw = 1, nw-1 * compute temperature correction coefficients: tcoeff = 0. IF(wc(iw) .GT. 190. .AND. wc(iw) .LT. 240.) THEN w1 = wc(iw) w2 = w1**2 w3 = w1**3 w4 = w1**4 tcoeff = b0 + b1*w1 + b2*w2 + b3*w3 + b4*w4 ENDIF DO iz = 1, nz temp = tlev(iz) temp = min(max(temp,210.),300.) sig = yg(iw) * 10.**(tcoeff*(temp-295.)) sq(j,iz,iw) = qy * sig ENDDO ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r141(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for C2H5ONO2 =* *= photolysis: =* *= C2H5ONO2 + hv -> C2H5O + NO2 =* *= =* *= Cross section: IUPAC 2006 (Atkinson et al., ACP, 6, 3625-4055, 2006) =* *= Quantum yield: Assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER (kdata = 200) INTEGER i, n INTEGER iw INTEGER n1, n2 REAL x1(kdata), x2(kdata) REAL y1(kdata), y2(kdata) * local REAL yg(kw), yg1(kw), yg2(kw) REAL qy REAL sig INTEGER ierr INTEGER mabs, myld **************** C2H5ONO2 photodissociation j = j + 1 jlabel(j) = 'C2H5ONO2 -> C2H5O + NO2' * mabs: absorption cross section options: * 1: IUPAC 2006 OPEN(NEWUNIT=ilu,FILE='DATAJ1/RONO2/C2H5ONO2_iup2006.abs', $ STATUS='old') DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n = 32 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i), y2(i) x2(i) = x1(i) y1(i) = y1(i) * 1.e-20 y2(i) = y2(i) * 1.e-3 ENDDO CLOSE (UNIT=ilu) n1 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF n2 = n CALL addpnt(x2,y2,kdata,n2,x2(1)*(1.-deltax),0.) CALL addpnt(x2,y2,kdata,n2, 0.,0.) CALL addpnt(x2,y2,kdata,n2,x2(n2)*(1.+deltax),0.) CALL addpnt(x2,y2,kdata,n2, 1.e+38,0.) CALL inter2(nw,wl,yg2,n2,x2,y2,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yield = 1 * sigma(T,lambda) = sigma(298,lambda) * exp(B * (T-298)) qy = 1. DO iw = 1, nw - 1 DO i = 1, nz sig = yg1(iw) * exp(yg2(iw) * (tlev(i)-298.)) sq(j,i,iw) = qy * sig ENDDO ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r142(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for n-C3H7ONO2 =* *= photolysis: =* *= n-C3H7ONO2 + hv -> C3H7O + NO2 =* *= =* *= Cross section: IUPAC 2006 (Atkinson et al., ACP, 6, 3625-4055, 2006) =* *= Quantum yield: Assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER (kdata = 200) INTEGER i, n INTEGER iw INTEGER n1, n2 REAL x1(kdata), x2(kdata) REAL y1(kdata), y2(kdata) * local REAL yg(kw), yg1(kw), yg2(kw) REAL qy REAL sig INTEGER ierr INTEGER mabs, myld **************** n-C3H7ONO2 photodissociation j = j + 1 jlabel(j) = 'n-C3H7ONO2 -> C3H7O + NO2' * 1: IUPAC 2006 OPEN(NEWUNIT=ilu,FILE='DATAJ1/RONO2/nC3H7ONO2_iup2006.abs', $ STATUS='old') DO i = 1, 3 READ(UNIT=ilu,FMT=*) ENDDO n = 32 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.e-20 ENDDO CLOSE (UNIT=ilu) n1 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yield = 1 qy = 1. DO iw = 1, nw - 1 DO i = 1, nz sq(j,i,iw) = qy * yg1(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r143(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for 1-C4H9ONO2 =* *= photolysis: =* *= 1-C4H9ONO2 + hv -> 1-C4H9O + NO2 =* *= =* *= Cross section: IUPAC 2006 (Atkinson et al., ACP, 6, 3625-4055, 2006) =* *= Quantum yield: Assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER (kdata = 200) INTEGER i, n INTEGER iw INTEGER n1, n2 REAL x1(kdata), x2(kdata) REAL y1(kdata), y2(kdata) * local REAL yg(kw), yg1(kw), yg2(kw) REAL qy REAL sig INTEGER ierr INTEGER mabs, myld **************** 1-C4H9ONO2 photodissociation j = j + 1 jlabel(j) = '1-C4H9ONO2 -> 1-C4H9O + NO2' * 1: IUPAC 2006 OPEN(NEWUNIT=ilu,FILE='DATAJ1/RONO2/1C4H9ONO2_iup2006.abs', $ STATUS='old') DO i = 1, 3 READ(UNIT=ilu,FMT=*) ENDDO n = 32 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.e-20 ENDDO CLOSE (UNIT=ilu) n1 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yield = 1 qy = 1. DO iw = 1, nw - 1 DO i = 1, nz sq(j,i,iw) = qy * yg1(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r144(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for 2-C4H9ONO2 =* *= photolysis: =* *= 2-C4H9ONO2 + hv -> 2-C4H9O + NO2 =* *= =* *= Cross section: IUPAC 2006 (Atkinson et al., ACP, 6, 3625-4055, 2006) =* *= Quantum yield: Assumed to be unity =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER (kdata = 200) INTEGER i, n INTEGER iw INTEGER n1, n2 REAL x1(kdata), x2(kdata) REAL y1(kdata), y2(kdata) * local REAL yg(kw), yg1(kw), yg2(kw) REAL qy REAL sig INTEGER ierr INTEGER mabs, myld **************** 2-C4H9ONO2 photodissociation j = j + 1 jlabel(j) = '2-C4H9ONO2 -> 2-C4H9O + NO2' * 1: IUPAC 2006 OPEN(NEWUNIT=ilu,FILE='DATAJ1/RONO2/2C4H9ONO2_iup2006.abs', $ STATUS='old') DO i = 1, 3 READ(UNIT=ilu,FMT=*) ENDDO n = 15 DO i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) y1(i) = y1(i) * 1.e-20 ENDDO CLOSE (UNIT=ilu) n1 = n CALL addpnt(x1,y1,kdata,n1,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n1, 0.,0.) CALL addpnt(x1,y1,kdata,n1,x1(n1)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n1, 1.e+38,0.) CALL inter2(nw,wl,yg1,n1,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yield = 1 qy = 1. DO iw = 1, nw - 1 DO i = 1, nz sq(j,i,iw) = qy * yg1(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *============================================================================* SUBROUTINE r145(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for =* *= perfluoro n-iodo propane (H24) =* *= cross section from JPL2011 =* *= Quantum yield: Assumed to be 0.55 =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) INTEGER iw INTEGER i, n REAL x(kdata), y(kdata) integer nn INTEGER ierr * local REAL yg(kw) REAL qy, dum j = j + 1 jlabel(j) = 'perfluoro 1-iodopropane -> products' * cross section from JPL2011 OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/PF-n-iodopropane.abs', & STATUS='old') DO i = 1, 2 READ(UNIT=ilu,FMT=*) ENDDO n = 16 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) y(i) = y(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) nn = n CALL addpnt(x,y,kdata,nn,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,nn, 0.,0.) CALL addpnt(x,y,kdata,nn,x(nn)*(1.+deltax),0.) CALL addpnt(x,y,kdata,nn, 1.e+38,0.) CALL inter2(nw,wl,yg,nn,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields assumed unity qy = 1. DO iw = 1, nw-1 DO i = 1, nz sq(j,i,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r146(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for =* *= molecular Iodine, I2 =* *= cross section from JPL2011 =* *= Quantum yield: wave-dep, from Brewer and Tellinhuisen, 1972 =* *= Quantum yield for Unimolecular Dissociation of I2 in Visible Absorption =* *= J. Chem. Phys. 56, 3929-3937, 1972. *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=200) INTEGER iw INTEGER i, n REAL x(kdata), y(kdata) integer nn INTEGER ierr * local REAL yg1(kw), yg2(kw) REAL qy, dum j = j + 1 jlabel(j) = 'I2 -> I + I' * cross section from JPL2011 OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/I2_jpl11.abs',STATUS='OLD') DO i = 1, 2 READ(UNIT=ilu,FMT=*) ENDDO n = 104 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) y(i) = y(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) nn = n CALL addpnt(x,y,kdata,nn,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,nn, 0.,0.) CALL addpnt(x,y,kdata,nn,x(nn)*(1.+deltax),0.) CALL addpnt(x,y,kdata,nn, 1.e+38,0.) CALL inter2(nw,wl,yg1,nn,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields OPEN(NEWUNIT=ilu,FILE='DATAJ1/YLD/I2.qy',STATUS='OLD') DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n = 12 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) ENDDO CLOSE(UNIT=ilu) nn = n CALL addpnt(x,y,kdata,nn,x(1)*(1.-deltax),1.) CALL addpnt(x,y,kdata,nn, 0.,1.) CALL addpnt(x,y,kdata,nn,x(nn)*(1.+deltax),0.) CALL addpnt(x,y,kdata,nn, 1.e+38,0.) CALL inter2(nw,wl,yg2,nn,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * combine DO iw = 1, nw-1 DO i = 1, nz sq(j,i,iw) = yg1(iw) * yg2(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *============================================================================* SUBROUTINE r147(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for =* *= Iodine monoxide, IO =* *= cross section from JPL2011 =* *= Quantum yield: assumed 1.0 =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=200) INTEGER iw INTEGER i, n REAL x(kdata), y(kdata) integer nn INTEGER ierr * local REAL yg(kw) REAL qy, dum j = j + 1 jlabel(j) = 'IO -> I + O' * cross section from JPL2011 OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/IO_jpl11.abs',STATUS='OLD') DO i = 1, 2 READ(UNIT=ilu,FMT=*) ENDDO n = 133 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) y(i) = y(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) nn = n CALL addpnt(x,y,kdata,nn,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,nn, 0.,0.) CALL addpnt(x,y,kdata,nn,x(nn)*(1.+deltax),0.) CALL addpnt(x,y,kdata,nn, 1.e+38,0.) CALL inter2(nw,wl,yg,nn,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields qy = 1. DO iw = 1, nw-1 DO i = 1, nz sq(j,i,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *============================================================================* SUBROUTINE r148(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide product (cross section) x (quantum yield) for =* *= Hypoiodous acid, IOH =* *= cross section from JPL2011 =* *= Quantum yield: assumed 1.0 =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=300) INTEGER iw INTEGER i, n REAL x(kdata), y(kdata) integer nn INTEGER ierr * local REAL yg(kw) REAL qy, dum j = j + 1 jlabel(j) = 'IOH -> I + OH' * cross section from JPL2011 OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/IOH_jpl11.abs',STATUS='OLD') DO i = 1, 2 READ(UNIT=ilu,FMT=*) ENDDO n = 101 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) y(i) = y(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) nn = n CALL addpnt(x,y,kdata,nn,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,nn, 0.,0.) CALL addpnt(x,y,kdata,nn,x(nn)*(1.+deltax),0.) CALL addpnt(x,y,kdata,nn, 1.e+38,0.) CALL inter2(nw,wl,yg,nn,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields qy = 1. DO iw = 1, nw-1 DO i = 1, nz sq(j,i,iw) = qy * yg(iw) ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r149(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for 2-pentanone =* *= photolysis: =* *= CH3COCH2CH2CH3 + hv -> CH3CO + CH2CH2CH3 =* *= =* *= Cross section from Martinez et al. (1992) =* *= =* *= Quantum yield assuumed 0.34 (Griffin et al., 2002) =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* *= Routine added by M. Leriche for specie KETH and KETL of CACM, ReLACS2 =* *= and ReLACS3 mecanisms - March 2018 =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=20000) INTEGER i, n REAL x(kdata), y(kdata) * local REAL yg(kw), dum REAL qy, sig INTEGER ierr INTEGER iw ************************* CH3COCH2CH2CH3 photolysis j = j+1 jlabel(j) = 'CH3COCH2CH2CH3 -> CH3CO + CH2CH2CH3' OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/Martinez.abs', $ STATUS='old') DO i = 1, 4 READ(UNIT=ilu,FMT=*) ENDDO n = 96 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), dum, dum, y(i), dum y(i) = y(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,n, 0.,0.) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields assumed to be 0.34 qy = 0.34 DO iw = 1, nw-1 DO i = 1, nz sig = yg(iw) sq(j,i,iw) = qy * sig ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r150(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for benzaldehyde =* *= photolysis: =* *= C6H5CHO + hv -> CHO + HO2 + CO =* *= =* *= Cross section from SAPRC-07 (Calvert et al., 2002) =* *= =* *= Products from Zhu and Cronin (Chem. Phys. Let., 317, 2000) =* *= =* *= Quantum yield asumed 0.06 (RACM2, Goliff et al., 2013) =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* *= Routine added by M. Leriche for BALD in RACM2 mecanism - March 2018 =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=20000) INTEGER i, n REAL x(kdata), y(kdata) * local REAL yg(kw) REAL qy, sig INTEGER ierr INTEGER iw ************************* C6H5CHO photolysis j = j+1 jlabel(j) = 'C6H5CHO -> HCO + HO2 + CO' OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/BENZALD.abs', $ STATUS='old') DO i = 1, 5 READ(UNIT=ilu,FMT=*) ENDDO n = 100 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,n, 0.,0.) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields assumed to be 0.06 qy = 0.06 DO iw = 1, nw-1 DO i = 1, nz sig = yg(iw) sq(j,i,iw) = qy * sig ENDDO ENDDO tpflag(j) = 0 RETURN END *=============================================================================* SUBROUTINE r151(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for nitrate ion =* *= photolysis in diluted aqueous atmospheric solution (cloud, rain): =* *= NO3- + hv + H2O -> NO2 + OH + OH- =* *= =* *= Cross section from Graedel and Weschler (1981) =* *= =* *= Quantum yield from Zellner, Exner and Herrmann (1990) =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* *= Routine added by M. Leriche for ReLACS-AQ and ReLACS3 mecanisms =* *= Adapted from TUVLaMP original 05/98 - March 2018 =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) INTEGER i, n REAL x(kdata), y(kdata) * local REAL yg(kw) REAL qy, sig INTEGER ierr INTEGER iw ************************* NO3-(aq) photolysis j = j+1 jlabel(j) = 'NO3-(aq) -> NO2(aq) + OH(aq)' OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABSAQ/NO3-aq.abs', $ STATUS='old') DO i = 1, 6 READ(UNIT=ilu,FMT=*) ENDDO n = 9 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) y(i) = y(i) * 1.e-20 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,n, 0.,0.) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields from: * Zellner, Exner, Herrmann: Absolute OH quantum Yields * in the laser photolysis of nitrate, nitrite and dissolved H2O2 * at 308 and 351 nm in the temperature range 278-353K, JAC, 1990. * Temperature dependency determined at 308 nm and 4<pH<9 DO iw = 1, nw-1 DO i = 1, nz qy = 0.017 * EXP (1800. *((1./298.)-(1./tlev(i)))) sig = yg(iw) * actinic flux in droplet assumes to be 1.6 the interstitial * actinic flux (see Ruggaber, 1997) sq(j,i,iw) = qy * sig *1.6 ENDDO ENDDO tpflag(j) = 1 RETURN END *=============================================================================* SUBROUTINE r152(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Provide the product (cross section) x (quantum yield) for H2O2 =* *= photolysis in diluted aqueous atmospheric solution (cloud, rain): =* *= H2O2 + hv -> OH + OH =* *= =* *= Cross section from Graedel and Weschler (1981) =* *= =* *= Quantum yield from Zellner, Exner and Herrmann (1990) =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= WC - REAL, vector of center points of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section x quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* *= Routine added by M. Leriche for ReLACS-AQ and ReLACS3 mecanisms =* *= Adapted from TUVLaMP original 05/98 - March 2018 =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw), wc(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) INTEGER TPFLAG(kj) REAL sq(kj,kz,kw) * input/output: INTEGER j * data arrays INTEGER kdata PARAMETER(kdata=100) INTEGER i, n REAL x(kdata), y(kdata) * local REAL yg(kw) REAL qy, sig INTEGER ierr INTEGER iw ************************* H2O2(aq) photolysis j = j+1 jlabel(j) = 'H2O2(aq) -> OH(aq) + OH(aq)' OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABSAQ/H2O2aq.abs', $ STATUS='old') DO i = 1, 7 READ(UNIT=ilu,FMT=*) ENDDO n = 11 DO i = 1, n READ(UNIT=ilu,FMT=*) x(i), y(i) y(i) = y(i) * 1.e-23 ENDDO CLOSE(UNIT=ilu) CALL addpnt(x,y,kdata,n,x(1)*(1.-deltax),0.) CALL addpnt(x,y,kdata,n, 0.,0.) CALL addpnt(x,y,kdata,n,x(n)*(1.+deltax),0.) CALL addpnt(x,y,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x,y,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, jlabel(j) STOP ENDIF * quantum yields from: * Zellner, Exner, Herrmann: Absolute OH quantum Yields * in the laser photolysis of nitrate, nitrite and dissolved H2O2 * at 308 and 351 nm in the temperature range 278-353K, JAC, 1990. * Temperature dependency determined at 308 nm and pH=9 DO iw = 1, nw-1 DO i = 1, nz qy = 0.98 * EXP (660. *((1./298.)-(1./tlev(i)))) sig = yg(iw) * actinic flux in droplet assumes to be 1.6 the interstitial * actinic flux (see Ruggaber, 1997) sq(j,i,iw) = qy * sig *1.6 ENDDO ENDDO tpflag(j) = 1 RETURN END CCC FILE setaer.f * vertical profiles of atmospheric variables * setaer *=============================================================================* SUBROUTINE setaer(ipbl, zpbl, aod330, $ tau550, ssaaer, alpha, $ nz, z, nw, wl, $ dtaer, omaer, gaer, kout ) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Set up an altitude profile of aerosols, and corresponding absorption =* *= optical depths, single scattering albedo, and asymmetry factor. =* *= Single scattering albedo and asymmetry factor can be selected for each =* *= input aerosol layer (do not have to correspond to working altitude =* *= grid). See loop 27. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NZ - INTEGER, number of specified altitude levels in the working (I)=* *= grid =* *= Z - REAL, specified altitude working grid (km) (I)=* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= DTAER - REAL, optical depth due to absorption by aerosols at each (O)=* *= altitude and wavelength =* *= OMAER - REAL, single scattering albedo due to aerosols at each (O)=* *= defined altitude and wavelength =* *= GAER - REAL, aerosol asymmetry factor at each defined altitude and (O)=* *= wavelength =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) INTEGER kdata PARAMETER(kdata=51) * input: REAL wl(kw) REAL z(kz) INTEGER nz INTEGER nw REAL tau550 REAL ssaaer, alpha * output: (on converted grid) REAL dtaer(kz,kw), omaer(kz,kw), gaer(kz,kw) * local: REAL zd(kdata), aer(kdata) REAL cd(kdata), omd(kdata), gd(kdata) REAL womd(kdata), wgd(kdata) REAL cz(kz) REAL omz(kz) REAL gz(kz) REAL colold REAL wc, wscale INTEGER i, iw, nd REAL fsum EXTERNAL fsum REAL zpbl INTEGER ipbl REAL aod330 REAL aodw(kw), ssaw(kw) REAL fract(kz) *_______________________________________________________________________ * Aerosol data from Elterman (1968) * These are vertical optical depths per km, in 1 km * intervals from 0 km to 50 km, at 340 nm. * This is one option. User can specify different data set. DATA aer/ 1 2.40E-01,1.06E-01,4.56E-02,1.91E-02,1.01E-02,7.63E-03, 2 5.38E-03,5.00E-03,5.15E-03,4.94E-03,4.82E-03,4.51E-03, 3 4.74E-03,4.37E-03,4.28E-03,4.03E-03,3.83E-03,3.78E-03, 4 3.88E-03,3.08E-03,2.26E-03,1.64E-03,1.23E-03,9.45E-04, 5 7.49E-04,6.30E-04,5.50E-04,4.21E-04,3.22E-04,2.48E-04, 6 1.90E-04,1.45E-04,1.11E-04,8.51E-05,6.52E-05,5.00E-05, 7 3.83E-05,2.93E-05,2.25E-05,1.72E-05,1.32E-05,1.01E-05, 8 7.72E-06,5.91E-06,4.53E-06,3.46E-06,2.66E-06,2.04E-06, 9 1.56E-06,1.19E-06,9.14E-07/ *_______________________________________________________________________ * Altitudes corresponding to Elterman profile, from bottom to top: WRITE(kout,*)'aerosols: Elterman (1968) continental profile' nd = 51 DO 22, i = 1, nd zd(i) = FLOAT(i-1) 22 CONTINUE * assume these are point values (at each level), so find column * increments DO 27, i = 1, nd - 1 cd(i) = (aer(i+1) + aer(i)) / 2. omd(i) = ssaaer gd(i) = .61 27 CONTINUE *********** end data input. * Compute integrals and averages over grid layers: * for g and omega, use averages weighted by optical depth DO 29, i = 1, nd-1 womd(i) = omd(i) * cd(i) wgd(i) = gd(i) * cd(i) 29 CONTINUE CALL inter3(nz,z,cz, nd,zd,cd, 1) CALL inter3(nz,z,omz, nd, zd,womd, 1) CALL inter3(nz,z,gz , nd, zd,wgd, 1) DO 30, i = 1, nz-1 IF (cz(i) .GT. 0.) THEN omz(i) = omz(i)/cz(i) gz(i) = gz(i) /cz(i) ELSE omz(i) = 1. gz(i) = 0. ENDIF 30 CONTINUE * old column at 340 nm * (minimum value is pzero = 10./largest) colold = MAX(fsum(nz-1,cz),pzero) * scale with new column tau at 550 nm IF(tau550 .GT. nzero) THEN DO i = 1, nz-1 cz(i) = cz(i) * (tau550/colold) * (550./340.)**alpha ENDDO ENDIF * assign at all wavelengths * (can move wavelength loop outside if want to vary with wavelength) DO 50, iw = 1, nw - 1 wc = (wl(iw)+wl(iw+1))/2. * Elterman's data are for 340 nm, so assume optical depth scales * inversely with first power of wavelength. wscale = (340./wc)**alpha * optical depths: DO 40, i = 1, nz - 1 dtaer(i,iw) = cz(i) * wscale omaer(i,iw) = omz(i) gaer(i,iw) = gz(i) 40 CONTINUE 50 CONTINUE *! overwrite for pbl: IF(ipbl .GT. 0) THEN write (*,*) 'pbl aerosols, aod330 = ', aod330 * create wavelength-dependent optical depth and single scattering albedo: DO iw = 1, nw-1 wc = (wl(iw)+wl(iw+1))/2. aodw(iw) = aod330*(wc/330.)**(-1.0) IF(wc .LT. 400.) THEN ssaw(iw) = 0.6 ELSE ssaw(iw) = 0.9 ENDIF ENDDO * divide aod among pbl layers, overwrite Elterman profile in pbl DO i = 1, ipbl fract(i) = (z(i+1) - z(i))/zpbl ENDDO DO iw = 1, nw-1 DO i = 1, ipbl dtaer(i, iw) = aodw(iw) * fract(i) omaer(i,iw) = ssaw(iw) ENDDO ENDDO ENDIF *_______________________________________________________________________ RETURN END CCC FILE setalb.f *=============================================================================* SUBROUTINE setalb(albnew,nw,wl,albedo,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Set the albedo of the surface. The albedo is assumed to be Lambertian, =* *= i.e., the reflected light is isotropic, and independent of direction =* *= of incidence of light. Albedo can be chosen to be wavelength dependent. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= ALBEDO - REAL, surface albedo at each specified wavelength (O)=* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input: (wavelength working grid data) INTEGER nw REAL wl(kw) REAL albnew * output: REAL albedo(kw) * local: INTEGER iw *_______________________________________________________________________ DO 10, iw = 1, nw - 1 albedo(iw) = albnew 10 CONTINUE * alternatively, can input wavelenght-dependent values if avaialble. *_______________________________________________________________________ RETURN END CCC FILE setcld.f *======================================================================* SUBROUTINE setcld(nz,z,nw,wl, $ lwc, nlevel, $ dtcld,omcld,gcld,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Set cloud properties for each specified altitude layer. Properties =* *= may be wavelength dependent. =* *= Assumes horizontally infinite homogeneous cloud layers. *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NZ - INTEGER, number of specified altitude levels in the working (I)=* *= grid =* *= Z - REAL, specified altitude working grid (km) (I)=* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= DTCLD - REAL, optical depth due to absorption by clouds at each (O)=* *= altitude and wavelength =* *= OMCLD - REAL, single scattering albedo due to clouds at each (O)=* *= defined altitude and wavelength =* *= GCLD - REAL, cloud asymmetry factor at each defined altitude and (O)=* *= wavelength =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) INTEGER kdata C PARAMETER(kdata=51) PARAMETER(kdata=151) ***** input * (grids) REAL wl(kw) REAL z(kz) INTEGER nz INTEGER nw * new total cloud optical depth: REAL taucld C REAL zbase, ztop C LWC is the liquid water content (!! kg/m3 !!) on the calling model C grid (which has NLEVEL points: Z(1:NLEVEL) = AZ(*) REAL lwc(*) INTEGER nlevel ***** Output: REAL dtcld(kz,kw), omcld(kz,kw), gcld(kz,kw) ***** specified default data: REAL zd(kdata), cd(kdata), omd(kdata), gd(kdata) REAL womd(kdata), wgd(kdata) REAL cldold * other: REAL cz(kz) REAL omz(kz) REAL gz(kz) INTEGER i, iw, n REAL scale * External functions: REAL fsum EXTERNAL fsum *_______________________________________________________________________ * Set up clouds: * All clouds are assumed to be infinite homogeneous layers * Can have different clouds at different altitudes. * If multiple cloud layers are specified, non-cloudy layers * between them (if any) must be assigned zero optical depth. * Set cloud optical properties: * cd(i) = optical depth of i_th cloudy layer * omd(i) = singel scattering albedo of i_th cloudy layer * gd(i) = asymmetry factorof i_th cloudy layer * Cloud top and bottom can be set to any height zd(i), but if they don't * match the z-grid (see subroutine gridz.f), they will be interpolated to * the z-grid. * Example: set two separate cloudy layers: * cloud 1: * base = 4 km * top = 7 km * optical depth = 20. (6.67 per km) * single scattering albedo = 0.9999 * asymmetry factor = 0.85 * cloud 2: * base = 9 km * top = 11 km * optical depth = 5. (2.50 per km) * single scattering albedo = 0.99999 * asymmetry factor = 0.85 n = nlevel + 1 if (n .gt. kdata) stop "SETCLD: not enough memory: KDATA" zd(1) = 0. do 110, i = 2, n zd(i) = 0.5*( z(i-1) + z(i) ) 110 continue C calculate cloud optical properties do 120, i = 1, nlevel C C reference: Fouquart et al., Rev. Geophys., 1990 C TAU = 3/2 LWC*DZ / (RHOWATER * Reff) C RHOWATER = 1E3 kg/m3 C Reff = (11 w + 4) 1E-6 C w = LWC * 1E+3 (in g/cm3, since LWC is given in kg/m3) C cd(i) = 1.5 * ( lwc(i) * 1E3*(zd(i+1) - zd(i)) ) + / ( 1E3 * (11.*lwc(i)*1E+3+4.) * 1E-6) omd(i) = .9999 gd(i) = .85 C print '(A,I5,99E12.5)', "I,TAU,LWC,REFF(um)" C + , i, cd(i), lwc(i) C + , ((11.*lwc(i)*1E+3+4.)) 120 continue ****************** * compute integrals and averages over grid layers: * for g and omega, use averages weighted by optical depth DO 10, i = 1, n-1 womd(i) = omd(i) * cd(i) wgd(i) = gd(i) * cd(i) 10 CONTINUE CALL inter3(nz,z,cz, n, zd,cd, 0) CALL inter3(nz,z,omz, n, zd,womd, 0) CALL inter3(nz,z,gz , n, zd,wgd, 0) DO 15, i = 1, nz-1 IF (cz(i) .GT. 0.) THEN omz(i) = omz(i)/cz(i) gz(i) = gz(i) /cz(i) ELSE omz(i) = 1. gz(i) = 0. ENDIF 15 CONTINUE * assign at all wavelengths * (can move wavelength loop outside if want to vary with wavelength) DO 20, iw = 1, nw-1 DO 25, i = 1, nz-1 dtcld(i,iw) = cz(i) omcld(i,iw) = omz(i) gcld (i,iw) = gz(i) 25 CONTINUE 20 CONTINUE *_______________________________________________________________________ RETURN END CCC FILE setno2.f *=============================================================================* SUBROUTINE setno2(ipbl, zpbl, xpbl, $ no2new, nz, z, nw, wl, no2xs, $ tlay, dcol, $ dtno2,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Set up an altitude profile of NO2 molecules, and corresponding absorption=* *= optical depths. Subroutine includes a shape-conserving scaling method =* *= that allows scaling of the entire profile to a given overhead NO2 =* *= column amount. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NO2NEW - REAL, overhead NO2 column amount (molec/cm^2) to which (I)=* *= profile should be scaled. If NO2NEW < 0, no scaling is done =* *= NZ - INTEGER, number of specified altitude levels in the working (I)=* *= grid =* *= Z - REAL, specified altitude working grid (km) (I)=* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= NO2XS - REAL, molecular absoprtion cross section (cm^2) of O2 at (I)=* *= each specified wavelength =* *= TLAY - REAL, temperature (K) at each specified altitude layer (I)=* *= DTNO2 - REAL, optical depth due to NO2 absorption at each (O)=* *= specified altitude at each specified wavelength =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) INTEGER kdata PARAMETER(kdata=51) ******** * input: ******** * grids: REAL wl(kw) REAL z(kz) INTEGER nw INTEGER nz REAL no2new * mid-layer temperature, layer air column REAL tlay(kz), dcol(kz) ******** * output: ******** REAL dtno2(kz,kw) ******** * local: ******** * absorption cross sections REAL no2xs(kz,kw) REAL cz(kz) * nitrogen dioxide profile data: REAL zd(kdata), no2(kdata) REAL cd(kdata) REAL hscale REAL colold, scale REAL sno2 REAL zpbl, xpbl INTEGER ipbl * other: INTEGER i, l, nd ******** * External functions: ******** REAL fsum EXTERNAL fsum *_______________________________________________________________________ * Data input: * Example: set to 1 ppb in lowest 1 km, set to zero above that. * - do by specifying concentration at 3 altitudes. nd = 3 zd(1) = 0. no2(1) = 1. * 2.69e10 zd(2) = 1. no2(2) = 1. * 2.69e10 zd(3) = zd(2)* 1.000001 no2(3) = 10./largest * compute column increments (alternatively, can specify these directly) DO 11, i = 1, nd - 1 cd(i) = (no2(i+1)+no2(i)) * 1.E5 * (zd(i+1)-zd(i)) / 2. 11 CONTINUE * Include exponential tail integral from top level to infinity. * fold tail integral into top layer * specify scale height near top of data (use ozone value) hscale = 4.50e5 cd(nd-1) = cd(nd-1) + hscale * no2(nd) *********** *********** end data input. * Compute column increments and total column on standard z-grid. CALL inter3(nz,z,cz, nd,zd,cd, 1) **** Scaling of vertical profile by ratio of new to old column: * If old column is near zero (less than 1 molec cm-2), * use constant mixing ratio profile (nominal 1 ppt before scaling) * to avoid numerical problems when scaling. IF(fsum(nz-1,cz) .LT. 1.) THEN DO i = 1, nz-1 cz(i) = 1.E-12 * dcol(i) ENDDO ENDIF colold = fsum(nz-1, cz) scale = 2.687e16 * no2new / colold DO i = 1, nz-1 cz(i) = cz(i) * scale ENDDO *! overwrite for specified pbl height IF(ipbl .GT. 0) THEN write(*,*) 'pbl NO2 = ', xpbl, ' ppb' DO i = 1, nz-1 IF (i .LE. ipbl) THEN cz(i) = xpbl*1.E-9 * dcol(i) ELSE cz(i) = 0. ENDIF ENDDO ENDIF ************************************ * calculate optical depth for each layer. Output: dtno2(kz,kw) 98 continue DO 20, l = 1, nw-1 DO 10, i = 1, nz-1 dtno2(i,l) = cz(i)*no2xs(i,l) 10 CONTINUE 20 CONTINUE *_______________________________________________________________________ RETURN END CCC FILE seto2.f *=============================================================================* SUBROUTINE seto2(nz, z, nw, wl, cz, o2xs1, dto2, kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Set up an altitude profile of air molecules. Subroutine includes a =* *= shape-conserving scaling method that allows scaling of the entire =* *= profile to a given sea-level pressure. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NZ - INTEGER, number of specified altitude levels in the working (I)=* *= grid =* *= Z - REAL, specified altitude working grid (km) (I)=* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= and each specified wavelength =* *= CZ - REAL, number of air molecules per cm^2 at each specified (O)=* *= altitude layer =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input: (grids) REAL wl(kw) REAL z(kz) INTEGER iw, nw INTEGER iz, nz REAL cz(kz) REAL o2xs1(kw) * output: * O2 absorption optical depth per layer at each wavelength REAL dto2(kz,kw) *_______________________________________________________________________ * Assumes that O2 = 20.95 % of air density. If desire different O2 * profile (e.g. for upper atmosphere) then can load it here. DO iz = 1, nz-1 DO iw =1, nw - 1 dto2(iz,iw) = 0.2095 * cz(iz) * o2xs1(iw) ENDDO ENDDO *_______________________________________________________________________ RETURN END CCC FILE setsnw.f * This file contains the following subroutines related to spectral optical * propersties of snowpack needed to compute actinic fluxes * setsnw * rdice_acff *=============================================================================* SUBROUTINE setsnw(nz,z,nw,wl,dtsnw,omsnw,gsnw,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Set optical and physical properties for snowpack. =* *= Currently for wavelength-independent properties. =* *= Subroutine outputs spectral quantities. =* *= Lee-Taylor, J., and S. Madronich (2002), Calculation of actinic fluxes =* *= with a coupled atmosphere-snow radiative transfer model, J. Geophys. =* *= Res., 107(D24) 4796 (2002) doi:10.1029/2002JD002084 =* *-----------------------------------------------------------------------------* *= USER-DEFINED VARIABLES: =* *= zs - height (km) of snow layer boundary above GROUND level =* *= snwdens - density (g/cm3) =* *= ksct - mass-specific scattering coefficient (m2/kg) =* *= csoot - soot content (ng Carbon / g snow) =* *= snow - (=T/F) switch for presence of snow *= =* *= PARAMETERS: =* *= nz - INTEGER, number of specified altitude levels in the working (I)=* *= grid =* *= z - REAL, specified altitude working grid (km) (I)=* *= nw - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= wl - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= dtsnw - REAL, optical depth due to absorption by snow at each (O)=* *= altitude and wavelength =* *= omsnw - REAL, single scattering albedo due to snow at each (O)=* *= defined altitude and wavelength =* *= gsnw - REAL, snow asymmetry factor at each defined altitude and (O)=* *= wavelength =* *= rabs - absorption coefficient of snow, wavelength-dependent =* *= rsct - scattering coefficient of snow, assume wavelength-independent =* *-----------------------------------------------------------------------------* *= EDIT HISTORY: =* *= 10/00 adapted from setcld.f, Julia Lee-Taylor, ACD, NCAR =* *-----------------------------------------------------------------------------* *= This program 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 2 of the license, or (at your =* *= option) any later version. =* *= The TUV package is distributed in the hope that it will be useful, but =* *= WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBI- =* *= LITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public =* *= License for more details. =* *= To obtain a copy of the GNU General Public License, write to: =* *= Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. =* *-----------------------------------------------------------------------------* *= To contact the authors, please mail to: =* *= Jula Lee-Taylor, NCAR/ACD, P.O.Box 3000, Boulder, CO, 80307-3000, USA or =* *= send email to: julial@ucar.edu =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) INTEGER kdata PARAMETER(kdata=51) * input: (grids) REAL wl(kw) REAL z(kz) INTEGER nz INTEGER nw * Output: REAL dtsnw(kz,kw), omsnw(kz,kw), gsnw(kz,kw) * local: * specified data: REAL zs(kdata),dzs REAL cd(kdata), omd(kdata), gd REAL snwdens(kdata) ! snwdens = snow density, g/cm3 REAL csoot(kdata) ! conc of elemental carbon, ng/g REAL r_ice(kw),rsoot REAL womd(kdata), wgd(kdata) REAL rsct(kdata),ksct(kdata),rabs(kdata) * other: REAL cz(kz),omz(kz),gz(kz) INTEGER i,is,iw,iz,nsl * External functions: REAL fsum EXTERNAL fsum *-------------------------------------------------------------------------- * SNOW PROPERTIES: USER-DEFINED *-------------------------------------------------------------------------- ** define "number of snow layers + 1" (0 = no snow, 2 = single snow layer) nsl = 0 IF(nsl.GE.2)THEN ** define snow grid, zs(ns), in km above GROUND level * NOTE: to get good vertical resolution, subroutine gridz (in grids.f) should * be modified to include small (1cm - 1mm) layers near snowpack top. zs(1) = 0.0 zs(2) = 0.001 ** define snow scattering coefficient, ksct, m2/kg snow * melting midlatitude maritime (mountain) snow, ksct = 1-5 m2/kg_snow * warmer polar coastal/maritime snow, ksct = 6-13 m2/kg_snow * cold dry polar/tundra snow, ksct = 20-30 m2/kg_snow * Fisher, King and Lee-Taylor (2005), JGR 110(D21301) doi:10.1029/2005JD005963 ksct(1) = 25. ! m2.kg-1 snow ** define snow density, snwdens, g/cm3 snwdens(1) = 0.4 ! g/cm3 ** define soot content, csoot, ng/g elemental carbon csoot(1) = 0. ! ng/g elemental carbon *---------------------------------------------------------------------------- * SNOW PROPERTIES: FROM LITERATURE *-------------------------------------------------------------------------- * read absorption coefficients CALL rdice_acff(nw,wl,r_ice,kout) ! cm^-1 ice * absorption due to soot, assume wavelength-independent * rsoot ~ 10 m2/gC @500nm : Warren & Wiscombe, Nature 313,467-470 (1985) rsoot = 10. ! m2/gC * asymmetry factor : Wiscombe & Warren, J. Atmos. Sci, 37, 2712-2733 (1980) gd = 0.89 *---------------------------------------------------------------------------- * loop snow layers, assigning optical properties at each wavelength DO 17, iw = 1, nw-1 DO 11 is = 1,nsl-1 rsct(is)=ksct(is)*snwdens(is)*1.e+3 ! m-1 rsct(is)=rsct(is)*(zs(is+1)-zs(is))*1.e+3 ! no units rabs(is) = (r_ice(iw)/0.9177*1.e5 + rsoot*csoot(is)) $ * snwdens(is)*(zs(is+1)-zs(is)) ! no units cd(is) = rsct(is) + rabs(is) omd(is)= rsct(is) / cd(is) if(iw.EQ.1)then print*,"Snowpack: is =",is,"; zs =",zs(is) PRINT*," ksct =", ksct(is) PRINT*," density =",snwdens(is) PRINT*," csoot =",csoot(is) PRINT*, 'cd = ',cd(is),' omd = ',omd(is),' gd = ',gd WRITE(kout,*)'snwdens = ',snwdens,' g/cm3' WRITE(kout,*)'ksct_snow = ',ksct(is),' m2.kg-1' WRITE(kout,*)'soot = ',csoot(is),' ng/g' WRITE(kout,*)'cd = ',cd(is),'omd = ',omd(is),'gd = ',gd endif * compute integrals and averages over snow layers: * for g and omega, use averages weighted by optical depth womd(is) = omd(is) * cd(is) wgd(is) = gd * cd(is) 11 CONTINUE * interpolate snow layers onto TUV altitude grid (gridz) CALL inter3(nz,z,cz, nsl,zs,cd, 0) CALL inter3(nz,z,omz,nsl,zs,womd, 0) CALL inter3(nz,z,gz ,nsl,zs,wgd, 0) DO 15, iz = 1, nz-1 IF (cz(iz) .GT. 0.) THEN omz(iz) = omz(iz)/cz(iz) gz(iz) = gz(iz) /cz(iz) ELSE omz(iz) = 0. gz(iz) = 0. ENDIF dtsnw(iz,iw) = cz(iz) omsnw(iz,iw) = omz(iz) gsnw(iz,iw) = gz(iz) 15 CONTINUE 17 CONTINUE PRINT*,"Snowpack top: zs =",zs(nsl) ELSE ! no snow DO 16, iz = 1, nz-1 cz(iz) = 0. omz(iz) = 1. gz(iz) = 0. DO 18, iw = 1, nw-1 dtsnw(iz,iw) = cz(iz) omsnw(iz,iw) = omz(iz) gsnw(iz,iw) = gz(iz) 18 CONTINUE 16 CONTINUE ENDIF ! snow exists RETURN END ******************************************************************************* SUBROUTINE rdice_acff(nw,wl,rabs,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Read ice absorption coefficient. Re-grid data to match =* *= specified wavelength working grid. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= RABS_ice - REAL, absorption coefficient (cm^-1) of ice at (O)=* *= each specified wavelength =* *-----------------------------------------------------------------------------* *= EDIT HISTORY: =* *= 10/00 Created routine by editing rdh2oxs. =* *-----------------------------------------------------------------------------* *= This program 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 2 of the license, or (at your =* *= option) any later version. =* *= The TUV package is distributed in the hope that it will be useful, but =* *= WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBI- =* *= LITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public =* *= License for more details. =* *= To obtain a copy of the GNU General Public License, write to: =* *= Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. =* *-----------------------------------------------------------------------------* *= To contact the authors, please mail to: =* *= Sasha Madronich, NCAR/ACD, P.O.Box 3000, Boulder, CO, 80307-3000, USA or =* *= send email to: sasha@ucar.edu =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) INTEGER kdata PARAMETER(kdata=1000) * input: (altitude working grid) INTEGER nw REAL wl(kw) * output: REAL rabs(kw) * local: REAL x1(kdata) REAL y1(kdata),y2(kdata),y3(kdata) REAL yg(kw) REAL a1, a2, dum INTEGER ierr INTEGER i,l,m, n, idum CHARACTER*40 fil *_______________________________________________________________________ ************* absorption cross sections: * ice absorption cross sections from fil = 'DATA/ice' OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/ICE_Perov.acff',STATUS='old') m = 17 ! header lines n = 79 ! data lines !OPEN(NEWUNIT=ilu,FILE='DATAJ1/ABS/ICE_min.acff',STATUS='old') !m = 13 ! header lines !n = 52 ! data lines DO 11, i = 1,m read(UNIT=ilu,FMT=*) 11 CONTINUE DO 12, i = 1, n READ(UNIT=ilu,FMT=*) x1(i), y1(i) 12 CONTINUE CLOSE (UNIT=ilu) CALL addpnt(x1,y1,kdata,n,x1(1)*(1.-deltax),0.) CALL addpnt(x1,y1,kdata,n, 0.,0.) CALL addpnt(x1,y1,kdata,n,x1(n)*(1.+deltax),0.) CALL addpnt(x1,y1,kdata,n, 1.e+38,0.) CALL inter2(nw,wl,yg,n,x1,y1,ierr) IF (ierr .NE. 0) THEN WRITE(*,*) ierr, fil STOP ENDIF DO 13, l = 1, nw-1 rabs(l) = yg(l) 13 CONTINUE *_______________________________________________________________________ RETURN END CCC FILE setso2.f *=============================================================================* SUBROUTINE setso2(ipbl, zpbl, xpbl, $ so2new, nz, z, nw, wl, so2xs, $ tlay, dcol, $ dtso2,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Set up an altitude profile of SO2 molecules, and corresponding absorption=* *= optical depths. Subroutine includes a shape-conserving scaling method =* *= that allows scaling of the entire profile to a given overhead SO2 =* *= column amount. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= SO2NEW - REAL, overhead SO2 column amount (molec/cm^2) to which (I)=* *= profile should be scaled. If SO2NEW < 0, no scaling is done =* *= NZ - INTEGER, number of specified altitude levels in the working (I)=* *= grid =* *= Z - REAL, specified altitude working grid (km) (I)=* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= SO2XS - REAL, molecular absoprtion cross section (cm^2) of O2 at (I)=* *= each specified wavelength =* *= TLAY - REAL, temperature (K) at each specified altitude layer (I)=* *= DTSO2 - REAL, optical depth due to SO2 absorption at each (O)=* *= specified altitude at each specified wavelength =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) INTEGER kdata PARAMETER(kdata=51) ******** * input: ******** * grids: REAL wl(kw) REAL z(kz) INTEGER nw INTEGER nz REAL so2new * mid-layer temperature and layer air column REAL tlay(kz), dcol(kz) ******** * output: ******** REAL dtso2(kz,kw) ******** * local: ******** * absorption cross sections REAL so2xs(kw) REAL cz(kz) * sulfur dioxide profile data: REAL zd(kdata), so2(kdata) REAL cd(kdata) REAL hscale REAL colold, scale REAL sso2 REAL zpbl, xpbl INTEGER ipbl * other: INTEGER i, l, nd ******** * External functions: ******** REAL fsum EXTERNAL fsum *_______________________________________________________________________ * Data input: * Example: set to 1 ppb in lowest 1 km, set to zero above that. * - do by specifying concentration at 3 altitudes. nd = 3 zd(1) = 0. so2(1) = 1. * 2.69e10 zd(2) = 1. so2(2) = 1. * 2.69e10 zd(3) = zd(2)* 1.000001 so2(3) = 10./largest * compute column increments (alternatively, can specify these directly) DO 11, i = 1, nd - 1 cd(i) = (so2(i+1)+so2(i)) * 1.E5 * (zd(i+1)-zd(i)) / 2. 11 CONTINUE * Include exponential tail integral from top level to infinity. * fold tail integral into top layer * specify scale height near top of data (use ozone value) hscale = 4.50e5 cd(nd-1) = cd(nd-1) + hscale * so2(nd) *********** *********** end data input. * Compute column increments on standard z-grid. CALL inter3(nz,z,cz, nd,zd,cd, 1) **** Scaling of vertical profile by ratio of new to old column: * If old column is near zero (less than 1 molec cm-2), * use constant mixing ratio profile (nominal 1 ppt before scaling) * to avoid numerical problems when scaling. IF(fsum(nz-1,cz) .LT. 1.) THEN DO i = 1, nz-1 cz(i) = 1.E-12 * dcol(i) ENDDO ENDIF colold = fsum(nz-1,cz) scale = 2.687e16 * so2new / colold DO i = 1, nz-1 cz(i) = cz(i) * scale ENDDO *! overwrite for specified pbl height, set concentration here IF(ipbl .GT. 0) THEN write(*,*) 'pbl SO2 = ', xpbl, ' ppb' DO i = 1, nz-1 IF (i .LE. ipbl) THEN cz(i) = xpbl*1.E-9 * dcol(i) ELSE cz(i) = 0. ENDIF ENDDO ENDIF ************************************ * calculate sulfur optical depth for each layer, with optional temperature * correction. Output, dtso2(kz,kw) DO 20, l = 1, nw-1 sso2 = so2xs(l) DO 10, i = 1, nz - 1 c Leaving this part in in case i want to interpolate between c the 221K and 298K data. c c IF ( wl(l) .GT. 240.5 .AND. wl(l+1) .LT. 350. ) THEN c IF (tlay(i) .LT. 263.) THEN c sso2 = s221(l) + (s263(l)-s226(l)) / (263.-226.) * c $ (tlay(i)-226.) c ELSE c sso2 = s263(l) + (s298(l)-s263(l)) / (298.-263.) * c $ (tlay(i)-263.) c ENDIF c ENDIF dtso2(i,l) = cz(i)*sso2 10 CONTINUE 20 CONTINUE *_______________________________________________________________________ RETURN END CCC FILE sphers.f * This file contains the following subroutines, related to the * spherical geometry of the Earth's atmosphere * sphers * airmas *=============================================================================* SUBROUTINE sphers(nz, z, zen, dsdh, nid, kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Calculate slant path over vertical depth ds/dh in spherical geometry. =* *= Calculation is based on: A.Dahlback, and K.Stamnes, A new spheric model =* *= for computing the radiation field available for photolysis and heating =* *= at twilight, Planet.Space Sci., v39, n5, pp. 671-683, 1991 (Appendix B) =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NZ - INTEGER, number of specified altitude levels in the working (I)=* *= grid =* *= Z - REAL, specified altitude working grid (km) (I)=* *= ZEN - REAL, solar zenith angle (degrees) (I)=* *= DSDH - REAL, slant path of direct beam through each layer crossed (O)=* *= when travelling from the top of the atmosphere to layer i; =* *= DSDH(i,j), i = 0..NZ-1, j = 1..NZ-1 =* *= NID - INTEGER, number of layers crossed by the direct beam when (O)=* *= travelling from the top of the atmosphere to layer i; =* *= NID(i), i = 0..NZ-1 =* *-----------------------------------------------------------------------------* *= EDIT HISTORY: =* *= double precision fix for shallow layers - Julia Lee-Taylor Dec 2000 =* *-----------------------------------------------------------------------------* *= This program 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 2 of the license, or (at your =* *= option) any later version. =* *= The TUV package is distributed in the hope that it will be useful, but =* *= WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBI- =* *= LITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public =* *= License for more details. =* *= To obtain a copy of the GNU General Public License, write to: =* *= Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. =* *-----------------------------------------------------------------------------* *= To contact the authors, please mail to: =* *= Sasha Madronich, NCAR/ACD, P.O.Box 3000, Boulder, CO, 80307-3000, USA or =* *= send email to: sasha@ucar.edu =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nz REAL zen, z(kz) * output INTEGER nid(0:kz) REAL dsdh(0:kz,kz) * more program constants REAL re, ze(kz) REAL dr PARAMETER ( dr = pi/180.) * local REAL(kind(0.0d0)) :: zenrad, rpsinz, rj, rjp1, dsj, dhj, & ga, gb, sm INTEGER i, j, k INTEGER id INTEGER nlayer REAL zd(0:kz-1) *----------------------------------------------------------------------------- zenrad = zen*dr * number of layers: nlayer = nz - 1 * include the elevation above sea level to the radius of the earth: re = radius + z(1) * correspondingly z changed to the elevation above earth surface: DO k = 1, nz ze(k) = z(k) - z(1) END DO * inverse coordinate of z zd(0) = ze(nz) DO k = 1, nlayer zd(k) = ze(nz - k) END DO * initialize dsdh(i,j), nid(i) DO i = 0, kz nid(i) = 0 DO j = 1, kz dsdh(i,j) = 0. END DO END DO * calculate ds/dh of every layer DO 100 i = 0, nlayer rpsinz = (re + zd(i)) * SIN(zenrad) IF ( (zen .GT. 90.0) .AND. (rpsinz .LT. re) ) THEN nid(i) = -1 ELSE * * Find index of layer in which the screening height lies * id = i IF( zen .GT. 90.0 ) THEN DO 10 j = 1, nlayer IF( (rpsinz .LT. ( zd(j-1) + re ) ) .AND. $ (rpsinz .GE. ( zd(j) + re )) ) id = j 10 CONTINUE END IF DO 20 j = 1, id sm = 1.0 IF(j .EQ. id .AND. id .EQ. i .AND. zen .GT. 90.0) $ sm = -1.0 rj = re + zd(j-1) rjp1 = re + zd(j) dhj = zd(j-1) - zd(j) ga = rj*rj - rpsinz*rpsinz gb = rjp1*rjp1 - rpsinz*rpsinz IF (ga .LT. 0.0) ga = 0.0 IF (gb .LT. 0.0) gb = 0.0 IF(id.GT.i .AND. j.EQ.id) THEN dsj = SQRT( ga ) ELSE dsj = SQRT( ga ) - sm*SQRT( gb ) END IF dsdh(i,j) = dsj / dhj 20 CONTINUE nid(i) = id END IF 100 CONTINUE *----------------------------------------------------------------------------- RETURN END *=============================================================================* SUBROUTINE airmas(nz, dsdh, nid, cz, $ vcol, scol,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Calculate vertical and slant air columns, in spherical geometry, as a =* *= function of altitude. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NZ - INTEGER, number of specified altitude levels in the working (I)=* *= grid =* *= DSDH - REAL, slant path of direct beam through each layer crossed (O)=* *= when travelling from the top of the atmosphere to layer i; =* *= DSDH(i,j), i = 0..NZ-1, j = 1..NZ-1 =* *= NID - INTEGER, number of layers crossed by the direct beam when (O)=* *= travelling from the top of the atmosphere to layer i; =* *= NID(i), i = 0..NZ-1 =* *= VCOL - REAL, output, vertical air column, molec cm-2, above level iz =* *= SCOL - REAL, output, slant air column in direction of sun, above iz =* *= also in molec cm-2 =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * Input: INTEGER nz INTEGER nid(0:kz) REAL dsdh(0:kz,kz) REAL cz(kz) * output: REAL vcol(kz), scol(kz) * internal: INTEGER id, j REAL sum, vsum * calculate vertical and slant column from each level: * work downward vsum = 0. DO id = 0, nz - 1 vsum = vsum + cz(nz-id) vcol(nz-id) = vsum sum = 0. IF(nid(id) .LT. 0) THEN sum = largest ELSE * single pass layers: DO j = 1, MIN(nid(id), id) sum = sum + cz(nz-j)*dsdh(id,j) ENDDO * double pass layers: DO j = MIN(nid(id),id)+1, nid(id) sum = sum + 2.*cz(nz-j)*dsdh(id,j) ENDDO ENDIF scol(nz - id) = sum ENDDO RETURN END CCC FILE swchem.f *=============================================================================* SUBROUTINE swchem(nw,wl,nz,tlev,airden, $ j,sq,jlabel,tpflag,kout) *-----------------------------------------------------------------------------* *= PURPOSE: =* *= Load various "weighting functions" (products of cross section and =* *= quantum yield at each altitude and each wavelength). The altitude =* *= dependence is necessary to ensure the consideration of pressure and =* *= temperature dependence of the cross sections or quantum yields. =* *= The actual reading, evaluation and interpolation is done in separate =* *= subroutines for ease of management and manipulation. Please refer to =* *= the inline documentation of the specific subroutines for detail =* *= information. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NW - INTEGER, number of specified intervals + 1 in working (I)=* *= wavelength grid =* *= WL - REAL, vector of lower limits of wavelength intervals in (I)=* *= working wavelength grid =* *= NZ - INTEGER, number of altitude levels in working altitude grid (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (I)=* *= AIRDEN - REAL, air density (molec/cc) at each altitude level (I)=* *= J - INTEGER, counter for number of weighting functions defined (IO)=* *= SQ - REAL, cross section * quantum yield (cm^2) for each (O)=* *= photolysis reaction defined, at each defined wavelength and =* *= at each defined altitude level =* *= JLABEL - CHARACTER*50, string identifier for each photolysis reaction (O)=* *= defined =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * input INTEGER nw REAL wl(kw) INTEGER nz REAL tlev(kz) REAL airden(kz) * weighting functions CHARACTER*50 jlabel(kj) REAL sq(kj,kz,kw) INTEGER tpflag(kj) * input/output: INTEGER j * local: REAL wc(kw) INTEGER iw *_______________________________________________________________________ * complete wavelength grid DO 5, iw = 1, nw - 1 wc(iw) = (wl(iw) + wl(iw+1))/2. 5 CONTINUE *____________________________________________________________________________ ******** Ox Photochemistry * A1. O2 + hv -> O + O * reserve first position. Cross section parameterization in Schumman-Runge and * Lyman-alpha regions are zenith-angle dependent, will be written in * subroutine seto2.f. * declare temperature dependence, tpflag = 1 j = 1 jlabel(j) = 'O2 -> O + O' tpflag(j) = 1 *A2. O3 + hv -> (both channels) CALL r01(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) ******** HOx Photochemistry *B1. HO2 + hv -> OH + O C CALL r39(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *B3. H2O2 + hv -> 2 OH CALL r08(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) ******** NOx Photochemistry *C1. NO2 + hv -> NO + O(3P) CALL r02(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *C2. NO3 + hv -> (both channels) CALL r03(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *C3. N2O + hv -> N2 + O(1D) C CALL r44(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *C5. N2O5 + hv -> (both channels) C CALL r04(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *C6. HNO2 + hv -> OH + NO CALL r05(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *C7. HNO3 + hv -> OH + NO2 CALL r06(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *C8. HNO4 + hv -> HO2 + NO2 CALL r07(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) * NO3-(aq) + hv -> NO2 + O- (for snow) * NO3-(aq) + hv -> NO2- + O(3P) (for snow) C CALL r118(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) ******** Organic Photochemistry *D1. CH2O + hv -> (both channels) c CALL r10(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) CALL pxCH2O(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *D2. CH3CHO + hv -> (all three channels) CALL r11(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *D3. C2H5CHO + hv -> C2H5 + HCO CALL r12(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *D9. CH3(OOH) + hv -> CH3O + OH CALL r16(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *D10. HOCH2OOH -> HOCH2O. + OH C CALL r121(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *D12. CH3(ONO2) + hv -> CH3O + NO2 CALL r17(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *D13. CH3(OONO2) -> CH3(OO) + NO2 C call r134(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) * CH3CH2(ONO2) -> CH3CH2O + NO2 CALL r106(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) * C2H5(ONO2) -> C2H5O + NO2 C call r141(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) * n-C3H7ONO2 -> n-C3H7O + NO2 call r142(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) * 1-C4H9ONO2 -> 1-C4H9O + NO2 C call r143(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) * 2-C4H9ONO2 -> 2-C4H9O + NO2 C call r144(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) * CH3CH(ONO2)CH3 -> CH3CHOCH3 + NO2 CALL r107(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) * CH2(OH)CH2(ONO2) -> CH2(OH)CH2(O.) + NO2 C CALL r108(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) * CH3COCH2(ONO2) -> CH3COCH2(O.) + NO2 C CALL r109(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) * C(CH3)3(ONO2) -> C(CH3)3(O.) + NO2 C CALL r110(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) * C(CH3)3(ONO) -> C(CH3)3(O) + NO C call r135(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *D14. PAN + hv -> CH3CO(OO) + NO2 * PAN + hv -> CH3CO(O) + NO3 CALL r18(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *D15. CH3CH2COO2NO2 -> CH3CH2CO(OO) + NO2 * CH3CH2COO2NO2 -> CH2CH2CO(O) + NO3 CALL r120(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *D16. CH2=CHCHO + hv -> Products CALL r122(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *D17. CH2=C(CH3)CHO + hv -> Products CALL r104(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *D18. CH3COCH=CH2 + hv -> Products CALL r103(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *D19. CH2(OH)CHO + hv -> Products CALL r101(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *D20. CH3COCH3 + hv -> Products CALL r15(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) * CH3COCH2CH3 -> CH3CO + CH2CH3 CALL r119(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *D21. CH2(OH)COCH3 -> CH3CO + CH2(OH) * CH2(OH)COCH3 -> CH2(OH)CO + CH3 C CALL r112(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *D22. CHOCHO + hv -> Products CALL r13(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *D23. CH3COCHO + hv -> Products CALL r14(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) * CH3COCOCH3 + hv -> Products C CALL r102(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *D25. CH3CO(OH) + hv -> Products C CALL r138(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *D26. CH3CO(OOH) + hv -> Products CALL r123(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *D28. CH3COCO(OH) + hv -> Products C CALL r105(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) * (CH3)2NNO -> products C call r124(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) * CH3COCH2CH2CH3 + hv -> CH3CO + CH2CH2CH3 * M. Leriche added March 2018 for KETL (CACM, ReLACS2 and ReLACS3) * Uses availble Martinez data for cross section CALL r149(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) * BENZALD + hv -> phenoxy + HO2 + CO * M. Leriche added March 2018 for BALD (RACM2) * Uses data from SAPRC-07 for cross section CALL r150(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) ******** FOx Photochemistry *E12. CF2O + hv -> Products C CALL r22(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) ******** ClOx Photochemistry *F1. Cl2 + hv -> Cl + Cl C CALL r47(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F2. ClO -> Cl + O C call r125(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F3. ClOO + hv -> Products C CALL r31(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F4. OCLO -> Products C call r132(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F7. ClOOCl -> Cl + ClOO C CALL r111(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F13. HCl -> H + Cl C CALL r137(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F14. HOCl -> HO + Cl C call r130(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F15. NOCl -> NO + Cl C call r131(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F16. ClNO2 -> Cl + NO2 C call r126(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F17. ClONO -> Cl + NO2 C call r136(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F18. ClONO2 + hv -> Products C CALL r45(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F19. CCl4 + hv -> Products C CALL r20(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F20. CH3OCl + hv -> Cl + CH3O C CALL r139(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F21. CHCl3 -> Products C CALL r140(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F23. CH3Cl + hv -> Products C CALL r30(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F24. CH3CCl3 + hv -> Products C CALL r29(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F30. CCl2O + hv -> Products C CALL r19(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F32. CClFO + hv -> Products C CALL r21(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F33. CCl3F (CFC-11) + hv -> Products C CALL r26(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F34. CCl2F2 (CFC-12) + hv -> Products C CALL r27(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F36. CF2ClCFCl2 (CFC-113) + hv -> Products C CALL r23(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F37. CF2ClCF2Cl (CFC-114) + hv -> Products C CALL r24(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F38. CF3CF2Cl (CFC-115) + hv -> Products C CALL r25(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F40. CHClF2 (HCFC-22) + hv -> Products C CALL r38(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F42. CF3CHCl2 (HCFC-123) + hv -> Products C CALL r32(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F43. CF3CHFCl (HCFC-124) + hv -> Products C CALL r33(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F45. CH3CFCl2 (HCFC-141b) + hv -> Products C CALL r34(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F46. CH3CF2Cl (HCFC-142b) + hv -> Products C CALL r35(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F56. CF3CF2CHCl2 (HCFC-225ca) + hv -> Products C CALL r36(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *F57. CF2ClCF2CHFCl (HCFC-225cb) + hv -> Products C CALL r37(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) **** BrOx Photochemistry *G1. Br2 -> Br + Br C CALL r115(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *G3. BrO -> Br + O C CALL r114(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *G6. HOBr -> OH + Br C CALL r113(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *G7. BrNO -> Br + NO C call r127(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *G8. BrONO -> Br + NO2 * BrONO -> BrO + NO C call r129(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *G9. BrNO2 -> Br + NO2 C call r128(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *G10. BrONO2 + hv -> Products C CALL r46(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *G11. BrCl -> Br + Cl C call r133(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *G13. CH3Br + hv -> Products C CALL r28(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *G15. CHBr3 + hv -> Products C CALL r09(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *G25. CF2Br2 (Halon-1202) + hv -> Products C CALL r40(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *G26. CF2BrCl (Halon-1211) + hv -> Products C CALL r41(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *G27. CF3Br (Halon-1301) + hv -> Products C CALL r42(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *G35. CF2BrCF2Br (Halon-2402) + hv -> Products C CALL r43(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) **** IOx Photochemistry *H01. I2 -> I + I c CALL r146(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *H02. IO -> I + O C CALL r147(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *H05. IOH -> I + OH C CALL r148(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *H24. perfluoro n-iodo propane -> products C CALL r145(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) ******** aqueous phase (diluted solution) Photochemistry *** M. Leriche March 2018 *** Add from LaMP code (Deguillaume et al., 2004) *AQ01. H2O2(aq) -> 2OH CALL r152(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) *AQ02. NO3-(aq) -> NO2 + OH CALL r151(nw,wl,wc,nz,tlev,airden,j,sq,jlabel,tpflag,kout) **************************************************************** IF (j .GT. kj) STOP '1002' RETURN END CCC FILE vpair.f *=============================================================================* SUBROUTINE vpair(psurf, nz, z, $ con, col,kout) *-----------------------------------------------------------------------------* *= NAME: Vertial Profile of AIR *= PURPOSE: =* *= Set up an altitude profile of air molecules. Subroutine includes a =* *= shape-conserving scaling method that allows scaling of the entire =* *= profile to a given sea-level pressure. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= PSURF - REAL, surface pressure (mb) to which profile should be (I)=* *= scaled. If PSURF < 0, no scaling is done =* *= NZ - INTEGER, number of specified altitude levels in the working (I)=* *= grid =* *= outputs are on z-grid: *= Z - REAL, specified altitude working grid (km) (I)=* *= CON - REAL, air density (molec/cc) at each specified altitude (O)=* *= COL - REAL, number of air molecules per cm^2 in each specified (O)=* *= altitude layer (column vertical increment =* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) INTEGER kdata PARAMETER(kdata=150) ********* input: REAL z(kz) INTEGER nz REAL psurf * specified air profile data: INTEGER nd REAL zd(kdata), air(kdata) REAL hscale REAL cd(kdata) ********* output: * con(iz) = air density (molec cm-3) at level iz * col(iz) = column amount (molec cm-2) for layer iz REAL con(kz) REAL col(kz) * local: REAL scale REAL pold REAL pconv PARAMETER(pconv = 980.665 * 1.E-3 * 28.9644 / 6.022169E23) * other: INTEGER i REAL airlog(kz), conlog(kz) * External functions: REAL fsum EXTERNAL fsum *_______________________________________________________________________ * The objective of this subroutine is to take the input air profile and interpolate * it to the working grid, z(i = 1, nz). The desired outputs are con(i) and col(i). * Input vertical profiles can be specified in various ways. For example: * altitude vs. concentration (molecules cm-3) * altitude vs. pressure (mbar) and temperature (K) * altitude vs. column increments (molec cm-2) * The interpolation scheme will depend on the specific type of input data. * Here, the US Standard Atmosphere is given as altitude vs. concentration (also called * number density) * _________SECTION 1: Read in vertical profile of concentration WRITE(kout,*) 'air concentrations: USSA, 1976' OPEN(NEWUNIT=ilu,FILE='DATAE1/ATM/ussa.dens',STATUS='old') DO i = 1, 3 READ(UNIT=ilu,FMT=*) ENDDO nd = 1 4 CONTINUE READ(UNIT=ilu,FMT=*,END=5) zd(nd), air(nd) nd = nd+1 GOTO 4 5 CONTINUE CLOSE(UNIT=ilu) nd = nd-1 * add 1 meter to top, to avoid interpolation end-problem if z-grid is up to 120 km zd(nd) = zd(nd) + 0.001 * scale height, km, at top of atmosphere: hscale = 8.01 ********************** end data input. * ________SECTION 2: Compute column increments on standard z-grid. * For air, this is best done using logarithms of concentration. * take logs * if z-grid extends beyond available data, stop (no extrapolation allowed) * interpolate log of air(nd) onto z grid * re-exponentiate to get gridded concentrations DO i = 1, nd airlog(i) = ALOG(air(i)) ENDDO IF(z(nz) .GT. zd(nd)) STOP 'in vpair: ztop < zdata' CALL inter1(nz,z,conlog, nd,zd,airlog) DO i = 1, nz con(i) = EXP(conlog(i)) ENDDO * Find gridded column increments in z-grid: * use log intergration DO i = 1, nz-1 col(i) = 1.E5*(z(i+1)-z(i)) * (con(i+1)-con(i)) / $ ALOG(con(i+1)/con(i)) ENDDO * Add exponential tail integral at top of atmosphere: * this is folded into layer nz-1, making this layer "heavy'. * The layer nz is not used. The radiative transfer * calculation is based on nz-1 layers (not nz). col(nz-1) = col(nz-1) + 1.E5 * hscale * con(nz) col(nz) = 0. * Scale by input surface pressure: * min value = 1 molec cm-2 pold = pconv * MAX(fsum(nz-1,col),1.) IF(psurf .GT. 0.) THEN scale = psurf/pold ELSE scale = 1. ENDIF DO i = 1, nz - 1 col(i) = col(i) * scale con(i) = con(i) * scale ENDDO con(nz) = con(nz) * scale *_______________________________________________________________________ RETURN END CCC FILE vpo3.f *=============================================================================* SUBROUTINE vpo3(ipbl, zpbl, mr_pbl, $ to3new, nz, z, aircol, col, kout) *-----------------------------------------------------------------------------* *= NAME: Vertical Profiles of Ozone = vpo3 =* *= PURPOSE: =* *= Computes O3 column increments, col(i), molec cm-2 for each layer i of =* *= the working grid z(i = 1, nz). =* *= Normally, col(i) values are computed from input vertical profiles of =* *= concentrations (molec cm-3), that are then interpolated and integrated =* *= over each layer. The default example here uses the US Standard =* *= Atmosphere (1976) mid-latitude concentration profile. =* *= Users can substitute their own concentration profile, as long as =* *= appropriate adjustments are made in Section 1 to input the data, and in =* *= section 2 to interpolate to the working grid. =* *= A scale factor is provided to allow changing the total column amount, =* *= but conserving the shape of the profile. =* *= An option to insert PBL pollutants is provided =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= TO3NEW - REAL, Dobson Units, new total column amount from surface =* *= to space, to be scaled. If TO3NEW < 0, no scaling is done. =* *= NZ - INTEGER, number of specified altitude levels in the working (I)=* *= grid =* *= Z - REAL, specified altitude working grid (km) (I)=* *= AIRCOL(KZ) = REAL, air column increment (molec cm-2), provided here in =* *= case it is necessary to convert from mixing ratio units (e.g. ppb). =* *-----------------------------------------------------------------------------* IMPLICIT NONE ******** * inputs: ******** c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) *** from calling program: INTEGER nz REAL z(kz) REAL to3new REAL aircol(kz) REAL zpbl, mr_pbl INTEGER ipbl * from data file: concentration data as a function of altitude INTEGER kdata PARAMETER(kdata=150) REAL zd(kdata), xd(kdata) ******** * internal ******** INTEGER i, nd REAL hscale REAL to3old, scale REAL con(kz) REAL rfact ******** * output: ******** REAL col(kz) ******** * External functions: ******** REAL fsum EXTERNAL fsum * The objective of this subroutine is to calculate the vertical increments * in the O3 column, for each layer of the working grid z(i = 1, nz). * The input O3 profiles can be specified in different ways, and each case * will require careful consideration of the interpolation scheme. Some * examples of possible input data are: * altitude vs. O3 concentration (number density), molec cm-3 * altitude vs. O3 mixing ratio (e.g. parts per billion) relative to air * altitude vs. O3 column increments, molec cm-2, between specific altitudes. * Special caution is required with mixed inputs, e.g. ppb in boundary layer and * molec cm-3 above the boundary layer. * _________SECTION 1: Read in vertical profile of concentration * Default is US Standard Atmosphere (1976) * If a different vertical concentration profile is specified, the code * in this section (Section 1) should be replaced accordingly WRITE(kout,*) 'ozone profile: USSA, 1976' OPEN(NEWUNIT=ilu,FILE='DATAE1/ATM/ussa.ozone',STATUS='old') DO i = 1, 7 READ(UNIT=ilu,FMT=*) ENDDO nd = 39 DO i = 1, nd READ(UNIT=ilu,FMT=*) zd(i), xd(i) ENDDO CLOSE(UNIT=ilu) * Ussa data stop at 74 km. Add values up to 121 km, * assuming exponential decay from 74 km up, with scale height of * 4.5 km. hscale = 4.5 rfact = EXP(-1./hscale) 10 CONTINUE nd = nd + 1 zd(nd) = zd(nd-1) + 1. xd(nd) = xd(nd-1) * rfact IF(zd(nd) .GE. 121.) GO TO 19 GO TO 10 19 CONTINUE *********** end data input. * ________SECTION 2: Compute column increments on standard z-grid. * linear interpolation CALL inter1(nz,z,con, nd,zd,xd) * compute column increments DO i = 1, nz-1 col(i) = 0.5 * (con(i) + con(i+1)) * (z(i+1) - z(i)) * 1.E5 ENDDO * Add exponential tail integral at top of atmosphere: * this is folded into layer nz-1, making this layer "heavy'. * The layer nz is not used. The radiative transfer * calculation is based on nz-1 layers (not nz). col(nz-1) = col(nz-1) + 1.E5 * hscale * con(nz) ***** Scaling to new total ozone * to3old = total o3 column, in Dobson Units, old value * to3new = total o3 column, in Dobson Units, new value * (1 DU = 2.687e16) * If to3new is not negative, scale to new total column value, to3new : * (to3new = 0. is a possible input, to see effect of zero ozone) IF (to3new .GT. nzero) THEN to3old = fsum(nz-1, col)/2.687e16 IF(to3old .LT. pzero) STOP 'in vpo3: to3old is too small' scale = to3new/to3old DO i = 1, nz-1 col(i) = col(i) * scale con(i) = con(i) * scale ENDDO con(nz) = con(nz) * scale ENDIF *! overwrite column increments for specified pbl height * use mixing ratio in pbl IF(ipbl .GT. 0) THEN write(*,*) 'pbl O3 = ', mr_pbl, ' ppb' DO i = 1, nz-1 IF (i .LE. ipbl) THEN col(i) = mr_pbl*1.E-9 * aircol(i) ENDIF ENDDO ENDIF *_______________________________________________________________________ RETURN END CCC FILE vptmp.f *=============================================================================* SUBROUTINE vptmp(nz,z,tlev,tlay,kout) *-----------------------------------------------------------------------------* * NAME: Vertical Profile of TeMPerature *= PURPOSE: =* *= Set up an altitude profile of temperatures. Temperature values are =* *= needed to compute some cross sections and quantum yields. Distinguish =* *= between temperature at levels and layers. =* *-----------------------------------------------------------------------------* *= PARAMETERS: =* *= NZ - INTEGER, number of specified altitude levels in the working (I)=* *= grid =* *= Z - REAL, specified altitude working grid (km) (I)=* *= TLEV - REAL, temperature (K) at each specified altitude level (O)=* *= TLAY - REAL, temperature (K) at each specified altitude layer (O)=* *-----------------------------------------------------------------------------* IMPLICIT NONE c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) INTEGER kdata PARAMETER(kdata=150) * input: (altitude working grid) REAL z(kz) INTEGER nz * output: REAL tlev(kz), tlay(kz) * local: REAL zd(kdata), td(kdata) INTEGER i, nd *_______________________________________________________________________ * read in temperature profile WRITE(kout,*) 'air temperature: USSA, 1976' OPEN(NEWUNIT=ilu,FILE='DATAE1/ATM/ussa.temp',STATUS='old') DO i = 1, 3 READ(UNIT=ilu,FMT=*) ENDDO nd = 1 4 CONTINUE READ(UNIT=ilu,FMT=*,END=5) zd(nd), td(nd) nd = nd+1 GOTO 4 5 CONTINUE CLOSE(UNIT=ilu) nd = nd-1 * use constant temperature to infinity: zd(nd) = 1.E10 * alternative input temperature data could include, e.g., a read file here: *********** *********** end data input. * interpolate onto z-grid CALL inter1(nz,z,tlev,nd,zd,td) * compute layer-averages DO 20, i = 1, nz - 1 tlay(i) = (tlev(i+1) + tlev(i))/2. 20 CONTINUE tlay(nz) = tlay(nz-1) *_______________________________________________________________________ RETURN END CCC FILE wshift.f This file contains the subroutine: * wshift * the function: * refrac *_______________________________________________________________________ SUBROUTINE wshift(mrefr, n, w, airden, kout) * Shift wavelength scale between air and vacuum. * if mrefr = 1, shift input waveelengths in air to vacuum. * if mrefr = -1, shift input wavelengths from vacuum to air * if any other number, don't shift IMPLICIT none c INCLUDE 'params' * BROADLY USED PARAMETERS: *_________________________________________________ * i/o file unit numbers INTEGER :: ilu INTEGER kout * output * PARAMETER(kout=6) *_________________________________________________ * altitude, wavelength, time (or solar zenith angle) grids INTEGER kz, kw * altitude PARAMETER(kz=151) * wavelength PARAMETER(kw=157) *_________________________________________________ * number of weighting functions INTEGER kj * wavelength and altitude dependent PARAMETER(kj=90) * delta for adding points at beginning or end of data grids REAL deltax PARAMETER (deltax = 1.E-5) * some constants... * pi: REAL pi PARAMETER(pi=3.1415926535898) * radius of the earth, km: REAL radius PARAMETER(radius=6.371E+3) * Planck constant x speed of light, J m REAL hc PARAMETER(hc = 6.626068E-34 * 2.99792458E8) * largest number of the machine: REAL largest PARAMETER(largest=1.E+36) * small numbers (positive and negative) REAL pzero, nzero PARAMETER(pzero = +10./largest) PARAMETER(nzero = -10./largest) * machine precision REAL precis PARAMETER(precis = 1.e-7) * inputs INTEGER mrefr, n REAL w(n), airden * output = modified w(n) * internal INTEGER i REAL refrac EXTERNAL refrac *_______________________________________________________________________ IF(mrefr .EQ. 1) THEN DO i = 1, n w(i) = w(i) * refrac(w(i),airden) ENDDO ELSEIF(mrefr .EQ. -1) THEN DO i = 1, n w(i) = w(i) / refrac(w(i),airden) ENDDO ENDIF END *_______________________________________________________________________ *_______________________________________________________________________ FUNCTION refrac(w,airden) IMPLICIT NONE * input vacuum wavelength, nm and air density, molec cm-3 REAL w, airden * output refractive index for standard air * (dry air at 15 deg. C, 101.325 kPa, 0.03% CO2) REAL refrac * internal REAL sig, dum * from CRC Handbook, originally from Edlen, B., Metrologia, 2, 71, 1966. * valid from 200 nm to 2000 nm * beyond this range, use constant value sig = 1.E3/w IF (w .LT. 200.) sig = 1.E3/200. IF (w .GT. 2000.) sig = 1.E3/2000. dum = 8342.13 + 2406030./(130. - sig*sig) + $ 15997./(38.9 - sig*sig) * adjust to local air density dum = dum * airden/(2.69e19 * 273.15/288.15) * index of refraction: refrac = 1. + 1.E-8 * dum RETURN END *======= END of TUV 5.3.1 =======*