diff --git a/doc/arkode/guide/source/ARKodeButcherTable.rst b/doc/arkode/guide/source/ARKodeButcherTable.rst index 916641678b..969e1bc23a 100644 --- a/doc/arkode/guide/source/ARKodeButcherTable.rst +++ b/doc/arkode/guide/source/ARKodeButcherTable.rst @@ -83,10 +83,14 @@ ARKodeButcherTable functions +--------------------------------------------------+------------------------------------------------------------+ | :c:func:`ARKodeButcherTable_LoadERKByName()` | Retrieve a given explicit Butcher table by its unique name | +--------------------------------------------------+------------------------------------------------------------+ + | :c:func:`ARKodeButcherTable_ERKIDToName()` | Convert an explicit Butcher table ID to its name | + +--------------------------------------------------+------------------------------------------------------------+ | :c:func:`ARKodeButcherTable_LoadDIRK()` | Retrieve a given implicit Butcher table by its unique ID | +--------------------------------------------------+------------------------------------------------------------+ | :c:func:`ARKodeButcherTable_LoadDIRKByName()` | Retrieve a given implicit Butcher table by its unique name | +--------------------------------------------------+------------------------------------------------------------+ + | :c:func:`ARKodeButcherTable_DIRKIDToName()` | Convert an implicit Butcher table ID to its name | + +--------------------------------------------------+------------------------------------------------------------+ | :c:func:`ARKodeButcherTable_Alloc()` | Allocate an empty Butcher table | +--------------------------------------------------+------------------------------------------------------------+ | :c:func:`ARKodeButcherTable_Create()` | Create a new Butcher table | @@ -138,6 +142,21 @@ ARKodeButcherTable functions **Notes:** This function is case sensitive. +.. c:function:: const char* ARKodeButcherTable_ERKIDToName(ARKODE_ERKTableID emethod) + + Converts a specified explicit Butcher table ID to a string of the same name. + The prototype for this function, as well as the integer names for each + provided method, are defined in the header file + ``arkode/arkode_butcher_erk.h``. For further information on these tables and + their corresponding identifiers, see :numref:`Butcher`. + + **Arguments:** + * *emethod* -- integer input specifying the given Butcher table. + + **Return value:** + * The name associated with *emethod*. + * ``NULL`` pointer if *emethod* was invalid. + .. c:function:: ARKodeButcherTable ARKodeButcherTable_LoadDIRK(ARKODE_DIRKTableID imethod) Retrieves a specified diagonally-implicit Butcher table. The prototype for @@ -172,6 +191,22 @@ ARKodeButcherTable functions This function is case sensitive. +.. c:function:: const char* ARKodeButcherTable_DIRKIDToName(ARKODE_DIRKTableID imethod) + + Converts a specified diagonally-implicit Butcher table ID to a string of the + same name. The prototype for this function, as well as the integer names for + each provided method, are defined in the header file + ``arkode/arkode_butcher_dirk.h``. For further information on these tables + and their corresponding identifiers, see :numref:`Butcher`. + + **Arguments:** + * *imethod* -- integer input specifying the given Butcher table. + + **Return value:** + * The name associated with *imethod*. + * ``NULL`` pointer if *imethod* was invalid. + + .. c:function:: ARKodeButcherTable ARKodeButcherTable_Alloc(int stages, sunbooleantype embedded) Allocates an empty Butcher table. diff --git a/include/arkode/arkode_butcher_dirk.h b/include/arkode/arkode_butcher_dirk.h index ffa4908c91..c89ea0594f 100644 --- a/include/arkode/arkode_butcher_dirk.h +++ b/include/arkode/arkode_butcher_dirk.h @@ -65,6 +65,9 @@ ARKodeButcherTable_LoadDIRK(ARKODE_DIRKTableID imethod); SUNDIALS_EXPORT ARKodeButcherTable ARKodeButcherTable_LoadDIRKByName(const char* imethod); +SUNDIALS_EXPORT const char* ARKodeButcherTable_DIRKIDToName( + ARKODE_DIRKTableID imethod); + #ifdef __cplusplus } #endif diff --git a/include/arkode/arkode_butcher_erk.h b/include/arkode/arkode_butcher_erk.h index 764b67bbfe..c6c0373510 100644 --- a/include/arkode/arkode_butcher_erk.h +++ b/include/arkode/arkode_butcher_erk.h @@ -62,6 +62,8 @@ ARKodeButcherTable_LoadERK(ARKODE_ERKTableID emethod); SUNDIALS_EXPORT ARKodeButcherTable ARKodeButcherTable_LoadERKByName(const char* emethod); +SUNDIALS_EXPORT const char* ARKodeButcherTable_ERKIDToName(ARKODE_ERKTableID emethod); + #ifdef __cplusplus } #endif diff --git a/src/arkode/arkode_butcher_dirk.c b/src/arkode/arkode_butcher_dirk.c index 54026e7ae2..ee3001a2c8 100644 --- a/src/arkode/arkode_butcher_dirk.c +++ b/src/arkode/arkode_butcher_dirk.c @@ -54,6 +54,28 @@ ARKodeButcherTable ARKodeButcherTable_LoadDIRKByName(const char* imethod) return ARKodeButcherTable_LoadDIRK(arkButcherTableDIRKNameToID(imethod)); } +/*--------------------------------------------------------------- + Returns the string name for a pre-set DIRK method by its ID. + + Input: imethod -- integer key for the desired method + ---------------------------------------------------------------*/ +const char* ARKodeButcherTable_DIRKIDToName(ARKODE_DIRKTableID imethod) +{ + /* Use X-macro to test each method name */ + switch (imethod) + { +#define ARK_BUTCHER_TABLE(name, coeff) \ + case name: return #name; +#include "arkode_butcher_dirk.def" +#undef ARK_BUTCHER_TABLE + + default: + arkProcessError(NULL, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "Unknown Butcher table"); + return NULL; + } +} + /*--------------------------------------------------------------- Returns Butcher table ID for pre-set DIRK methods. diff --git a/src/arkode/arkode_butcher_erk.c b/src/arkode/arkode_butcher_erk.c index e15aa6b8b0..10cebbfdf4 100644 --- a/src/arkode/arkode_butcher_erk.c +++ b/src/arkode/arkode_butcher_erk.c @@ -25,7 +25,7 @@ /*--------------------------------------------------------------- Returns Butcher table structure for pre-set Runge Kutta methods. - Input: emthod -- integer key for the desired method + Input: emethod -- integer key for the desired method ---------------------------------------------------------------*/ ARKodeButcherTable ARKodeButcherTable_LoadERK(ARKODE_ERKTableID emethod) { @@ -54,6 +54,28 @@ ARKodeButcherTable ARKodeButcherTable_LoadERKByName(const char* emethod) return ARKodeButcherTable_LoadERK(arkButcherTableERKNameToID(emethod)); } +/*--------------------------------------------------------------- + Returns the string name for a pre-set Runge Kutta method by its ID. + + Input: emethod -- integer key for the desired method + ---------------------------------------------------------------*/ +const char* ARKodeButcherTable_ERKIDToName(ARKODE_ERKTableID emethod) +{ + /* Use X-macro to test each method name */ + switch (emethod) + { +#define ARK_BUTCHER_TABLE(name, coeff) \ + case name: return #name; +#include "arkode_butcher_erk.def" +#undef ARK_BUTCHER_TABLE + + default: + arkProcessError(NULL, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "Unknown Butcher table"); + return NULL; + } +} + /*--------------------------------------------------------------- Returns Butcher table ID for pre-set Runge Kutta methods. diff --git a/test/answers b/test/answers index 073b119355..b622a192d5 160000 --- a/test/answers +++ b/test/answers @@ -1 +1 @@ -Subproject commit 073b119355058ac88a2e4abc87acfb007bc211f6 +Subproject commit b622a192d52f7982bb6485f0cba5ffd3fc24e622 diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_butcher.cpp b/test/unit_tests/arkode/CXX_serial/ark_test_butcher.cpp index c789fec715..a8013ad472 100644 --- a/test/unit_tests/arkode/CXX_serial/ark_test_butcher.cpp +++ b/test/unit_tests/arkode/CXX_serial/ark_test_butcher.cpp @@ -21,76 +21,45 @@ #include #include #include -#include #include #include +#include "arkode/arkode_impl.h" + +struct ARK_Table +{ + const char* const name; + const char* const erk_table; + const char* const dirk_table; +}; + // Main Program int main() { - // set vectors of individual tables to test - std::vector Tables_ERK = - {"ARKODE_HEUN_EULER_2_1_2", "ARKODE_ARK2_ERK_3_1_2", - "ARKODE_BOGACKI_SHAMPINE_4_2_3", "ARKODE_ARK324L2SA_ERK_4_2_3", - "ARKODE_ZONNEVELD_5_3_4", "ARKODE_ARK436L2SA_ERK_6_3_4", - "ARKODE_SAYFY_ABURUB_6_3_4", "ARKODE_CASH_KARP_6_4_5", - "ARKODE_FEHLBERG_6_4_5", "ARKODE_DORMAND_PRINCE_7_4_5", - "ARKODE_ARK548L2SA_ERK_8_4_5", "ARKODE_VERNER_8_5_6", - "ARKODE_FEHLBERG_13_7_8", "ARKODE_ARK437L2SA_ERK_7_3_4", - "ARKODE_ARK548L2SAb_ERK_8_4_5", "ARKODE_SOFRONIOU_SPALETTA_5_3_4", - "ARKODE_SHU_OSHER_3_2_3", "ARKODE_VERNER_9_5_6", - "ARKODE_VERNER_10_6_7", "ARKODE_VERNER_13_7_8", - "ARKODE_VERNER_16_8_9"}; - std::vector Tables_DIRK = {"ARKODE_SDIRK_2_1_2", - "ARKODE_ARK2_DIRK_3_1_2", - "ARKODE_BILLINGTON_3_3_2", - "ARKODE_TRBDF2_3_3_2", - "ARKODE_KVAERNO_4_2_3", - "ARKODE_ARK324L2SA_DIRK_4_2_3", - "ARKODE_CASH_5_2_4", - "ARKODE_CASH_5_3_4", - "ARKODE_SDIRK_5_3_4", - "ARKODE_KVAERNO_5_3_4", - "ARKODE_ARK436L2SA_DIRK_6_3_4", - "ARKODE_KVAERNO_7_4_5", - "ARKODE_ARK548L2SA_DIRK_8_4_5", - "ARKODE_ARK437L2SA_DIRK_7_3_4", - "ARKODE_ARK548L2SAb_DIRK_8_4_5", - "ARKODE_ESDIRK324L2SA_4_2_3", - "ARKODE_ESDIRK325L2SA_5_2_3", - "ARKODE_ESDIRK32I5L2SA_5_2_3", - "ARKODE_ESDIRK436L2SA_6_3_4", - "ARKODE_ESDIRK43I6L2SA_6_3_4", - "ARKODE_QESDIRK436L2SA_6_3_4", - "ARKODE_ESDIRK437L2SA_7_3_4", - "ARKODE_ESDIRK547L2SA_7_4_5", - "ARKODE_ESDIRK547L2SA2_7_4_5"}; - std::vector Tables_ARK_ERK = {ARKODE_ARK2_ERK_3_1_2, - ARKODE_ARK324L2SA_ERK_4_2_3, - ARKODE_ARK436L2SA_ERK_6_3_4, - ARKODE_ARK437L2SA_ERK_7_3_4, - ARKODE_ARK548L2SA_ERK_8_4_5, - ARKODE_ARK548L2SAb_ERK_8_4_5}; - std::vector Tables_ARK_DIRK = - {ARKODE_ARK2_DIRK_3_1_2, ARKODE_ARK324L2SA_DIRK_4_2_3, - ARKODE_ARK436L2SA_DIRK_6_3_4, ARKODE_ARK437L2SA_DIRK_7_3_4, - ARKODE_ARK548L2SA_DIRK_8_4_5, ARKODE_ARK548L2SAb_DIRK_8_4_5}; - std::vector STables_ARK = {"ARKODE_ARK2_3_1_2", - "ARKODE_ARK324L2SA_4_2_3", - "ARKODE_ARK436L2SA_6_3_4", - "ARKODE_ARK437L2SA_7_3_4", - "ARKODE_ARK548L2SA_8_4_5", - "ARKODE_ARK548L2SAb_8_4_5"}; - int numfails = 0; + std::vector ark_tables = + {{"ARKODE_ARK2_3_1_2", "ARKODE_ARK2_ERK_3_1_2", "ARKODE_ARK2_DIRK_3_1_2"}, + {"ARKODE_ARK324L2SA_4_2_3", "ARKODE_ARK324L2SA_ERK_4_2_3", + "ARKODE_ARK324L2SA_DIRK_4_2_3"}, + {"ARKODE_ARK436L2SA_6_3_4", "ARKODE_ARK436L2SA_ERK_6_3_4", + "ARKODE_ARK436L2SA_DIRK_6_3_4"}, + {"ARKODE_ARK437L2SA_7_3_4", "ARKODE_ARK437L2SA_ERK_7_3_4", + "ARKODE_ARK437L2SA_DIRK_7_3_4"}, + {"ARKODE_ARK548L2SA_8_4_5", "ARKODE_ARK548L2SA_ERK_8_4_5", + "ARKODE_ARK548L2SA_DIRK_8_4_5"}, + {"ARKODE_ARK548L2SAb_8_4_5", "ARKODE_ARK548L2SAb_ERK_8_4_5", + "ARKODE_ARK548L2SAb_DIRK_8_4_5"}}; + + int numfails = 0; // loop over individual ERK tables std::cout << "\nTesting individual ERK methods:\n\n"; - for (std::string table : Tables_ERK) + for (int i = ARKODE_MIN_ERK_NUM; i <= ARKODE_MAX_ERK_NUM; i++) { - std::cout << "Testing method " << table << ":"; + ARKODE_ERKTableID id = static_cast(i); + std::cout << "Testing method " << ARKodeButcherTable_ERKIDToName(id) << ":"; // load Butcher table - ARKodeButcherTable B = ARKodeButcherTable_LoadERKByName(table.c_str()); + ARKodeButcherTable B = ARKodeButcherTable_LoadERK(id); if (B == NULL) { std::cout << " error retrieving table, aborting\n"; @@ -123,12 +92,13 @@ int main() // loop over individual DIRK tables std::cout << "\nTesting individual DIRK methods:\n\n"; - for (std::string table : Tables_DIRK) + for (int i = ARKODE_MIN_DIRK_NUM; i <= ARKODE_MAX_DIRK_NUM; i++) { - std::cout << "Testing method " << table << ":"; + ARKODE_DIRKTableID id = static_cast(i); + std::cout << "Testing method " << ARKodeButcherTable_DIRKIDToName(id) << ":"; // load Butcher table - ARKodeButcherTable B = ARKodeButcherTable_LoadDIRKByName(table.c_str()); + ARKodeButcherTable B = ARKodeButcherTable_LoadDIRK(id); if (B == NULL) { std::cout << " error retrieving table, aborting\n"; @@ -161,18 +131,19 @@ int main() // loop over ARK pairs std::cout << "\nTesting ARK pairs:\n\n"; - for (size_t i = 0; i < Tables_ARK_ERK.size(); i++) + for (ARK_Table& ark_table : ark_tables) { - std::cout << "Testing method " << STables_ARK[i] << ":"; + std::cout << "Testing method " << ark_table.name << ":"; // load Butcher tables - ARKodeButcherTable Be = ARKodeButcherTable_LoadERK(Tables_ARK_ERK[i]); + ARKodeButcherTable Be = ARKodeButcherTable_LoadERKByName(ark_table.erk_table); if (Be == NULL) { std::cout << " error retrieving explicit table, aborting\n"; return 1; } - ARKodeButcherTable Bi = ARKodeButcherTable_LoadDIRK(Tables_ARK_DIRK[i]); + ARKodeButcherTable Bi = + ARKodeButcherTable_LoadDIRKByName(ark_table.dirk_table); if (Bi == NULL) { std::cout << " error retrieving implicit table, aborting"; diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_butcher.out b/test/unit_tests/arkode/CXX_serial/ark_test_butcher.out index b7c11bcecf..559c92b3ae 100644 --- a/test/unit_tests/arkode/CXX_serial/ark_test_butcher.out +++ b/test/unit_tests/arkode/CXX_serial/ark_test_butcher.out @@ -2,7 +2,6 @@ Testing individual ERK methods: Testing method ARKODE_HEUN_EULER_2_1_2: table matches predicted method/embedding orders of 2/1 -Testing method ARKODE_ARK2_ERK_3_1_2: table matches predicted method/embedding orders of 2/1 Testing method ARKODE_BOGACKI_SHAMPINE_4_2_3: table matches predicted method/embedding orders of 3/2 Testing method ARKODE_ARK324L2SA_ERK_4_2_3: table matches predicted method/embedding orders of 3/2 Testing method ARKODE_ZONNEVELD_5_3_4: table matches predicted method/embedding orders of 4/3 @@ -20,8 +19,10 @@ ARKodeButcherTable_CheckOrder: embedding order >= 6; reverting to simplifying assumptions embedding order = 6 +Testing method ARKODE_KNOTH_WOLKE_3_3: table matches predicted method/embedding orders of 3/0 Testing method ARKODE_ARK437L2SA_ERK_7_3_4: table matches predicted method/embedding orders of 4/3 Testing method ARKODE_ARK548L2SAb_ERK_8_4_5: table matches predicted method/embedding orders of 5/4 +Testing method ARKODE_ARK2_ERK_3_1_2: table matches predicted method/embedding orders of 2/1 Testing method ARKODE_SOFRONIOU_SPALETTA_5_3_4: table matches predicted method/embedding orders of 4/3 Testing method ARKODE_SHU_OSHER_3_2_3: table matches predicted method/embedding orders of 3/2 Testing method ARKODE_VERNER_9_5_6: table matches predicted method/embedding orders of 6/5 @@ -46,11 +47,13 @@ ARKodeButcherTable_CheckOrder: embedding order >= 6; reverting to simplifying assumptions embedding order = 6 +Testing method ARKODE_FORWARD_EULER_1_1: table matches predicted method/embedding orders of 1/0 +Testing method ARKODE_RALSTON_EULER_2_1_2: table matches predicted method/embedding orders of 2/1 +Testing method ARKODE_EXPLICIT_MIDPOINT_EULER_2_1_2: table matches predicted method/embedding orders of 2/1 Testing individual DIRK methods: Testing method ARKODE_SDIRK_2_1_2: table matches predicted method/embedding orders of 2/1 -Testing method ARKODE_ARK2_DIRK_3_1_2: table matches predicted method/embedding orders of 2/1 Testing method ARKODE_BILLINGTON_3_3_2: table matches predicted method/embedding orders of 2/3 Testing method ARKODE_TRBDF2_3_3_2: table matches predicted method/embedding orders of 2/3 Testing method ARKODE_KVAERNO_4_2_3: table matches predicted method/embedding orders of 3/2 @@ -73,6 +76,10 @@ Testing method ARKODE_QESDIRK436L2SA_6_3_4: table matches predicted method/embe Testing method ARKODE_ESDIRK437L2SA_7_3_4: table matches predicted method/embedding orders of 4/3 Testing method ARKODE_ESDIRK547L2SA_7_4_5: table matches predicted method/embedding orders of 5/4 Testing method ARKODE_ESDIRK547L2SA2_7_4_5: table matches predicted method/embedding orders of 5/4 +Testing method ARKODE_ARK2_DIRK_3_1_2: table matches predicted method/embedding orders of 2/1 +Testing method ARKODE_BACKWARD_EULER_1_1: table matches predicted method/embedding orders of 1/0 +Testing method ARKODE_IMPLICIT_MIDPOINT_1_2: table matches predicted method/embedding orders of 2/0 +Testing method ARKODE_IMPLICIT_TRAPEZOIDAL_2_2: table matches predicted method/embedding orders of 2/0 Testing ARK pairs: