diff --git a/.gitignore b/.gitignore index 00cec10..6a87b70 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ # from compiler: *.mod *.o +*.exe # results from ci-tests: /ci-tests/**/*.m @@ -67,5 +68,5 @@ docs/build/* # Other files/dirs to exclude *.pdf -/examples/mcm/__pycache__ +/examples/mcm*/__pycache__ diff --git a/CHANGELOG.md b/CHANGELOG.md index e4c5ef1..6244891 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,9 +9,18 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] - TBD +### Added +- Added new inline key `F90_RCONST_USE` in `src/gdata.h` and `src/scanner.c` +- Added documentation about `F90_RCONST_USE` for ReadTheDocs + ### Changed - Updated `Update_RCONST` to use `Y` instead of `C` to account for updated variable species concentrations - Updated C-I tests to print the compiler versions that are used +- Updated routine `GenerateUpdateRconst` to manually write the `SUBROUTINE` and `END SUBROUTINE` lines (F90 only) +- Updated routine `GenerateUpdateRconst` to inline code from `#INLINE F90_RCONST_USE` before any other F90 variable declarations or statements +- Updated `.gitignore` to ignore all executable files +- Changed `Begin INLINED RCONST - F90 USE STATEMENTS` to `Begin inlined code from F90_RCONST_USE` in `src/gen.c` +- Changed `Begin INLINED RCONST` to `Begin inlined code from F90_RCONST` in `src/gen.c` ### Fixed - Added `char* rootFileName` to functions and function prototypes for `Use_C`, `Use_F`, `Use_F90`, `Use_MATLAB`, and `Generate` diff --git a/docs/source/using_kpp/04_input_for_kpp.rst b/docs/source/using_kpp/04_input_for_kpp.rst index 92502a4..01a4559 100644 --- a/docs/source/using_kpp/04_input_for_kpp.rst +++ b/docs/source/using_kpp/04_input_for_kpp.rst @@ -790,26 +790,28 @@ by :code:`C`, or :code:`matlab`, respectively. .. table:: KPP inlined types :align: center - +-----------------+-------------------+---------------------+---------------------+ - | Inline_type | File | Placement | Usage | - +=================+===================+=====================+=====================+ - | **F90_DATA** | :ref:`Monitor` | specification | (obsolete) | - | | | section | | - +-----------------+-------------------+---------------------+---------------------+ - | **F90_GLOBAL** | :ref:`Global` | specification | global variables | - | | | section | | - +-----------------+-------------------+---------------------+---------------------+ - | **F90_INIT** | :ref:`Initialize` | subroutine | integration | - | | | | parameters | - +-----------------+-------------------+---------------------+---------------------+ - | **F90_RATES** | :ref:`Rates` | executable section | rate law functions | - +-----------------+-------------------+---------------------+---------------------+ - | **F90_RCONST** | :ref:`Rates` | subroutine | statements and | - | | | | definitions of rate | - | | | | coefficients | - +-----------------+-------------------+---------------------+---------------------+ - | **F90_UTIL** | :ref:`Util` | executable section | utility functions | - +-----------------+-------------------+---------------------+---------------------+ + +--------------------+-------------------+---------------------+---------------------+ + | Inline_type | File | Placement | Usage | + +====================+===================+=====================+=====================+ + | **F90_DATA** | :ref:`Monitor` | specification | (obsolete) | + | | | section | | + +--------------------+-------------------+---------------------+---------------------+ + | **F90_GLOBAL** | :ref:`Global` | specification | global variables | + | | | section | | + +--------------------+-------------------+---------------------+---------------------+ + | **F90_INIT** | :ref:`Initialize` | subroutine | integration | + | | | | parameters | + +--------------------+-------------------+---------------------+---------------------+ + | **F90_RATES** | :ref:`Rates` | executable section | rate law functions | + +--------------------+-------------------+---------------------+---------------------+ + | **F90_RCONST** | :ref:`Rates` | subroutine | rate coefficient | + | | | | definitions | + +--------------------+-------------------+---------------------+---------------------+ + | **F90_RCONST_USE** | :ref:`Rates` | subroutine | rate coefficient | + | | | | definitions | + +--------------------+-------------------+---------------------+---------------------+ + | **F90_UTIL** | :ref:`Util` | executable section | utility functions | + +--------------------+-------------------+---------------------+---------------------+ .. _f90-data: @@ -909,29 +911,38 @@ F90_RCONST ---------- This inline type can be used to define time-dependent values of rate -coefficients. You may inline :code:`USE` statements that reference -modules where rate coefficients are computed, e.g.: +coefficients. You may inline variables directly, e.g.: .. code-block:: fortran #INLINE F90_RCONST - USE MyRateFunctionModule + k_DMS_OH = 1.E-9*EXP(5820./temp)*C(ind_O2)/ & + (1.E30+5.*EXP(6280./temp)*C(ind_O2)) #ENDINLINE -or define variables directly, e.g.: +The inlined code will be placed directly into the subroutines +:code:`UPDATE_RCONST` and :code:`UPDATE_PHOTO` in the :ref:`Rates` file. + +.. _f90-rconst-use: + +F90_RCONST_USE +-------------- + +Similar to :ref:`f90-rconst`, but allows you to inline Fortran-90 +:code:`USE` statements referencing modules where rate coefficients are +computed, such as: .. code-block:: fortran #INLINE F90_RCONST - k_DMS_OH = 1.E-9*EXP(5820./temp)*C(ind_O2)/ & - (1.E30+5.*EXP(6280./temp)*C(ind_O2)) + USE MyRateFunctionModule #ENDINLINE - -Note that the :code:`USE` statements must precede any variable -definitions. - + The inlined code will be placed directly into the subroutines -:code:`UPDATE_RCONST` and :code:`UPDATE_PHOTO` in the :ref:`Rates` file. +:code:`UPDATE_RCONST` in the :ref:`Rates` file. :code:`USE` +statements will be placed before Fortran variable definitions and +executable statements, as is required by the Fortran-90 language +standard. .. _f90-util: @@ -1078,7 +1089,7 @@ List of symbols replaced by the substitution preprocessor +--------------------------+-------------------------------+----------------------------+ .. _icntrl-rcntrl: - + ================================================================= Controlling the Integrator with :code:`ICNTRL` and :code:`RCNTRL` ================================================================= @@ -1226,13 +1237,13 @@ ICNTRL g.: .. code-block:: console - + HSO3m + HSO5m + Hp = 2 HSO4m + Hp : k_aqueous( C(ind_Hp) ); - + This ensures that the concentration :code:`C(ind_Hp)` at the specific integration time is used when the reaction rate coefficient is updated within the integrator. - + .. option:: ICNTRL(16) Treatment of negative concentrations: diff --git a/src/gdata.h b/src/gdata.h index 333412b..435337b 100644 --- a/src/gdata.h +++ b/src/gdata.h @@ -92,11 +92,11 @@ enum krtypes { NUMBER, EXPRESION, PHOTO }; enum table_modes { F_TEXT, FC_TEXT, C_TEXT, S_TEXT }; enum lang { NO_LANG, C_LANG, F77_LANG, F90_LANG, MATLAB_LANG }; enum inl_code { - F77_GLOBAL, F77_INIT, F77_DATA, F77_UTIL, F77_RATES, - F77_RCONST, F90_GLOBAL, F90_INIT, F90_DATA, F90_UTIL, - F90_RATES, F90_RCONST, C_GLOBAL, C_INIT, C_DATA, - C_UTIL, C_RATES, C_RCONST, MATLAB_GLOBAL, MATLAB_INIT, - MATLAB_DATA, MATLAB_UTIL, MATLAB_RATES, MATLAB_RCONST, + F77_GLOBAL, F77_INIT, F77_DATA, F77_UTIL, F77_RATES, + F77_RCONST, F90_GLOBAL, F90_INIT, F90_DATA, F90_UTIL, + F90_RATES, F90_RCONST, F90_RCONST_USE, C_GLOBAL, C_INIT, + C_DATA, C_UTIL, C_RATES, C_RCONST, MATLAB_GLOBAL, + MATLAB_INIT, MATLAB_DATA, MATLAB_UTIL, MATLAB_RATES, MATLAB_RCONST, INLINE_OPT }; diff --git a/src/gen.c b/src/gen.c index 8b728df..98630c3 100644 --- a/src/gen.c +++ b/src/gen.c @@ -2167,21 +2167,57 @@ void GenerateUpdateRconst() { int i; int UPDATE_RCONST; -int YIN,Y; +int YIN, Y; UseFile( rateFile ); if (useLang==F90_LANG) { - // F90: Declare function with optional YIN argument and local Y variable. + // + // SPECIAL HANDLING FOR F90: + // ------------------------- + // Manually write the "SUBROUTINE RCONST ( YIN )" line instead of + // using the FunctionBegin( UPDATE_RCONST ). This will allow us + // to add any inlined F90 use statements immediately afterwards. + // Recall that F90 "USE" statements must precede variable + // declarations or any other executable statements, or else a + // compilation error will be generated. + // + // -- Bob Yantosca (19 Dec 2024) + // + bprintf("SUBROUTINE Update_RCONST ( YIN )"); + NewLines(2); + + // Inline USE statements right after the subroutine declaration + WriteComment("Begin inlined code from F90_RCONST_USE"); + NewLines(1); + bprintf( InlineCode[ F90_RCONST_USE ].code ); + FlushBuf(); + NewLines(1); + WriteComment("End inlined code from F90_RCONST_USE"); + NewLines(1); + + // Declare optional YIN argument YIN = DefvElmO( "YIN", real, -NVAR, "Optional input concentrations of variable species" ); - UPDATE_RCONST = DefFnc( "Update_RCONST", 1, "function to update rate constants"); + Declare(YIN); + NewLines(1); - FunctionBegin( UPDATE_RCONST, YIN ); + // Declare local Y variable Y = DefvElm( "Y", real, -NSPEC, "Concentrations of species (local)" ); Declare(Y); NewLines(1); + + // Copy values of YIN to Y if YIN is present + WriteComment("Ensure local Y array is filled with variable and constant concentrations"); + bprintf(" Y(1:NSPEC) = C(1:NSPEC)\n"); + NewLines(1); + WriteComment("Update local Y array if variable concentrations are provided"); + bprintf(" if (present(YIN)) Y(1:NVAR) = YIN(1:NVAR)\n"); + NewLines(1); + } else { + // // For other languages, declare function w/o any arguments + // UPDATE_RCONST = DefFnc( "Update_RCONST", 0, "function to update rate constants"); FunctionBegin( UPDATE_RCONST ); } @@ -2189,23 +2225,14 @@ int YIN,Y; F77_Inline(" INCLUDE '%s_Global.h'", rootFileName); MATLAB_Inline("global SUN TEMP RCONST"); - switch( useLang ){ - case F90_LANG: - WriteComment("Ensure local Y array is filled with variable and constant concentrations"); - bprintf(" Y(1:NSPEC) = C(1:NSPEC)\n"); - NewLines(1); - WriteComment("Update local Y array if variable concentrations are provided"); - bprintf(" if (present(YIN)) Y(1:NVAR) = YIN(1:NVAR)\n"); - break; - } - if ( useLang==F77_LANG ) IncludeCode( "%s/util/UserRateLaws_FcnHeader", Home ); NewLines(1); + // Inline code from {C,F77,F90_MATLAB}_RCONST inline keys NewLines(1); - WriteComment("Begin INLINED RCONST"); + WriteComment("Begin inlined code from F90_RCONST"); NewLines(1); switch( useLang ) { @@ -2221,7 +2248,7 @@ int YIN,Y; FlushBuf(); NewLines(1); - WriteComment("End INLINED RCONST"); + WriteComment("End inlined code from F90_RCONST"); NewLines(1); for( i = 0; i < EqnNr; i++) { @@ -2242,9 +2269,22 @@ int YIN,Y; } MATLAB_Inline(" RCONST = RCONST(:);"); - - FunctionEnd( UPDATE_RCONST ); - FreeVariable( UPDATE_RCONST ); + // + // SPECIAL HANDLING FOR F90: + // ------------------------- + // Manually write the "END SUBROUTINE UPDATE_RCONST" line when + // generating F90 output. But if generating C, F77, MatLab output, + // then close the UPDATE_RCONST routine as we normally would. + // -- Bob Yantosca (19 Dec 2024) + // + if (useLang == F90_LANG) { + NewLines(1); + bprintf("END SUBROUTINE UPDATE_RCONST"); + NewLines(1); + } else { + FunctionEnd( UPDATE_RCONST ); + FreeVariable( UPDATE_RCONST ); + } } diff --git a/src/scanner.c b/src/scanner.c index abeaf52..06ca034 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -79,6 +79,7 @@ INLINE_KEY InlineKeys[] = { { F77_GLOBAL, APPEND, "F77_GLOBAL" }, { F90_UTIL, APPEND, "F90_UTIL" }, { F90_RATES, APPEND, "F90_RATES" }, { F90_RCONST, APPEND, "F90_RCONST" }, + { F90_RCONST_USE, APPEND, "F90_RCONST_USE"}, { C_GLOBAL, APPEND, "C_GLOBAL" }, { C_INIT, APPEND, "C_INIT" }, { C_DATA, APPEND, "C_DATA" },