From aee4ae62431907dd751966840d4331d2b332410a Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Sun, 22 Sep 2024 15:52:32 -0700 Subject: [PATCH 01/89] Add high precision coefficients for some DIRK methods --- src/arkode/arkode_butcher_dirk.def | 306 ++++++++++++++--------------- 1 file changed, 153 insertions(+), 153 deletions(-) diff --git a/src/arkode/arkode_butcher_dirk.def b/src/arkode/arkode_butcher_dirk.def index 40d13e60bd..06fdfb82bd 100644 --- a/src/arkode/arkode_butcher_dirk.def +++ b/src/arkode/arkode_butcher_dirk.def @@ -39,24 +39,24 @@ ARKODE_ARK2_DIRK_3_1_2 ESDIRK Y Y Y ARKODE_IMPLICIT_MIDPOINT_1_2 SDIRK Y N Y ARKODE_IMPLICIT_TRAPEZOIDAL_2_2 ESDIRK Y N Y - ARKODE_BILLINGTON_3_3_2 SDIRK N N N + ARKODE_BILLINGTON_3_3_2 SDIRK N N Y ARKODE_TRBDF2_3_3_2 ESDIRK N N Y - ARKODE_KVAERNO_4_2_3 ESDIRK Y Y N + ARKODE_KVAERNO_4_2_3 ESDIRK Y Y Y ARKODE_ARK324L2SA_DIRK_4_2_3* ESDIRK Y Y N ARKODE_ESDIRK324L2SA_4_2_3 ESDIRK Y Y Y ARKODE_ESDIRK325L2SA_5_2_3 ESDIRK Y Y Y ARKODE_ESDIRK32I5L2SA_5_2_3 ESDIRK Y Y Y - ARKODE_CASH_5_2_4 SDIRK Y Y N - ARKODE_CASH_5_3_4 SDIRK Y Y N + ARKODE_CASH_5_2_4 SDIRK Y Y Y + ARKODE_CASH_5_3_4 SDIRK Y Y Y ARKODE_SDIRK_5_3_4 SDIRK Y Y Y - ARKODE_KVAERNO_5_3_4 ESDIRK Y N N + ARKODE_KVAERNO_5_3_4 ESDIRK Y N Y ARKODE_ARK436L2SA_DIRK_6_3_4* ESDIRK Y Y N ARKODE_ARK437L2SA_DIRK_7_3_4* ESDIRK Y Y N ARKODE_ESDIRK436L2SA_6_3_4 ESDIRK Y Y N ARKODE_ESDIRK43I6L2SA_6_3_4 ESDIRK Y Y N ARKODE_QESDIRK436L2SA_6_3_4 ESDIRK Y Y N ARKODE_ESDIRK437L2SA_7_3_4 ESDIRK Y Y N - ARKODE_KVAERNO_7_4_5 ESDIRK Y Y N + ARKODE_KVAERNO_7_4_5 ESDIRK Y Y Y ARKODE_ARK548L2SA_DIRK_8_4_5* ESDIRK Y Y N ARKODE_ARK548L2SAb_DIRK_8_4_5* ESDIRK Y Y N ARKODE_ESDIRK547L2SA_7_4_5 ESDIRK Y Y N @@ -169,23 +169,23 @@ ARK_BUTCHER_TABLE(ARKODE_BILLINGTON_3_3_2, { /* Billington-SDIRK */ B->q = 2; B->p = 3; - B->A[0][0] = SUN_RCONST(0.292893218813); - B->A[1][0] = SUN_RCONST(0.798989873223); - B->A[1][1] = SUN_RCONST(0.292893218813); - B->A[2][0] = SUN_RCONST(0.740789228841); - B->A[2][1] = SUN_RCONST(0.259210771159); - B->A[2][2] = SUN_RCONST(0.292893218813); + B->A[0][0] = SUN_RCONST(0.2928932188134524755991556378951509607152); + B->A[1][0] = SUN_RCONST(0.7989898732233306832236421389357730999754); + B->A[1][1] = SUN_RCONST(0.2928932188134524755991556378951509607152); + B->A[2][0] = SUN_RCONST(0.7407892288408794315482509093379275743089); + B->A[2][1] = SUN_RCONST(0.2592107711591205684517490906620724256911); + B->A[2][2] = SUN_RCONST(0.2928932188134524755991556378951509607152); - B->d[0] = SUN_RCONST(0.691665115992); - B->d[1] = SUN_RCONST(0.503597029883); - B->d[2] = SUN_RCONST(-0.195262145876); + B->d[0] = SUN_RCONST(0.6916651159922363998055890924735413039564); + B->d[1] = SUN_RCONST(0.5035970298833985839271813327898926698538); + B->d[2] = SUN_RCONST(-0.1952621458756349837327704252634339738101); - B->b[0] = SUN_RCONST(0.740789228840); - B->b[1] = SUN_RCONST(0.259210771159); + B->b[0] = SUN_RCONST(0.7407892288408794315482509093379275743089); + B->b[1] = SUN_RCONST(0.2592107711591205684517490906620724256911); - B->c[0] = SUN_RCONST(0.292893218813); - B->c[1] = SUN_RCONST(1.091883092037); - B->c[2] = SUN_RCONST(1.292893218813); + B->c[0] = SUN_RCONST(0.2928932188134524755991556378951509607152); + B->c[1] = SUN_RCONST(1.091883092036783158822797776830924060691); + B->c[2] = SUN_RCONST(1.292893218813452475599155637895150960715); return B; }) @@ -217,26 +217,26 @@ ARK_BUTCHER_TABLE(ARKODE_KVAERNO_4_2_3, { /* Kvaerno(4,2,3)-ESDIRK */ ARKodeButcherTable B = ARKodeButcherTable_Alloc(4, SUNTRUE); B->q = 3; B->p = 2; - B->A[1][0] = SUN_RCONST(0.4358665215); - B->A[1][1] = SUN_RCONST(0.4358665215); - B->A[2][0] = SUN_RCONST(0.490563388419108); - B->A[2][1] = SUN_RCONST(0.073570090080892); - B->A[2][2] = SUN_RCONST(0.4358665215); - B->A[3][0] = SUN_RCONST(0.308809969973036); - B->A[3][1] = SUN_RCONST(1.490563388254106); - B->A[3][2] = SUN_RCONST(-1.235239879727145); - B->A[3][3] = SUN_RCONST(0.4358665215); - - B->b[0] = SUN_RCONST(0.308809969973036); - B->b[1] = SUN_RCONST(1.490563388254106); - B->b[2] = SUN_RCONST(-1.235239879727145); - B->b[3] = SUN_RCONST(0.4358665215); - - B->d[0] = SUN_RCONST(0.490563388419108); - B->d[1] = SUN_RCONST(0.073570090080892); - B->d[2] = SUN_RCONST(0.4358665215); - - B->c[1] = SUN_RCONST(0.871733043); + B->A[1][0] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[1][1] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[2][0] = SUN_RCONST(0.4905633884217805706284679584665446902307); + B->A[2][1] = SUN_RCONST(0.07357009006976042995551259033989846723997); + B->A[2][2] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[3][0] = SUN_RCONST(0.3088099699767465233481624698867005109200); + B->A[3][1] = SUN_RCONST(1.490563388421780570628467958466544690231); + B->A[3][2] = SUN_RCONST(-1.235239879906986093392649879546802043680); + B->A[3][3] = SUN_RCONST(0.4358665215084589994160194511935568425293); + + B->b[0] = SUN_RCONST(0.3088099699767465233481624698867005109200); + B->b[1] = SUN_RCONST(1.490563388421780570628467958466544690231); + B->b[2] = SUN_RCONST(-1.235239879906986093392649879546802043680); + B->b[3] = SUN_RCONST(0.4358665215084589994160194511935568425293); + + B->d[0] = SUN_RCONST(0.4905633884217805706284679584665446902307); + B->d[1] = SUN_RCONST(0.07357009006976042995551259033989846723997); + B->d[2] = SUN_RCONST(0.4358665215084589994160194511935568425293); + + B->c[1] = SUN_RCONST(0.8717330430169179988320389023871136850586); B->c[2] = SUN_RCONST(1.0); B->c[3] = SUN_RCONST(1.0); return B; @@ -276,35 +276,35 @@ ARK_BUTCHER_TABLE(ARKODE_CASH_5_2_4, { /* Cash(5,2,4)-SDIRK */ ARKodeButcherTable B = ARKodeButcherTable_Alloc(5, SUNTRUE); B->q = 4; B->p = 2; - B->A[0][0] = SUN_RCONST(0.435866521508); - B->A[1][0] = SUN_RCONST(-1.13586652150); - B->A[1][1] = SUN_RCONST(0.435866521508); - B->A[2][0] = SUN_RCONST(1.08543330679); - B->A[2][1] = SUN_RCONST(-0.721299828287); - B->A[2][2] = SUN_RCONST(0.435866521508); - B->A[3][0] = SUN_RCONST(0.416349501547); - B->A[3][1] = SUN_RCONST(0.190984004184); - B->A[3][2] = SUN_RCONST(-0.118643265417); - B->A[3][3] = SUN_RCONST(0.435866521508); - B->A[4][0] = SUN_RCONST(0.896869652944); - B->A[4][1] = SUN_RCONST(0.0182725272734); - B->A[4][2] = SUN_RCONST(-0.0845900310706); - B->A[4][3] = SUN_RCONST(-0.266418670647); - B->A[4][4] = SUN_RCONST(0.435866521508); - - B->b[0] = SUN_RCONST(0.896869652944); - B->b[1] = SUN_RCONST(0.0182725272734); - B->b[2] = SUN_RCONST(-0.0845900310706); - B->b[3] = SUN_RCONST(-0.266418670647); - B->b[4] = SUN_RCONST(0.435866521508); - - B->d[0] = (SUN_RCONST(-0.7)-SUN_RCONST(0.5))/(SUN_RCONST(-0.7)-SUN_RCONST(0.435866521508)); - B->d[1] = (SUN_RCONST(0.5)-SUN_RCONST(0.435866521508))/(SUN_RCONST(-0.7)-SUN_RCONST(0.435866521508)); - - B->c[0] = SUN_RCONST(0.435866521508); + B->A[0][0] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[1][0] = SUN_RCONST(-1.135866521508458999416019451193556842529); + B->A[1][1] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[2][0] = SUN_RCONST(1.085433306501187798233740932177548948256); + B->A[2][1] = SUN_RCONST(-0.7212998280096467976497603833711057907848); + B->A[2][2] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[3][0] = SUN_RCONST(0.4163495015787799872439975203112232915822); + B->A[3][1] = SUN_RCONST(0.1909840041795561340637290424182710083545); + B->A[3][2] = SUN_RCONST(-0.1186432654601150605249854908172545332519); + B->A[3][3] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[4][0] = SUN_RCONST(0.8968696529704295827357809984030487598656); + B->A[4][1] = SUN_RCONST(0.01827252727396890379954420931708867645445); + B->A[4][2] = SUN_RCONST(-0.08459003110197203803096641412326485130547); + B->A[4][3] = SUN_RCONST(-0.2664186706508854479203782447904294275438); + B->A[4][4] = SUN_RCONST(0.4358665215084589994160194511935568425293); + + B->b[0] = SUN_RCONST(0.8968696529704295827357809984030487598656); + B->b[1] = SUN_RCONST(0.01827252727396890379954420931708867645445); + B->b[2] = SUN_RCONST(-0.08459003110197203803096641412326485130547); + B->b[3] = SUN_RCONST(-0.2664186706508854479203782447904294275438); + B->b[4] = SUN_RCONST(0.4358665215084589994160194511935568425293); + + B->d[0] = SUN_RCONST(1.056462161070096639164359247420837614501); + B->d[1] = SUN_RCONST(-0.05646216107009663916435924742083761450128); + + B->c[0] = SUN_RCONST(0.4358665215084589994160194511935568425293); B->c[1] = SUN_RCONST(-0.7); B->c[2] = SUN_RCONST(0.8); - B->c[3] = SUN_RCONST(0.924556761814); + B->c[3] = SUN_RCONST(0.9245567618066800601987605231057966092142); B->c[4] = SUN_RCONST(1.0); return B; }) @@ -313,37 +313,37 @@ ARK_BUTCHER_TABLE(ARKODE_CASH_5_3_4, { /* Cash(5,3,4)-SDIRK */ ARKodeButcherTable B = ARKodeButcherTable_Alloc(5, SUNTRUE); B->q = 4; B->p = 3; - B->A[0][0] = SUN_RCONST(0.435866521508); - B->A[1][0] = SUN_RCONST(-1.13586652150); - B->A[1][1] = SUN_RCONST(0.435866521508); - B->A[2][0] = SUN_RCONST(1.08543330679); - B->A[2][1] = SUN_RCONST(-0.721299828287); - B->A[2][2] = SUN_RCONST(0.435866521508); - B->A[3][0] = SUN_RCONST(0.416349501547); - B->A[3][1] = SUN_RCONST(0.190984004184); - B->A[3][2] = SUN_RCONST(-0.118643265417); - B->A[3][3] = SUN_RCONST(0.435866521508); - B->A[4][0] = SUN_RCONST(0.896869652944); - B->A[4][1] = SUN_RCONST(0.0182725272734); - B->A[4][2] = SUN_RCONST(-0.0845900310706); - B->A[4][3] = SUN_RCONST(-0.266418670647); - B->A[4][4] = SUN_RCONST(0.435866521508); - - B->b[0] = SUN_RCONST(0.896869652944); - B->b[1] = SUN_RCONST(0.0182725272734); - B->b[2] = SUN_RCONST(-0.0845900310706); - B->b[3] = SUN_RCONST(-0.266418670647); - B->b[4] = SUN_RCONST(0.435866521508); - - B->d[0] = SUN_RCONST(0.776691932910); - B->d[1] = SUN_RCONST(0.0297472791484); - B->d[2] = SUN_RCONST(-0.0267440239074); - B->d[3] = SUN_RCONST(0.220304811849); - - B->c[0] = SUN_RCONST(0.435866521508); + B->A[0][0] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[1][0] = SUN_RCONST(-1.135866521508458999416019451193556842529); + B->A[1][1] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[2][0] = SUN_RCONST(1.085433306501187798233740932177548948256); + B->A[2][1] = SUN_RCONST(-0.7212998280096467976497603833711057907848); + B->A[2][2] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[3][0] = SUN_RCONST(0.4163495015787799872439975203112232915822); + B->A[3][1] = SUN_RCONST(0.1909840041795561340637290424182710083545); + B->A[3][2] = SUN_RCONST(-0.1186432654601150605249854908172545332519); + B->A[3][3] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[4][0] = SUN_RCONST(0.8968696529704295827357809984030487598656); + B->A[4][1] = SUN_RCONST(0.01827252727396890379954420931708867645445); + B->A[4][2] = SUN_RCONST(-0.08459003110197203803096641412326485130547); + B->A[4][3] = SUN_RCONST(-0.2664186706508854479203782447904294275438); + B->A[4][4] = SUN_RCONST(0.4358665215084589994160194511935568425293); + + B->b[0] = SUN_RCONST(0.8968696529704295827357809984030487598656); + B->b[1] = SUN_RCONST(0.01827252727396890379954420931708867645445); + B->b[2] = SUN_RCONST(-0.08459003110197203803096641412326485130547); + B->b[3] = SUN_RCONST(-0.2664186706508854479203782447904294275438); + B->b[4] = SUN_RCONST(0.4358665215084589994160194511935568425293); + + B->d[0] = SUN_RCONST(0.7766919329157524221967851040635650689914); + B->d[1] = SUN_RCONST(0.02974727915032039108861503804581544141749); + B->d[2] = SUN_RCONST(-0.02674402391564096382835552392654800827276); + B->d[3] = SUN_RCONST(0.2203048118495681505429553818171674978639); + + B->c[0] = SUN_RCONST(0.4358665215084589994160194511935568425293); B->c[1] = SUN_RCONST(-0.7); B->c[2] = SUN_RCONST(0.8); - B->c[3] = SUN_RCONST(0.924556761814); + B->c[3] = SUN_RCONST(0.9245567618066800601987605231057966092142); B->c[4] = SUN_RCONST(1.0); return B; }) @@ -391,34 +391,34 @@ ARK_BUTCHER_TABLE(ARKODE_KVAERNO_5_3_4, { /* Kvaerno(5,3,4)-ESDIRK */ ARKodeButcherTable B = ARKodeButcherTable_Alloc(5, SUNTRUE); B->q = 4; B->p = 3; - B->A[1][0] = SUN_RCONST(0.4358665215); - B->A[1][1] = SUN_RCONST(0.4358665215); - B->A[2][0] = SUN_RCONST(0.140737774731968); - B->A[2][1] = SUN_RCONST(-0.108365551378832); - B->A[2][2] = SUN_RCONST(0.4358665215); - B->A[3][0] = SUN_RCONST(0.102399400616089); - B->A[3][1] = SUN_RCONST(-0.376878452267324); - B->A[3][2] = SUN_RCONST(0.838612530151233); - B->A[3][3] = SUN_RCONST(0.4358665215); - B->A[4][0] = SUN_RCONST(0.157024897860995); - B->A[4][1] = SUN_RCONST(0.117330441357768); - B->A[4][2] = SUN_RCONST(0.61667803039168); - B->A[4][3] = SUN_RCONST(-0.326899891110444); - B->A[4][4] = SUN_RCONST(0.4358665215); - - B->b[0] = SUN_RCONST(0.157024897860995); - B->b[1] = SUN_RCONST(0.117330441357768); - B->b[2] = SUN_RCONST(0.61667803039168); - B->b[3] = SUN_RCONST(-0.326899891110444); - B->b[4] = SUN_RCONST(0.4358665215); - - B->d[0] = SUN_RCONST(0.102399400616089); - B->d[1] = SUN_RCONST(-0.376878452267324); - B->d[2] = SUN_RCONST(0.838612530151233); - B->d[3] = SUN_RCONST(0.4358665215); - - B->c[1] = SUN_RCONST(0.871733043); - B->c[2] = SUN_RCONST(0.468238744853136); + B->A[1][0] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[1][1] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[2][0] = SUN_RCONST(0.1407377747247061961864132309262694299296); + B->A[2][1] = SUN_RCONST(-0.1083655513813207999782253192353360264820); + B->A[2][2] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[3][0] = SUN_RCONST(0.1023994006199109976822794150595997362069); + B->A[3][1] = SUN_RCONST(-0.3768784522555561060886970749014278247138); + B->A[3][2] = SUN_RCONST(0.8386125301271861089903982086482712459776); + B->A[3][3] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[4][0] = SUN_RCONST(0.1570248978603249371007885739812418750001); + B->A[4][1] = SUN_RCONST(0.1173304413704388486968184370770592278731); + B->A[4][2] = SUN_RCONST(0.6166780303921214643483881261433096864945); + B->A[4][3] = SUN_RCONST(-0.3268998911313442495620145883951676318970); + B->A[4][4] = SUN_RCONST(0.4358665215084589994160194511935568425293); + + B->b[0] = SUN_RCONST(0.1570248978603249371007885739812418750001); + B->b[1] = SUN_RCONST(0.1173304413704388486968184370770592278731); + B->b[2] = SUN_RCONST(0.6166780303921214643483881261433096864945); + B->b[3] = SUN_RCONST(-0.3268998911313442495620145883951676318970); + B->b[4] = SUN_RCONST(0.4358665215084589994160194511935568425293); + + B->d[0] = SUN_RCONST(0.1023994006199109976822794150595997362069); + B->d[1] = SUN_RCONST(-0.3768784522555561060886970749014278247138); + B->d[2] = SUN_RCONST(0.8386125301271861089903982086482712459776); + B->d[3] = SUN_RCONST(0.4358665215084589994160194511935568425293); + + B->c[1] = SUN_RCONST(0.8717330430169179988320389023871136850586); + B->c[2] = SUN_RCONST(0.4682387448518443956242073628844902459769); B->c[3] = SUN_RCONST(1.0); B->c[4] = SUN_RCONST(1.0); return B; @@ -527,46 +527,46 @@ ARK_BUTCHER_TABLE(ARKODE_KVAERNO_7_4_5, { /* Kvaerno(7,4,5)-ESDIRK */ B->A[1][0] = SUN_RCONST(0.26); B->A[1][1] = SUN_RCONST(0.26); B->A[2][0] = SUN_RCONST(0.13); - B->A[2][1] = SUN_RCONST(0.84033320996790809); + B->A[2][1] = SUN_RCONST(0.8403332099679080963171360487915268154051); B->A[2][2] = SUN_RCONST(0.26); - B->A[3][0] = SUN_RCONST(0.22371961478320505); - B->A[3][1] = SUN_RCONST(0.47675532319799699); - B->A[3][2] = SUN_RCONST(-0.06470895363112615); + B->A[3][0] = SUN_RCONST(0.2237196147832050559163143898290529441991); + B->A[3][1] = SUN_RCONST(0.4767553231979969983278927937270874162429); + B->A[3][2] = SUN_RCONST(-0.06470895363112615133816161180658488282681); B->A[3][3] = SUN_RCONST(0.26); - B->A[4][0] = SUN_RCONST(0.16648564323248321); - B->A[4][1] = SUN_RCONST(0.10450018841591720); - B->A[4][2] = SUN_RCONST(0.03631482272098715); - B->A[4][3] = SUN_RCONST(-0.13090704451073998); + B->A[4][0] = SUN_RCONST(0.1664856432324832152535151725360430044452); + B->A[4][1] = SUN_RCONST(0.1045001884159172041151167240328967362455); + B->A[4][2] = SUN_RCONST(0.03631482272098715161651993758285203251909); + B->A[4][3] = SUN_RCONST(-0.1309070445107399857071749645700052401819); B->A[4][4] = SUN_RCONST(0.26); - B->A[5][0] = SUN_RCONST(0.13855640231268224); - B->A[5][2] = SUN_RCONST(-0.04245337201752043); - B->A[5][3] = SUN_RCONST(0.02446657898003141); - B->A[5][4] = SUN_RCONST(0.61943039072480676); + B->A[5][0] = SUN_RCONST(0.1385564023126822495054973091161581456582); + B->A[5][2] = SUN_RCONST(-0.04245337201752043098884399725982168512523); + B->A[5][3] = SUN_RCONST(0.02446657898003141965963581513879101305561); + B->A[5][4] = SUN_RCONST(0.6194303907248067618237108730048725264114); B->A[5][5] = SUN_RCONST(0.26); - B->A[6][0] = SUN_RCONST(0.13659751177640291); - B->A[6][2] = SUN_RCONST(-0.05496908796538376); - B->A[6][3] = SUN_RCONST(-0.04118626728321046); - B->A[6][4] = SUN_RCONST(0.62993304899016403); - B->A[6][5] = SUN_RCONST(0.06962479448202728); + B->A[6][0] = SUN_RCONST(0.1365975117764029144062783844146127033921); + B->A[6][2] = SUN_RCONST(-0.05496908796538376712487773114648630009105); + B->A[6][3] = SUN_RCONST(-0.04118626728321046868299776958296295741592); + B->A[6][4] = SUN_RCONST(0.6299330489901640319161060392667246534806); + B->A[6][5] = SUN_RCONST(0.06962479448202728948549107704811190063421); B->A[6][6] = SUN_RCONST(0.26); - B->b[0] = SUN_RCONST(0.13659751177640291); - B->b[2] = SUN_RCONST(-0.05496908796538376); - B->b[3] = SUN_RCONST(-0.04118626728321046); - B->b[4] = SUN_RCONST(0.62993304899016403); - B->b[5] = SUN_RCONST(0.06962479448202728); + B->b[0] = SUN_RCONST(0.1365975117764029144062783844146127033921); + B->b[2] = SUN_RCONST(-0.05496908796538376712487773114648630009105); + B->b[3] = SUN_RCONST(-0.04118626728321046868299776958296295741592); + B->b[4] = SUN_RCONST(0.6299330489901640319161060392667246534806); + B->b[5] = SUN_RCONST(0.06962479448202728948549107704811190063421); B->b[6] = SUN_RCONST(0.26); - B->d[0] = SUN_RCONST(0.13855640231268224); - B->d[2] = SUN_RCONST(-0.04245337201752043); - B->d[3] = SUN_RCONST(0.02446657898003141); - B->d[4] = SUN_RCONST(0.61943039072480676); + B->d[0] = SUN_RCONST(0.1385564023126822495054973091161581456582); + B->d[2] = SUN_RCONST(-0.04245337201752043098884399725982168512523); + B->d[3] = SUN_RCONST(0.02446657898003141965963581513879101305561); + B->d[4] = SUN_RCONST(0.6194303907248067618237108730048725264114); B->d[5] = SUN_RCONST(0.26); B->c[1] = SUN_RCONST(0.52); - B->c[2] = SUN_RCONST(1.230333209967908); - B->c[3] = SUN_RCONST(0.895765984350076); - B->c[4] = SUN_RCONST(0.436393609858648); + B->c[2] = SUN_RCONST(1.230333209967908096317136048791526815405); + B->c[3] = SUN_RCONST(0.8957659843500759029060455717495554776153); + B->c[4] = SUN_RCONST(0.4363936098586475852779768695817865330279); B->c[5] = SUN_RCONST(1.0); B->c[6] = SUN_RCONST(1.0); return B; From 674baef40af618863bfb6cae8a345695d06b82c4 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Sun, 22 Sep 2024 16:12:29 -0700 Subject: [PATCH 02/89] Update Billington table in docs --- doc/arkode/guide/source/Butcher.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/arkode/guide/source/Butcher.rst b/doc/arkode/guide/source/Butcher.rst index 0b7e401a56..4e6aec608a 100644 --- a/doc/arkode/guide/source/Butcher.rst +++ b/doc/arkode/guide/source/Butcher.rst @@ -1407,12 +1407,12 @@ Here, the higher-order embedding is less stable than the lower-order method \renewcommand{\arraystretch}{1.5} \begin{array}{r|ccc} - 0.292893218813 & 0.292893218813 & 0 & 0 \\ - 1.091883092037 & 0.798989873223 & 0.292893218813 & 0 \\ - 1.292893218813 & 0.740789228841 & 0.259210771159 & 0.292893218813 \\ + 1 - \frac{1}{\sqrt{2}} & 1 - \frac{1}{\sqrt{2}} & 0 & 0 \\ + \frac{27}{\sqrt{2}} - 18 & 14 \sqrt{2} - 19 & 1 - \frac{1}{\sqrt{2}} & 0 \\ + 2 - \frac{1}{\sqrt{2}} & \frac{53 - 5 \sqrt{2}}{62} & \frac{9 + 5 \sqrt{2}}{62} & 1 - \frac{1}{\sqrt{2}} \\ \hline - 2 & 0.740789228840 & 0.259210771159 & 0 \\ - 3 & 0.691665115992 & 0.503597029883 & -0.195262145876 + 2 & \frac{53 - 5 \sqrt{2}}{62} & \frac{9 + 5 \sqrt{2}}{62} & 0 \\ + 3 & \frac{263 - 95 \sqrt{2}}{186} & \frac{47 + 33 \sqrt{2}}{186} & \frac{\sqrt{2} - 2}{3} \end{array} .. figure:: /figs/arkode/stab_region_12.png From 271c0ed6cc60e723b49d12f8254b530975cc53a7 Mon Sep 17 00:00:00 2001 From: Cody Balos Date: Tue, 1 Oct 2024 21:48:04 -0700 Subject: [PATCH 03/89] CI: add magic /autofix ability for PRs (#577) Comment `/autofix` on your PR and a GitHub action will fix the spelling, formatting, and swig errors. --- .github/actions/apply-style/checkout.sh | 45 ++++++++++++++ .github/workflows/check-format.yml | 54 ++++++++++++++++- .github/workflows/check-spelling.yml | 54 ++++++++++++++++- .github/workflows/check-swig.yml | 59 +++++++++++++++++-- .github/workflows/spack-develop.yml | 4 +- .github/workflows/ubuntu-latest.yml | 4 +- doc/superbuild/source/developers/index.rst | 6 ++ .../developers/pull_requests/OpenPR.rst | 11 +++- .../developers/style_guide/SourceCode.rst | 4 +- 9 files changed, 228 insertions(+), 13 deletions(-) create mode 100755 .github/actions/apply-style/checkout.sh diff --git a/.github/actions/apply-style/checkout.sh b/.github/actions/apply-style/checkout.sh new file mode 100755 index 0000000000..34a6f15b43 --- /dev/null +++ b/.github/actions/apply-style/checkout.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +### +# Attempt to find the branch of the PR from the detached head state +## + +echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" +echo "Attempting to find branch that matches commit..." + +# Get the current commit SHA +current_commit_sha=$(git rev-parse HEAD) +# List all branches containing the current commit SHA +branches=$(git branch -r --contains $current_commit_sha) + +echo "all branches:" +echo "$(git branch -a)" +echo "branches with SHA $current_commit_sha:" +echo "$branches" + +# Loop over the string split by whitespace +branch="" +num_branches_found=0 +for _possible_branch in $branches; do + # Skip items that start with "pull/" + if [[ $_possible_branch == pull/* ]]; then + continue + fi + if [[ $_possible_branch == origin/* ]]; then + _possible_branch=$(echo "$_possible_branch" | sed 's/origin\///') + fi + echo "Possible Branch: $_possible_branch" + branch=$_possible_branch + num_branches_found=$((num_branches_found+1)) +done + +if [ "$num_branches_found" -ne 1 ]; then + echo "Error: Unable to find a single branch that matched git sha $current_commit_sha" + exit 1 +fi + +echo "Found branch: $branch" +echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" + +git checkout $branch +git submodule update --init --recursive diff --git a/.github/workflows/check-format.yml b/.github/workflows/check-format.yml index b3d0850ca9..d052dfec97 100644 --- a/.github/workflows/check-format.yml +++ b/.github/workflows/check-format.yml @@ -3,9 +3,12 @@ name: Checks - formatting on: pull_request: workflow_dispatch: + issue_comment: + types: [created] jobs: format_check: + if: ${{ github.event_name != 'issue_comment' || (github.event_name == 'issue_comment' && startsWith(github.event.comment.body, '/autofix')) }} runs-on: ubuntu-latest container: image: ghcr.io/llnl/sundials_spack_cache:llvm-17.0.4-h4lflucc3v2vage45opbo2didtcuigsn.spack @@ -37,10 +40,18 @@ jobs: run: clang-format --version - name: Check out repository code + if: github.event_name != 'issue_comment' uses: actions/checkout@v4 with: submodules: true + - name: Check out repository code + if: github.event_name == 'issue_comment' + uses: actions/checkout@v4 + with: + ref: refs/pull/${{ github.event.issue.number }}/head + fetch-depth: 0 + - name: Add safe directory run: git config --global --add safe.directory "$GITHUB_WORKSPACE" @@ -56,9 +67,50 @@ jobs: run: /usr/bin/git diff > format.patch - name: Archive diff as a patch if we failed - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: failure() with: name: format.patch path: | ${{ github.workspace }}/format.patch + + apply_format: + if: ${{ always() && contains(join(needs.*.result, ','), 'failure') && (github.event_name == 'issue_comment' && startsWith(github.event.comment.body, '/autofix')) }} + needs: format_check + runs-on: ubuntu-latest + steps: + # Checkout the GitHub created reference for the PR. + # The only way to do this is by using the "issue" number + # but that is really the PR number in this context. + # This is due to using an `issue_comment` event which + # is due to the GitHub Actions API that does not have + # a `pull_request_comment` event or something similar. + # This leaves us in a detached head state which is corrected + # in `apply-style/checkout.sh` + - name: Checkout repository code + uses: actions/checkout@v4 + with: + ref: refs/pull/${{ github.event.issue.number }}/head + fetch-depth: 0 + + - name: Checkout the right git ref + run: ./.github/actions/apply-style/checkout.sh + + - name: Download the git diff from format_check + uses: actions/download-artifact@v4 + with: + name: format.patch + + - name: Apply patch + run: | + git apply format.patch + rm format.patch + + - name: Commit fixes + run: | + git config user.name "format-robot" + git config user.email "no-reply@llnl.gov" + if [ -n "$(git status --porcelain)" ]; then + git commit -am 'apply format updates' + git push + fi diff --git a/.github/workflows/check-spelling.yml b/.github/workflows/check-spelling.yml index 8825e58b06..16349e8891 100644 --- a/.github/workflows/check-spelling.yml +++ b/.github/workflows/check-spelling.yml @@ -3,9 +3,12 @@ name: Checks - spelling on: pull_request: workflow_dispatch: + issue_comment: + types: [created] jobs: spelling_check: + if: ${{ github.event_name != 'issue_comment' || (github.event_name == 'issue_comment' && startsWith(github.event.comment.body, '/autofix')) }} runs-on: ubuntu-latest steps: - name: Install python3-pip @@ -20,10 +23,18 @@ jobs: run: codespell --version - name: Check out repository code + if: github.event_name != 'issue_comment' uses: actions/checkout@v4 with: submodules: true + - name: Check out repository code + if: github.event_name == 'issue_comment' + uses: actions/checkout@v4 + with: + ref: refs/pull/${{ github.event.issue.number }}/head + fetch-depth: 0 + - name: Run codespell run: | ./scripts/spelling.sh @@ -36,9 +47,50 @@ jobs: run: /usr/bin/git diff > spelling.patch - name: Archive diff as a patch if we failed - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: failure() with: name: spelling.patch path: | ${{ github.workspace }}/spelling.patch + + apply_spelling: + if: ${{ always() && contains(join(needs.*.result, ','), 'failure') && (github.event_name == 'issue_comment' && startsWith(github.event.comment.body, '/autofix')) }} + needs: spelling_check + runs-on: ubuntu-latest + steps: + # Checkout the GitHub created reference for the PR. + # The only way to do this is by using the "issue" number + # but that is really the PR number in this context. + # This is due to using an `issue_comment` event which + # is due to the GitHub Actions API that does not have + # a `pull_request_comment` event or something similar. + # This leaves us in a detached head state which is corrected + # in `apply-style/checkout.sh` + - name: Checkout repository code + uses: actions/checkout@v4 + with: + ref: refs/pull/${{ github.event.issue.number }}/head + fetch-depth: 0 + + - name: Checkout the right git ref + run: ./.github/actions/apply-style/checkout.sh + + - name: Download the git diff from spelling_check + uses: actions/download-artifact@v4 + with: + name: spelling.patch + + - name: Apply patch + run: | + git apply spelling.patch + rm spelling.patch + + - name: Commit fixes + run: | + git config user.name "format-robot" + git config user.email "no-reply@llnl.gov" + if [ -n "$(git status --porcelain)" ]; then + git commit -am 'apply spelling updates' + git push + fi diff --git a/.github/workflows/check-swig.yml b/.github/workflows/check-swig.yml index 2a4193a239..25a0bc16a2 100644 --- a/.github/workflows/check-swig.yml +++ b/.github/workflows/check-swig.yml @@ -3,11 +3,13 @@ name: Checks - swig on: pull_request: workflow_dispatch: + issue_comment: + types: [created] jobs: - swig: + swig_check: + if: ${{ github.event_name != 'issue_comment' || (github.event_name == 'issue_comment' && startsWith(github.event.comment.body, '/autofix')) }} runs-on: ubuntu-latest - steps: - name: Install swig run: | @@ -15,15 +17,23 @@ jobs: cd swig ./autogen.sh ./configure --prefix=/usr/ - make + make sudo make install swig -version - name: Check out repository code + if: github.event_name != 'issue_comment' uses: actions/checkout@v4 with: submodules: true + - name: Check out repository code + if: github.event_name == 'issue_comment' + uses: actions/checkout@v4 + with: + ref: refs/pull/${{ github.event.issue.number }}/head + fetch-depth: 0 + - name: Add safe directory run: git config --global --add safe.directory "$GITHUB_WORKSPACE" @@ -41,9 +51,50 @@ jobs: run: /usr/bin/git diff > swig.patch - name: Archive diff as a patch if we failed - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: failure() with: name: swig.patch path: | ${{ github.workspace }}/swig.patch + + apply_swig: + if: ${{ always() && contains(join(needs.*.result, ','), 'failure') && (github.event_name == 'issue_comment' && startsWith(github.event.comment.body, '/autofix')) }} + needs: swig_check + runs-on: ubuntu-latest + steps: + # Checkout the GitHub created reference for the PR. + # The only way to do this is by using the "issue" number + # but that is really the PR number in this context. + # This is due to using an `issue_comment` event which + # is due to the GitHub Actions API that does not have + # a `pull_request_comment` event or something similar. + # This leaves us in a detached head state which is corrected + # in `apply-style/checkout.sh` + - name: Checkout repository code + uses: actions/checkout@v4 + with: + ref: refs/pull/${{ github.event.issue.number }}/head + fetch-depth: 0 + + - name: Checkout the right git ref + run: ./.github/actions/apply-style/checkout.sh + + - name: Download the git diff from swig_check + uses: actions/download-artifact@v4 + with: + name: swig.patch + + - name: Apply patch + run: | + git apply swig.patch + rm swig.patch + + - name: Commit fixes + run: | + git config user.name "format-robot" + git config user.email "no-reply@llnl.gov" + if [ -n "$(git status --porcelain)" ]; then + git commit -am 'apply swig updates' + git push + fi diff --git a/.github/workflows/spack-develop.yml b/.github/workflows/spack-develop.yml index 41f312164f..adf15d2de3 100644 --- a/.github/workflows/spack-develop.yml +++ b/.github/workflows/spack-develop.yml @@ -33,7 +33,7 @@ jobs: indexsize: ${{ matrix.indexsize }} precision: ${{ matrix.precision }} - name: Archive build files from failed build - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: failure() with: name: build_files @@ -41,7 +41,7 @@ jobs: ${{ github.workspace }}/test/build_* !${{ github.workspace }}/test/build_*/Testing/output - name: Archive output files from failed build - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: failure() with: name: output_files diff --git a/.github/workflows/ubuntu-latest.yml b/.github/workflows/ubuntu-latest.yml index 0bc9ab7510..9b83c16c30 100644 --- a/.github/workflows/ubuntu-latest.yml +++ b/.github/workflows/ubuntu-latest.yml @@ -52,7 +52,7 @@ jobs: env: CMAKE_BUILD_TYPE: ${{ matrix.buildtype }} - name: Archive build files from failed build - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: failure() with: name: build_files @@ -60,7 +60,7 @@ jobs: ${{ github.workspace }}/test/build_* !${{ github.workspace }}/test/build_*/Testing/output - name: Archive output files from failed build - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: failure() with: name: output_files diff --git a/doc/superbuild/source/developers/index.rst b/doc/superbuild/source/developers/index.rst index b0737c8792..9b1d381e1d 100644 --- a/doc/superbuild/source/developers/index.rst +++ b/doc/superbuild/source/developers/index.rst @@ -23,6 +23,12 @@ integration packages CVODE, IDA, and ARKODE, the sensitivity analysis enabled va IDAS, and the nonlinear solver package KINSOL. This is the part of the SUNDIALS documentation is meant for SUNDIALS developers. +.. note:: + + New SUNDIALS developers should review this developer guide. In particular, the + :ref:`Style` section should be *carefully* read. + + .. toctree:: :maxdepth: 1 diff --git a/doc/superbuild/source/developers/pull_requests/OpenPR.rst b/doc/superbuild/source/developers/pull_requests/OpenPR.rst index 71ddd39ee1..f7e4f8e0a8 100644 --- a/doc/superbuild/source/developers/pull_requests/OpenPR.rst +++ b/doc/superbuild/source/developers/pull_requests/OpenPR.rst @@ -45,8 +45,17 @@ merged, delete the local copy the branch: $ git branch -D +.. note:: + + When you open a PR, various "checks" will run on your code. You can see the status of these + checks at the bottom of the PR page on GitHub. Any fixes needed to pass the checks for + formatting, spelling, and SWIG updates can be automatically addressed by leaving a comment + ``/autofix``. Checks that build the code, run more extensive tests, etc., will not automatically + be fixed. + + .. warning:: Almost all pull requests should be issued against the ``develop`` branch. Generally, the only branches we merge to ``main`` are special PRs to synchronize - ``develop`` and ``main``. \ No newline at end of file + ``develop`` and ``main``. diff --git a/doc/superbuild/source/developers/style_guide/SourceCode.rst b/doc/superbuild/source/developers/style_guide/SourceCode.rst index ba5a9c4ff8..022cffbc7e 100644 --- a/doc/superbuild/source/developers/style_guide/SourceCode.rst +++ b/doc/superbuild/source/developers/style_guide/SourceCode.rst @@ -402,8 +402,8 @@ can run: The output of ``clang-format`` is sensitive to the ``clang-format`` version. We recommend that you use version ``17.0.4``, which can be installed from source or with Spack. Alternatively, when you open a pull request on GitHub, an action will run ``clang-format`` on the code. If any - formatting is required, the action will fail and produce a git patch artifact that you can download - (from the job artifacts section) and apply with ``git apply``. + formatting is required, the action will fail. Commenting with the magic keyword ``/autofix`` will + kick off a GitHub action which will automatically apply the formatting changes needed. If clang-format breaks lines in a way that is unreadable, use ``//`` to break the line. For example, sometimes (mostly in C++ code) you may have code like this: From 04525fd54de8cf5d7f7e72f2b4bca454127bf785 Mon Sep 17 00:00:00 2001 From: Cody Balos Date: Wed, 2 Oct 2024 06:49:39 -0700 Subject: [PATCH 04/89] Maintenance: dependabot target (#585) Tell dependabot to target develop instead of `main` --- .github/dependabot.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index df4d15b35c..3bc7efbf9d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -6,3 +6,4 @@ updates: schedule: # Check for updates to GitHub Actions every week interval: "weekly" + target-branch: "develop" From a549e93341e3e21b544478d9ef82c1a08a794d22 Mon Sep 17 00:00:00 2001 From: David Gardner Date: Thu, 3 Oct 2024 07:19:55 -0700 Subject: [PATCH 05/89] Docs: Fix orderd list indentation (#586) Fix indentation so the ordered list is enumerated correctly --- doc/shared/sundials/SUNContext.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/shared/sundials/SUNContext.rst b/doc/shared/sundials/SUNContext.rst index 18b1bf050d..de5c4d05d5 100644 --- a/doc/shared/sundials/SUNContext.rst +++ b/doc/shared/sundials/SUNContext.rst @@ -187,7 +187,7 @@ Applications that need to have *concurrently initialized* SUNDIALS simulations need to take care to understand the following: #. A :c:type:`SUNContext` object must only be associated with *one* SUNDIALS simulation -(a solver object and its associated vectors etc.) at a time. + (a solver object and its associated vectors etc.) at a time. - Concurrently initialized is not the same as concurrently executing. Even if two SUNDIALS simulations execute sequentially, if both are initialized @@ -199,7 +199,7 @@ need to take care to understand the following: destroyed. #. The creation and destruction of a :c:type:`SUNContext` object is cheap, especially -in comparison to the cost of creating/destroying a SUNDIALS solver object. + in comparison to the cost of creating/destroying a SUNDIALS solver object. The following (incomplete) code examples demonstrate these points using CVODE as the example SUNDIALS package. From a1bc87904dc7970abe453afc9f65914cb3ad91ee Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Fri, 4 Oct 2024 09:45:27 -0700 Subject: [PATCH 06/89] Bugfix/sparse add i (#584) Fixes https://github.com/LLNL/sundials/issues/581 The new implementation eliminates all temporary storage/mallocs and only traverses the matrix entries once when diagonal elements don't need to be added. The sparse matrix example shows about a 1.5x speedup on 50000x50000 matrices. --- CHANGELOG.md | 4 + benchmarks/nvector/test_nvector_performance.c | 6 +- doc/shared/Changelog.rst | 38 +-- doc/shared/RecentChanges.rst | 8 +- examples/nvector/test_nvector.c | 6 +- examples/sunlinsol/test_sunlinsol.c | 8 +- examples/sunmatrix/test_sunmatrix.c | 8 +- src/sunmatrix/sparse/sunmatrix_sparse.c | 243 +++--------------- 8 files changed, 84 insertions(+), 237 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82e24b6382..138ba4ada0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,10 @@ specific linker flags e.g., MKL. ### Bug Fixes +Fixed a [bug](https://github.com/LLNL/sundials/issues/581) in the sparse matrix +implementation of `SUNMatScaleAddI` which caused out of bounds writes unless +`indexvals` were in ascending order for each row/column. + Fixed `ARKodeResize` not using the default `hscale` when an argument of `0` was provided. diff --git a/benchmarks/nvector/test_nvector_performance.c b/benchmarks/nvector/test_nvector_performance.c index 36224a9c38..c0f0870da2 100644 --- a/benchmarks/nvector/test_nvector_performance.c +++ b/benchmarks/nvector/test_nvector_performance.c @@ -43,7 +43,7 @@ static void time_stats(N_Vector X, double* times, int start, int ntimes, int print_time = 0; /* flag for printing timing data */ int nwarmups = 1; /* number of extra tests to perform and ignore in average */ -#if defined(SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS) +#if defined(SUNDIALS_HAVE_POSIX_TIMERS) time_t base_time_tv_sec = 0; /* Base time; makes time values returned by get_time easier to read when printed since they will be zero @@ -2723,7 +2723,7 @@ void SetNumWarmups(int num_warmups) void SetTiming(int onoff, int myid) { -#if defined(SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS) +#if defined(SUNDIALS_HAVE_POSIX_TIMERS) struct timespec spec; clock_gettime(CLOCK_MONOTONIC, &spec); base_time_tv_sec = spec.tv_sec; @@ -2812,7 +2812,7 @@ void rand_realtype_constraints(sunrealtype* data, sunindextype len) static double get_time(void) { double time; -#if defined(SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS) +#if defined(SUNDIALS_HAVE_POSIX_TIMERS) struct timespec spec; clock_gettime(CLOCK_MONOTONIC, &spec); time = (double)(spec.tv_sec - base_time_tv_sec) + diff --git a/doc/shared/Changelog.rst b/doc/shared/Changelog.rst index bc9d5c1ad9..2824b85a83 100644 --- a/doc/shared/Changelog.rst +++ b/doc/shared/Changelog.rst @@ -31,7 +31,7 @@ Changes to SUNDIALS in release 7.1.1 **Bug Fixes** -Fixed a `bug `_ in v7.1.0 with the +Fixed a `bug `__ in v7.1.0 with the SYCL N_Vector ``N_VSpace`` function. Changes to SUNDIALS in release 7.1.0 @@ -109,11 +109,11 @@ to ``SYCL`` to match Ginkgo's updated naming convention. Changed the CMake version compatibility mode for SUNDIALS to ``AnyNewerVersion`` instead of ``SameMajorVersion``. This fixes the issue seen `here -`_. +`__. Fixed a CMake bug that caused an MPI linking error for our C++ examples in some instances. Fixes `GitHub Issue #464 -`_. +`__. Fixed the runtime library installation path for windows systems. This fix changes the default library installation path from @@ -134,11 +134,11 @@ Fixed a bug in the HIP execution policies where ``WARP_SIZE`` would not be set with ROCm 6.0.0 or newer. Fixed a bug that caused error messages to be cut off in some cases. Fixes -`GitHub Issue #461 `_. +`GitHub Issue #461 `__. Fixed a memory leak when an error handler was added to a :c:type:`SUNContext`. Fixes `GitHub Issue #466 -`_. +`__. Fixed a bug where :c:func:`MRIStepEvolve` would not handle a recoverable error produced from evolving the inner stepper. @@ -187,7 +187,7 @@ be built with additional error checking by default. See SUNDIALS now requires using a compiler that supports a subset of the C99 standard. Note with the Microsoft C/C++ compiler the subset of C99 features utilized by SUNDIALS are available starting with `Visual Studio 2015 -`_. +`__. *Minimum CMake Version* @@ -297,7 +297,7 @@ and a typedef to a ``MPI_Comm`` in builds with MPI. As a result: The change away from type-erased pointers for :c:type:`SUNComm` fixes problems like the one described in -`GitHub Issue #275 `_. +`GitHub Issue #275 `__. The SUNLogger is now always MPI-aware if MPI is enabled in SUNDIALS and the ``SUNDIALS_LOGGING_ENABLE_MPI`` CMake option and macro definition were removed @@ -358,12 +358,12 @@ interface. **Bug Fixes** -Fixed `GitHub Issue #329 `_ so +Fixed `GitHub Issue #329 `__ so that C++20 aggregate initialization can be used. Fixed integer overflow in the internal SUNDIALS hashmap. This resolves -`GitHub Issues #409 `_ and -`#249 `_. +`GitHub Issues #409 `__ and +`#249 `__. **Deprecation Notice** @@ -431,7 +431,7 @@ an :c:type:`MRIStepInnerFullRhsFn` optional. **Bug Fixes** Changed the :c:type:`SUNProfiler` so that it does not rely on ``MPI_WTime`` in -any case. This fixes `GitHub Issue #312 `_. +any case. This fixes `GitHub Issue #312 `__. Fixed scaling bug in ``SUNMatScaleAddI_Sparse`` for non-square matrices. @@ -587,7 +587,7 @@ Added support for the SYCL backend with RAJA 2022.x.y. **Bug Fixes** Fixed an underflow bug during root finding in ARKODE, CVODE, CVODES, IDA and -IDAS. This fixes `GitHub Issue #57 `_. +IDAS. This fixes `GitHub Issue #57 `__. Fixed an issue with finding oneMKL when using the ``icpx`` compiler with the ``-fsycl`` flag as the C++ compiler instead of ``dpcpp``. @@ -624,13 +624,13 @@ e.g., CUDA, HIP, RAJA, Trilinos, SuperLU_DIST, MAGMA, Ginkgo, and Kokkos. **Major Features** -Added support for the `Ginkgo `_ linear +Added support for the `Ginkgo `__ linear algebra library. This support includes new SUNDIALS matrix and linear solver implementations, see the sections :numref:`SUNMatrix.Ginkgo` and :numref:`SUNLinSol.Ginkgo`. Added new SUNDIALS vector, dense matrix, and dense linear solver implementations -utilizing the `Kokkos Ecosystem `_ for performance +utilizing the `Kokkos Ecosystem `__ for performance portability, see sections :numref:`NVectors.Kokkos`, :numref:`SUNMatrix.Kokkos`, and :numref:`SUNLinSol.Kokkos` for more information. @@ -702,7 +702,7 @@ functions when they are available and the user may provide the math library to link to via the advanced CMake option :cmakeop:`SUNDIALS_MATH_LIBRARY`. Changed ``SUNDIALS_LOGGING_ENABLE_MPI`` CMake option default to be ``OFF``. This -fixes `GitHub Issue #177 `_. +fixes `GitHub Issue #177 `__. Changes to SUNDIALS in release 6.2.0 ==================================== @@ -1052,7 +1052,7 @@ namespace. A capability to profile/instrument SUNDIALS library code has been added. This can be enabled with the CMake option :cmakeop:`SUNDIALS_BUILD_WITH_PROFILING`. A built-in profiler will be used by default, but the `Caliper -`_ library can also be used instead with the +`__ library can also be used instead with the CMake option :cmakeop:`ENABLE_CALIPER`. See the documentation section on profiling for more details. @@ -2656,7 +2656,7 @@ these vectors both move all data to the GPU device upon construction, and speedup will only be realized if the user also conducts the right-hand-side function evaluation on the device. In addition, these vectors assume the problem fits on one GPU. For further information about RAJA, users are referred to the -`RAJA web site `_. +`RAJA web site `__. Added the type :c:type:`sunindextype` to support using 32-bit or 64-bit integer types for indexing arrays within all SUNDIALS structures. :c:type:`sunindextype` @@ -2680,11 +2680,11 @@ The file ``include/sundials_fconfig.h`` was added. This file contains SUNDIALS type information for use in Fortran programs. Added support for many xSDK-compliant build system keys. For more information on -on xSDK compliance the `xSDK policies `_. The xSDK +on xSDK compliance the `xSDK policies `__. The xSDK is a movement in scientific software to provide a foundation for the rapid and efficient production of high-quality, sustainable extreme-scale scientific applications. For more information visit the -`xSDK web site `_. +`xSDK web site `__. Added functions :c:func:`SUNDIALSGetVersion` and :c:func:`SUNDIALSGetVersionNumber` to get SUNDIALS release version information diff --git a/doc/shared/RecentChanges.rst b/doc/shared/RecentChanges.rst index 015e111fb9..6965215f07 100644 --- a/doc/shared/RecentChanges.rst +++ b/doc/shared/RecentChanges.rst @@ -21,8 +21,12 @@ specific linker flags e.g., MKL. **Bug Fixes** -Fixed c:func:`ARKodeResize` not using the default ``hscale`` when an argument of -``0`` was provided. +Fixed a `bug `__ in the sparse +matrix implementation of :c:func:`SUNMatScaleAddI` which caused out of bounds +writes unless ``indexvals`` were in ascending order for each row/column. + +Fixed :c:func:`ARKodeResize` not using the default ``hscale`` when an argument +of ``0`` was provided. Fixed the loading of ARKStep's default first order explicit method. diff --git a/examples/nvector/test_nvector.c b/examples/nvector/test_nvector.c index 4cd581001a..a7d5741522 100644 --- a/examples/nvector/test_nvector.c +++ b/examples/nvector/test_nvector.c @@ -48,7 +48,7 @@ /* all tests need a SUNContext */ SUNContext sunctx = NULL; -#if defined(SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS) +#if defined(SUNDIALS_HAVE_POSIX_TIMERS) static time_t base_time_tv_sec = 0; /* Base time; makes time values returned by get_time easier to read when printed since they will be zero @@ -5993,7 +5993,7 @@ int Test_N_VBufUnpack(N_Vector x, sunindextype local_length, int myid) void SetTiming(int onoff, int myid) { -#if defined(SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS) +#if defined(SUNDIALS_HAVE_POSIX_TIMERS) struct timespec spec; clock_gettime(CLOCK_MONOTONIC, &spec); base_time_tv_sec = spec.tv_sec; @@ -6016,7 +6016,7 @@ void SetTiming(int onoff, int myid) static double get_time(void) { double time; -#if defined(SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS) +#if defined(SUNDIALS_HAVE_POSIX_TIMERS) struct timespec spec; clock_gettime(CLOCK_MONOTONIC, &spec); time = (double)(spec.tv_sec - base_time_tv_sec) + diff --git a/examples/sunlinsol/test_sunlinsol.c b/examples/sunlinsol/test_sunlinsol.c index 2a6900e666..cec2cc9648 100644 --- a/examples/sunlinsol/test_sunlinsol.c +++ b/examples/sunlinsol/test_sunlinsol.c @@ -27,7 +27,7 @@ #include #include -#if defined(SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS) +#if defined(SUNDIALS_HAVE_POSIX_TIMERS) #include #include #endif @@ -519,7 +519,7 @@ int Test_SUNLinSolSolve(SUNLinearSolver S, SUNMatrix A, N_Vector x, N_Vector b, * Private functions * ====================================================================*/ -#if defined(SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS) +#if defined(SUNDIALS_HAVE_POSIX_TIMERS) time_t base_time_tv_sec = 0; /* Base time; makes time values returned by get_time easier to read when printed since they will be zero @@ -531,7 +531,7 @@ void SetTiming(int onoff) { print_time = onoff; -#if defined(SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS) +#if defined(SUNDIALS_HAVE_POSIX_TIMERS) struct timespec spec; clock_gettime(CLOCK_MONOTONIC, &spec); base_time_tv_sec = spec.tv_sec; @@ -543,7 +543,7 @@ void SetTiming(int onoff) * --------------------------------------------------------------------*/ static double get_time(void) { -#if defined(SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS) +#if defined(SUNDIALS_HAVE_POSIX_TIMERS) struct timespec spec; clock_gettime(CLOCK_MONOTONIC, &spec); double time = (double)(spec.tv_sec - base_time_tv_sec) + diff --git a/examples/sunmatrix/test_sunmatrix.c b/examples/sunmatrix/test_sunmatrix.c index 9849e308b2..47b2cf9296 100644 --- a/examples/sunmatrix/test_sunmatrix.c +++ b/examples/sunmatrix/test_sunmatrix.c @@ -27,7 +27,7 @@ #include #include -#if defined(SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS) +#if defined(SUNDIALS_HAVE_POSIX_TIMERS) #include #include #endif @@ -611,7 +611,7 @@ int Test_SUNMatSpace(SUNMatrix A, int myid) * Private functions * ====================================================================*/ -#if defined(SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS) +#if defined(SUNDIALS_HAVE_POSIX_TIMERS) time_t base_time_tv_sec = 0; /* Base time; makes time values returned by get_time easier to read when printed since they will be zero @@ -623,7 +623,7 @@ void SetTiming(int onoff) { print_time = onoff; -#if defined(SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS) +#if defined(SUNDIALS_HAVE_POSIX_TIMERS) struct timespec spec; clock_gettime(CLOCK_MONOTONIC, &spec); base_time_tv_sec = spec.tv_sec; @@ -637,7 +637,7 @@ void SetPrintAllRanks(int onoff) { print_all_ranks = onoff; } * --------------------------------------------------------------------*/ static double get_time(void) { -#if defined(SUNDIALS_HAVE_POSIX_TIMERS) && defined(_POSIX_TIMERS) +#if defined(SUNDIALS_HAVE_POSIX_TIMERS) struct timespec spec; clock_gettime(CLOCK_MONOTONIC, &spec); double time = (double)(spec.tv_sec - base_time_tv_sec) + diff --git a/src/sunmatrix/sparse/sunmatrix_sparse.c b/src/sunmatrix/sparse/sunmatrix_sparse.c index bbdbc344d2..89a1ca576a 100644 --- a/src/sunmatrix/sparse/sunmatrix_sparse.c +++ b/src/sunmatrix/sparse/sunmatrix_sparse.c @@ -2,6 +2,7 @@ * ----------------------------------------------------------------- * Programmer(s): Daniel Reynolds @ SMU * David Gardner @ LLNL + * Steven B. Roberts @ LLNL * Based on code sundials_sparse.c by: Carol Woodward and * Slaven Peles @ LLNL, and Daniel R. Reynolds @ SMU * ----------------------------------------------------------------- @@ -623,234 +624,72 @@ SUNErrCode SUNMatCopy_Sparse(SUNMatrix A, SUNMatrix B) SUNErrCode SUNMatScaleAddI_Sparse(sunrealtype c, SUNMatrix A) { - sunindextype j, i, p, nz, newvals, M, N, cend, nw; - sunbooleantype newmat, found; - sunindextype *w, *Ap, *Ai, *Cp, *Ci; - sunrealtype *x, *Ax, *Cx; - SUNMatrix C; SUNFunctionBegin(A->sunctx); + const sunindextype N = SM_SPARSETYPE_S(A) == CSC_MAT ? SM_COLUMNS_S(A) + : SM_ROWS_S(A); + const sunindextype M = SM_SPARSETYPE_S(A) == CSC_MAT ? SM_ROWS_S(A) + : SM_COLUMNS_S(A); - /* store shortcuts to matrix dimensions (M is inner dimension, N is outer) */ - if (SM_SPARSETYPE_S(A) == CSC_MAT) - { - M = SM_ROWS_S(A); - N = SM_COLUMNS_S(A); - } - else - { - M = SM_COLUMNS_S(A); - N = SM_ROWS_S(A); - } - - /* access data arrays from A */ - Ap = NULL; - Ai = NULL; - Ax = NULL; - Ap = SM_INDEXPTRS_S(A); + sunindextype* Ap = SM_INDEXPTRS_S(A); SUNAssert(Ap, SUN_ERR_ARG_CORRUPT); - Ai = SM_INDEXVALS_S(A); + sunindextype* Ai = SM_INDEXVALS_S(A); SUNAssert(Ai, SUN_ERR_ARG_CORRUPT); - Ax = SM_DATA_S(A); + sunrealtype* Ax = SM_DATA_S(A); SUNAssert(Ax, SUN_ERR_ARG_CORRUPT); - /* determine if A: contains values on the diagonal (so I can just be added - in); if not, then increment counter for extra storage that should be - required. */ - newvals = 0; - for (j = 0; j < SUNMIN(M, N); j++) + sunindextype newvals = 0; + for (sunindextype j = 0; j < N; j++) { /* scan column (row if CSR) of A, searching for diagonal value */ - found = SUNFALSE; - for (i = Ap[j]; i < Ap[j + 1]; i++) + sunbooleantype found = SUNFALSE; + for (sunindextype i = Ap[j]; i < Ap[j + 1]; i++) { if (Ai[i] == j) { found = SUNTRUE; - break; + Ax[i] = ONE + c * Ax[i]; } + else { Ax[i] *= c; } } - /* if no diagonal found, increment necessary storage counter */ - if (!found) { newvals += 1; } + /* If no diagonal element found and the current column (row) can actually + * contain a diagonal element, increment the storage counter */ + if (!found && j < M) { newvals++; } } - /* If extra nonzeros required, check whether matrix has sufficient storage - space for new nonzero entries (so I can be inserted into existing storage) - */ - newmat = SUNFALSE; /* no reallocation needed */ - if (newvals > (SM_NNZ_S(A) - Ap[N])) { newmat = SUNTRUE; } - - /* perform operation based on existing/necessary structure */ - - /* case 1: A already contains a diagonal */ - if (newvals == 0) + /* At this point, A has the correctly updated values except for any new + * diagonal elements that need to be added (of which there are newvals). Now, + * we allocate additional storage if needed */ + const sunindextype new_nnz = Ap[N] + newvals; + if (new_nnz > SM_NNZ_S(A)) { - /* iterate through columns, adding 1.0 to diagonal */ - for (j = 0; j < SUNMIN(M, N); j++) - { - for (i = Ap[j]; i < Ap[j + 1]; i++) - { - if (Ai[i] == j) { Ax[i] = ONE + c * Ax[i]; } - else { Ax[i] = c * Ax[i]; } - } - } - - /* case 2: A has sufficient storage, but does not already contain a - * diagonal */ + SUNCheckCall(SUNSparseMatrix_Reallocate(A, new_nnz)); + Ap = SM_INDEXPTRS_S(A); + Ai = SM_INDEXVALS_S(A); + Ax = SM_DATA_S(A); } - else if (!newmat) - { - /* create work arrays for nonzero row (column) indices and values in a - * single column (row) */ - w = (sunindextype*)malloc(M * sizeof(sunindextype)); - SUNAssert(w, SUN_ERR_MALLOC_FAIL); - x = (sunrealtype*)malloc(M * sizeof(sunrealtype)); - SUNAssert(x, SUN_ERR_MALLOC_FAIL); - /* determine storage location where last column (row) should end */ - nz = Ap[N] + newvals; - - /* store pointer past last column (row) from original A, - and store updated value in revised A */ - cend = Ap[N]; - Ap[N] = nz; - - /* iterate through columns (rows) backwards */ - for (j = N - 1; j >= 0; j--) + for (sunindextype j = N - 1; newvals > 0; j--) + { + sunbooleantype found = SUNFALSE; + for (sunindextype i = Ap[j + 1] - 1; i >= Ap[j]; i--) { - /* reset diagonal entry, in case it's not in A */ - x[j] = ZERO; - - /* iterate down column (row) of A, collecting nonzeros */ - for (p = Ap[j], i = 0; p < cend; p++, i++) - { - w[i] = Ai[p]; /* collect row (column) index */ - x[Ai[p]] = c * Ax[p]; /* collect/scale value */ - } + if (Ai[i] == j) { found = SUNTRUE; } - /* NNZ in this column (row) */ - nw = cend - Ap[j]; - - /* add identity to this column (row) */ - if (j < M) { x[j] += ONE; /* update value */ } - - /* fill entries of A with this column's (row's) data */ - /* fill entries past diagonal */ - for (i = nw - 1; i >= 0 && w[i] > j; i--) - { - Ai[--nz] = w[i]; - Ax[nz] = x[w[i]]; - } - /* fill diagonal if applicable */ - if (i < 0 /* empty or insert at front */ || - w[i] != j /* insert behind front */) - { - Ai[--nz] = j; - Ax[nz] = x[j]; - } - /* fill entries before diagonal */ - for (; i >= 0; i--) - { - Ai[--nz] = w[i]; - Ax[nz] = x[w[i]]; - } - - /* store ptr past this col (row) from orig A, update value for new A */ - cend = Ap[j]; - Ap[j] = nz; + /* Shift elements to make room for diagonal elements */ + Ai[i + newvals] = Ai[i]; + Ax[i + newvals] = Ax[i]; } - /* clean up */ - free(w); - free(x); - - /* case 3: A must be reallocated with sufficient storage */ - } - else - { - /* create work array for nonzero values in a single column (row) */ - x = (sunrealtype*)malloc(M * sizeof(sunrealtype)); - - /* create new matrix for sum */ - C = SUNSparseMatrix(SM_ROWS_S(A), SM_COLUMNS_S(A), Ap[N] + newvals, - SM_SPARSETYPE_S(A), A->sunctx); - SUNCheckLastErr(); - - /* access data from CSR structures (return if failure) */ - Cp = NULL; - Ci = NULL; - Cx = NULL; - Cp = SM_INDEXPTRS_S(C); - SUNAssert(Cp, SUN_ERR_ARG_CORRUPT); - Ci = SM_INDEXVALS_S(C); - SUNAssert(Ci, SUN_ERR_ARG_CORRUPT); - Cx = SM_DATA_S(C); - SUNAssert(Cx, SUN_ERR_ARG_CORRUPT); - - /* initialize total nonzero count */ - nz = 0; - - /* iterate through columns (rows for CSR) */ - for (j = 0; j < N; j++) + Ap[j + 1] += newvals; + if (!found && j < M) { - /* set current column (row) pointer to current # nonzeros */ - Cp[j] = nz; - - /* reset diagonal entry, in case it's not in A */ - x[j] = ZERO; - - /* iterate down column (along row) of A, collecting nonzeros */ - for (p = Ap[j]; p < Ap[j + 1]; p++) - { - x[Ai[p]] = c * Ax[p]; /* collect/scale value */ - } - - /* add identity to this column (row) */ - if (j < M) { x[j] += ONE; /* update value */ } - - /* fill entries of C with this column's (row's) data */ - /* fill entries before diagonal */ - for (p = Ap[j]; p < Ap[j + 1] && Ai[p] < j; p++) - { - Ci[nz] = Ai[p]; - Cx[nz++] = x[Ai[p]]; - } - /* fill diagonal if applicable */ - if (p >= Ap[j + 1] /* empty or insert at end */ || - Ai[p] != j /* insert before end */) - { - Ci[nz] = j; - Cx[nz++] = x[j]; - } - /* fill entries past diagonal */ - for (; p < Ap[j + 1]; p++) - { - Ci[nz] = Ai[p]; - Cx[nz++] = x[Ai[p]]; - } + /* This column (row) needs a diagonal element added */ + newvals--; + Ai[Ap[j] + newvals] = j; + Ax[Ap[j] + newvals] = ONE; } - - /* indicate end of data */ - Cp[N] = nz; - - /* update A's structure with C's values; nullify C's pointers */ - SM_NNZ_S(A) = SM_NNZ_S(C); - - if (SM_DATA_S(A)) { free(SM_DATA_S(A)); } - SM_DATA_S(A) = SM_DATA_S(C); - SM_DATA_S(C) = NULL; - - if (SM_INDEXVALS_S(A)) { free(SM_INDEXVALS_S(A)); } - SM_INDEXVALS_S(A) = SM_INDEXVALS_S(C); - SM_INDEXVALS_S(C) = NULL; - - if (SM_INDEXPTRS_S(A)) { free(SM_INDEXPTRS_S(A)); } - SM_INDEXPTRS_S(A) = SM_INDEXPTRS_S(C); - SM_INDEXPTRS_S(C) = NULL; - - /* clean up */ - SUNMatDestroy_Sparse(C); - free(x); } + return SUN_SUCCESS; } From 1770cd765ce1faf3c3de27b1f2e224ef6b2a33dd Mon Sep 17 00:00:00 2001 From: David Gardner Date: Tue, 8 Oct 2024 08:43:24 -0700 Subject: [PATCH 07/89] Doc: Add Function Documentation Style Guide (#588) Some recent PRs have included comments about stylistic inconsistencies in the documentation. This PR adds a style guide for documenting user-callable and user-supplied functions to hopefully reduce this kind of traffic in future PRs. --------- Co-authored-by: Daniel R. Reynolds --- doc/superbuild/source/conf.py | 11 +- .../developers/style_guide/Documentation.rst | 282 ++++++++++++++++-- 2 files changed, 271 insertions(+), 22 deletions(-) diff --git a/doc/superbuild/source/conf.py b/doc/superbuild/source/conf.py index 2a6fe2431c..5a4a6414b1 100644 --- a/doc/superbuild/source/conf.py +++ b/doc/superbuild/source/conf.py @@ -27,9 +27,14 @@ # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx_rtd_theme', 'sphinx.ext.ifconfig', 'sphinx.ext.mathjax', - 'sphinxfortran.fortran_domain', 'sphinxcontrib.bibtex', - 'sphinx_copybutton', 'sphinx.ext.graphviz', 'sphinx_sundials', - 'sphinx_toolbox.collapse'] + 'sphinx.ext.intersphinx', 'sphinxfortran.fortran_domain', + 'sphinxcontrib.bibtex', 'sphinx_copybutton', 'sphinx.ext.graphviz', + 'sphinx_sundials', 'sphinx_toolbox.collapse'] + +intersphinx_mapping = {"sphinx": ("https://www.sphinx-doc.org/en/master/", None),} + +# No non-external references will be resolved by intersphinx +intersphinx_disabled_reftypes = ["*"] # References bibtex_bibfiles = ['../../shared/sundials.bib'] diff --git a/doc/superbuild/source/developers/style_guide/Documentation.rst b/doc/superbuild/source/developers/style_guide/Documentation.rst index 63c9b294c1..92b6d02e86 100644 --- a/doc/superbuild/source/developers/style_guide/Documentation.rst +++ b/doc/superbuild/source/developers/style_guide/Documentation.rst @@ -127,28 +127,272 @@ All citations go into `doc/shared/sundials.bib`. TODO: add citation and reference key style. -Documenting Functions -===================== +User-Callable Functions +======================= -Adding New Functions --------------------- +Document user-callable functions with the :external+sphinx:rst:dir:`c:function` +or :external+sphinx:rst:dir:`cpp:function` directives, as appropriate. The +directive is followed by the C/C++ function signature. Under the signature +(skipping a line and indenting 3 spaces) provide a brief description of the +function followed by any information on its usage. When describing the function +parameters use ``:param :``. If the function returns a specific set of +SUNDIALS error codes, describe the possible return values using ``:retval +:`` for each value. Otherwise, use a single ``:returns:`` item to +describe the result of the function. If the function returns ``void``, a return +entry should not be included. Below we give two examples, the first returns an +error code (int) while the second is a constructor that returns an object +(pointer). -The documentation for new functions should include the ``.. versionadded::`` -directive at the end of the documentation text noting the *package version* -number in which the function was added. +.. code-block:: rst -Changes to Existing Functions ------------------------------ + .. c:function:: int SetFoo(param_type p1, param_type p2) -If the signature or behavior of a function changes in any release the -``.. versionchanged::`` directive should be added to the function documentation -noting the *package version* number in which the change happened and describing -the change. + Brief description of what the user-callable function does. -Deprecating Functions ---------------------- + Additional information about the function and its usage. -When a function is deprecated the ``.. deprecated::`` directive should be added -to the function documentation noting the *package version* number in which the -function was deprecated and describing what function should be used instead -if appropriate. + :param p1: description of the first parameter. + :param p2: description of the second parameter. + + :retval SUCCESS: under some conditions. + :retval FAILURE_1: under some other conditions. + :retval FAILURE_2: under yet some other conditions. + +.. code-block:: rst + + .. c:function:: FooObject CreateFooObject(param_type p1, param_type p2) + + Brief description of what the user-callable function does. + + Additional information about the function and its usage. + + :param p1: description of the first parameter. + :param p2: description of the second parameter. + + :returns: If successful some object, otherwise ``NULL``. + +When adding, updating, or deprecating a function, use the +:external+sphinx:rst:dir:`versionadded`, +:external+sphinx:rst:dir:`versionchanged`, or +:external+sphinx:rst:dir:`deprecated` directives with the placeholder version +number ``x.y.z`` after the return description. The release script will find and +replace all instances of ``x.y.z`` in the documentation with the actual release +number. When altering the behavior of a function or deprecating a function +include a description for the change under the directive (skipping a line and +indenting 3 spaces). For example, + +.. code-block:: rst + + .. versionadded:: x.y.z + +.. code-block:: rst + + .. versionchanged:: x.y.z + + Describe how the function behavior has changed from before. + +.. code-block:: rst + + .. deprecated:: x.y.z + + If a replacement function/procedure is available, describe what users + should do to replace the deprecated function e.g., cross reference the + function superseding this one or list the new steps to follow. Otherwise, + note the feature/capability is no longer supported/provided and, if + possible, state why this function was removed. + +If special attention needs to be drawn to some behavior, consideration, or +limitation of a function that could be overlooked in the description, use the +:external+sphinx:rst:dir:`note` or :external+sphinx:rst:dir:`warning` directives +as appropriate. These should be used sparingly to avoid diluting their impact. +For example, + +.. code-block:: rst + + .. note:: + + Something users should not over look e.g., a feature is only compatible + with a subset of methods. + +.. code-block:: rst + + .. warning:: + + Something critical users should be aware of e.g., performance impacts. + +Finally, at the end of the function documentation, you may include (a +non-trivial) example usage of the function and/or a list of example programs +that utilize the function. For example, + +.. code-block:: rst + + **Example usage:** + + .. code-block:: C + + /* Short code block demonstrating typical usage */ + + /* Create the object */ + FooObject foo_obj = CreateFooObject(p1, p2); + if (foo_obj == NULL) { return 1; } + + /* Attach the object to mem */ + int retval = SetFoo(mem, foo_obj); + if (retval != 0) { return 1; } + + /* Perform some actions */ + ... + + /* Destroy the object */ + retval = DestroyFooObject(&foo_obj); + if (retval != 0) { return 1; } + +.. code-block:: rst + + **Examples codes:** + + * ``examples/package/subdir/pkg_some_code.c`` + +Putting it all together, the rendered documentation should look like the +following. + +.. c:function:: int FooSetBar(void* foo_obj, int bar_value) + :nocontentsentry: + :noindexentry: + + This function sets the value of Bar in a FooObject. + + The default value for Bar is :math:`10`. An input value :math:`< 0` will + reset Bar to the default value. + + :param foo_obj: the FooObject. + :param bar_value: the value of Bar. + + :retval SUCCESS: if the value was successfully set. + :retval NULL_OBJ: if the ``foo_obj`` was ``NULL``. + + .. versionadded:: 1.1.0 + + .. versionchanged:: 2.0.0 + + The type of p1 was changed from ``unsigned int`` to ``int`` + + .. note:: + + Utilizing this capability requires building with Bar enabled. + + .. warning:: + + Setting values greater than 100 may degrade performance. + + **Example usage:** + + .. code-block:: C + + /* Create the object */ + void* foo_obj = CreateFooObject(p1, p2); + if (foo_obj == NULL) { return 1; } + + /* Update the value of Bar */ + int retval = FooSetBar(foo_obj, 50); + if (retval != 0) { return 1; } + + /* Perform some actions */ + ... + + **Examples codes:** + + * ``examples/package/subdir/pkg_foo_demo.c`` + + +User-Supplied Functions +======================= + +Document user-supplied functions with the :external+sphinx:rst:dir:`c:type` +directive. The directive is followed by the ``typedef`` for the function +pointer. The description of the function type mirrors the style used for +user-callable function with one exception. As :external+sphinx:rst:dir:`c:type` +does not currently support the ``param``, ``retval``, and ``returns`` fields, +these sections must be manually created. The style that follows is chosen to +reflect that of ``param``, ``retval``, and ``returns`` fields as much as +possible. Function parameters should be listed under a boldface "Parameters:" +section with the parameters in boldface and separated from their description by +an en-dash. As user-supplied functions typically return a ``int``, but specific +values are not required, a description of how the return value is interpreted +should be given under a boldface "Returns:" section (skipping a line and +indenting 2 spaces). If specific return values are required, these should be +documented similarly to the function parameters and listed under a boldface +"Return values:" section. If the function returns ``void``, a return section +should not be included. Below we give, two examples describing user-supplied +functions. + +.. code-block:: rst + + .. c:type:: int (*FooFn)(param_type p1, param_type p2) + + Brief description of what the user-provided function should do. + + Additional information about the function and its usage. + + **Parameters:** + + * **p1** -- description of the first parameter. + * **p2** -- description of the second parameter. + + **Returns:** + + A :c:type:`FooFn` function should return 0 if successful, a positive + value if a recoverable error occurred, or a negative value if an + unrecoverable error occurred. + +.. code-block:: rst + + .. c:type:: int (*BarFn)(param_type p1, param_type p2) + + Brief description of what the user-provided function should do. + + Additional information about the function and its usage. + + **Parameters:** + + * **p1** -- description of the first parameter. + * **p2** -- description of the second parameter. + + **Return values:** + + * **VALUE_1** -- under some circumstances. + * **VALUE_2** -- under some other circumstances. + +Other than the difference in the function parameter and return value sections +the remaining guidelines from the user-callable function documentation are the +same. Putting it all together, the rendered documentation should look like the +following. + +.. c:type:: int (*FooFn)(double* p1, double* p2) + :nocontentsentry: + :noindexentry: + + Brief description of what the user-provided function should do. + + Additional information about the function and its usage. + + **Parameters:** + + * **p1** -- the input array of values. + * **p2** -- the output array of values. + + **Returns:** + + A :c:type:`FooFn` function should return 0 if successful, a positive value + if a recoverable error occurred, or a negative value if an unrecoverable + error occurred. + + .. versionadded:: 2.2.0 + + .. note:: + + This function is required when using the Foo option. + + **Examples codes:** + + * ``examples/package/subdir/pkg_bar_demo.c`` From f7483ed9e30837253834ca5317bb93f75ce70c17 Mon Sep 17 00:00:00 2001 From: David Gardner Date: Mon, 14 Oct 2024 10:17:22 -0700 Subject: [PATCH 08/89] CI: Add concurrency in format/swig/spelling checks (#591) Cancel running formatting, swing, and spelling checks on new pushes to prevent redundant failure messages --- .github/workflows/check-format.yml | 4 ++++ .github/workflows/check-spelling.yml | 4 ++++ .github/workflows/check-swig.yml | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/.github/workflows/check-format.yml b/.github/workflows/check-format.yml index d052dfec97..f96e3cdaf7 100644 --- a/.github/workflows/check-format.yml +++ b/.github/workflows/check-format.yml @@ -6,6 +6,10 @@ on: issue_comment: types: [created] +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref_name }} + cancel-in-progress: true + jobs: format_check: if: ${{ github.event_name != 'issue_comment' || (github.event_name == 'issue_comment' && startsWith(github.event.comment.body, '/autofix')) }} diff --git a/.github/workflows/check-spelling.yml b/.github/workflows/check-spelling.yml index 16349e8891..70da910142 100644 --- a/.github/workflows/check-spelling.yml +++ b/.github/workflows/check-spelling.yml @@ -6,6 +6,10 @@ on: issue_comment: types: [created] +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref_name }} + cancel-in-progress: true + jobs: spelling_check: if: ${{ github.event_name != 'issue_comment' || (github.event_name == 'issue_comment' && startsWith(github.event.comment.body, '/autofix')) }} diff --git a/.github/workflows/check-swig.yml b/.github/workflows/check-swig.yml index 25a0bc16a2..2f9fad653d 100644 --- a/.github/workflows/check-swig.yml +++ b/.github/workflows/check-swig.yml @@ -6,6 +6,10 @@ on: issue_comment: types: [created] +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref_name }} + cancel-in-progress: true + jobs: swig_check: if: ${{ github.event_name != 'issue_comment' || (github.event_name == 'issue_comment' && startsWith(github.event.comment.body, '/autofix')) }} From 99215eeca696e2d8a37cd54e2dbc3220f5bf5c0b Mon Sep 17 00:00:00 2001 From: "Daniel R. Reynolds" Date: Tue, 15 Oct 2024 12:35:29 -0500 Subject: [PATCH 09/89] Bugfix: Erroneous deprecation warnings (#589) When moving the ARKODE user interface to a shared level and adding deprecation warnings to stepper-specific routines, some of the deprecation warnings seemed to have search/replace issues. This PR fixes those. --- include/arkode/arkode_erkstep.h | 30 +++++++++++++++--------------- include/arkode/arkode_mristep.h | 14 +++++++------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/include/arkode/arkode_erkstep.h b/include/arkode/arkode_erkstep.h index ed93a240b9..c40bab8112 100644 --- a/include/arkode/arkode_erkstep.h +++ b/include/arkode/arkode_erkstep.h @@ -109,7 +109,7 @@ SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetMaxGrowth instead") int ERKStepSetMaxGrowth(void* arkode_mem, sunrealtype mx_growth); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetMinReduction instead") int ERKStepSetMinReduction(void* arkode_mem, sunrealtype eta_min); -SUNDIALS_DEPRECATED_EXPORT_MSG("use ERKStepSetFiARKodeBounds instead") +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetFixedStepBounds instead") int ERKStepSetFixedStepBounds(void* arkode_mem, sunrealtype lb, sunrealtype ub); SUNDIALS_DEPRECATED_EXPORT_MSG("use SUNAdaptController instead") int ERKStepSetAdaptivityMethod(void* arkode_mem, int imethod, int idefault, @@ -128,15 +128,15 @@ SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetMaxErrTestFails instead") int ERKStepSetMaxErrTestFails(void* arkode_mem, int maxnef); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetConstraints instead") int ERKStepSetConstraints(void* arkode_mem, N_Vector constraints); -SUNDIALS_DEPRECATED_EXPORT_MSG("use ERKStepSetMaxARKodes instead") +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetMaxNumSteps instead") int ERKStepSetMaxNumSteps(void* arkode_mem, long int mxsteps); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetMaxHnilWarns instead") int ERKStepSetMaxHnilWarns(void* arkode_mem, int mxhnil); -SUNDIALS_DEPRECATED_EXPORT_MSG("use ERKStepSetIARKode instead") +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetInitStep instead") int ERKStepSetInitStep(void* arkode_mem, sunrealtype hin); -SUNDIALS_DEPRECATED_EXPORT_MSG("use ERKStepSetARKode instead") +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetMinStep instead") int ERKStepSetMinStep(void* arkode_mem, sunrealtype hmin); -SUNDIALS_DEPRECATED_EXPORT_MSG("use ERKStepSetARKode instead") +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetMaxStep instead") int ERKStepSetMaxStep(void* arkode_mem, sunrealtype hmax); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetInterpolateStopTime instead") int ERKStepSetInterpolateStopTime(void* arkode_mem, sunbooleantype interp); @@ -144,7 +144,7 @@ SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetStopTime instead") int ERKStepSetStopTime(void* arkode_mem, sunrealtype tstop); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeClearStopTime instead") int ERKStepClearStopTime(void* arkode_mem); -SUNDIALS_DEPRECATED_EXPORT_MSG("use ERKStepSetFiARKode instead") +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetFixedStep instead") int ERKStepSetFixedStep(void* arkode_mem, sunrealtype hfixed); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetMaxNumConstrFails instead") int ERKStepSetMaxNumConstrFails(void* arkode_mem, int maxfails); @@ -154,7 +154,7 @@ SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetNoInactiveRootWarn instead") int ERKStepSetNoInactiveRootWarn(void* arkode_mem); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetUserData instead") int ERKStepSetUserData(void* arkode_mem, void* user_data); -SUNDIALS_DEPRECATED_EXPORT_MSG("use ERKStepSetPostprocARKodeFn instead") +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetPostprocessStepFn instead") int ERKStepSetPostprocessStepFn(void* arkode_mem, ARKPostProcessFn ProcessStep); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetPostprocessStageFn instead") int ERKStepSetPostprocessStageFn(void* arkode_mem, ARKPostProcessFn ProcessStage); @@ -163,11 +163,11 @@ int ERKStepEvolve(void* arkode_mem, sunrealtype tout, N_Vector yout, sunrealtype* tret, int itask); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetDky instead") int ERKStepGetDky(void* arkode_mem, sunrealtype t, int k, N_Vector dky); -SUNDIALS_DEPRECATED_EXPORT_MSG("use ERKStepGetNumARKodes instead") +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetNumExpSteps instead") int ERKStepGetNumExpSteps(void* arkode_mem, long int* expsteps); -SUNDIALS_DEPRECATED_EXPORT_MSG("use ERKStepGetNumARKodes instead") +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetNumAccSteps instead") int ERKStepGetNumAccSteps(void* arkode_mem, long int* accsteps); -SUNDIALS_DEPRECATED_EXPORT_MSG("use ERKStepGetARKodeAttempts instead") +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetNumStepAttempts instead") int ERKStepGetNumStepAttempts(void* arkode_mem, long int* step_attempts); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetNumErrTestFails instead") int ERKStepGetNumErrTestFails(void* arkode_mem, long int* netfails); @@ -175,13 +175,13 @@ SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetEstLocalErrors instead") int ERKStepGetEstLocalErrors(void* arkode_mem, N_Vector ele); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetWorkSpace instead") int ERKStepGetWorkSpace(void* arkode_mem, long int* lenrw, long int* leniw); -SUNDIALS_DEPRECATED_EXPORT_MSG("use ERKStepGetARKodes instead") +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetNumSteps instead") int ERKStepGetNumSteps(void* arkode_mem, long int* nsteps); -SUNDIALS_DEPRECATED_EXPORT_MSG("use ERKStepGetActualIARKode instead") +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetActualInitStep instead") int ERKStepGetActualInitStep(void* arkode_mem, sunrealtype* hinused); -SUNDIALS_DEPRECATED_EXPORT_MSG("use ERKStepGetLARKode instead") +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetLastStep instead") int ERKStepGetLastStep(void* arkode_mem, sunrealtype* hlast); -SUNDIALS_DEPRECATED_EXPORT_MSG("use ERKStepGetCurrARKode instead") +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetCurrentStep instead") int ERKStepGetCurrentStep(void* arkode_mem, sunrealtype* hcur); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetCurrentTime instead") int ERKStepGetCurrentTime(void* arkode_mem, sunrealtype* tcur); @@ -206,7 +206,7 @@ int ERKStepWriteParameters(void* arkode_mem, FILE* fp); SUNDIALS_DEPRECATED_EXPORT_MSG( "use ERKStepGetCurrentButcherTable and ARKodeButcherTable_Write instead") int ERKStepWriteButcher(void* arkode_mem, FILE* fp); -SUNDIALS_DEPRECATED_EXPORT_MSG("use ERKStepARKodeStats instead") +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetStepStats instead") int ERKStepGetStepStats(void* arkode_mem, long int* nsteps, sunrealtype* hinused, sunrealtype* hlast, sunrealtype* hcur, sunrealtype* tcur); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeFree instead") diff --git a/include/arkode/arkode_mristep.h b/include/arkode/arkode_mristep.h index 000bae135a..7fa2219e1e 100644 --- a/include/arkode/arkode_mristep.h +++ b/include/arkode/arkode_mristep.h @@ -223,7 +223,7 @@ SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetLinear instead") int MRIStepSetLinear(void* arkode_mem, int timedepend); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetNonlinear instead") int MRIStepSetNonlinear(void* arkode_mem); -SUNDIALS_DEPRECATED_EXPORT_MSG("use MRIStepSetMaxARKodes instead") +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetMaxNumSteps instead") int MRIStepSetMaxNumSteps(void* arkode_mem, long int mxsteps); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetNonlinCRDown instead") int MRIStepSetNonlinCRDown(void* arkode_mem, sunrealtype crdown); @@ -247,7 +247,7 @@ SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetStopTime instead") int MRIStepSetStopTime(void* arkode_mem, sunrealtype tstop); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeClearStopTime instead") int MRIStepClearStopTime(void* arkode_mem); -SUNDIALS_DEPRECATED_EXPORT_MSG("use MRIStepSetFiARKode instead") +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetFixedStep instead") int MRIStepSetFixedStep(void* arkode_mem, sunrealtype hsfixed); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetRootDirection instead") int MRIStepSetRootDirection(void* arkode_mem, int* rootdir); @@ -255,7 +255,7 @@ SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetNoInactiveRootWarn instead") int MRIStepSetNoInactiveRootWarn(void* arkode_mem); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetUserData instead") int MRIStepSetUserData(void* arkode_mem, void* user_data); -SUNDIALS_DEPRECATED_EXPORT_MSG("use MRIStepSetPostprocARKodeFn instead") +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetPostprocessStepFn instead") int MRIStepSetPostprocessStepFn(void* arkode_mem, ARKPostProcessFn ProcessStep); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeSetPostprocessStageFn instead") int MRIStepSetPostprocessStageFn(void* arkode_mem, ARKPostProcessFn ProcessStage); @@ -294,9 +294,9 @@ SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetNumLinSolvSetups instead") int MRIStepGetNumLinSolvSetups(void* arkode_mem, long int* nlinsetups); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetWorkSpace instead") int MRIStepGetWorkSpace(void* arkode_mem, long int* lenrw, long int* leniw); -SUNDIALS_DEPRECATED_EXPORT_MSG("use MRIStepGetARKodes instead") +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetNumSteps instead") int MRIStepGetNumSteps(void* arkode_mem, long int* nssteps); -SUNDIALS_DEPRECATED_EXPORT_MSG("use MRIStepGetLARKode instead") +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetLastStep instead") int MRIStepGetLastStep(void* arkode_mem, sunrealtype* hlast); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetCurrentTime instead") int MRIStepGetCurrentTime(void* arkode_mem, sunrealtype* tcur); @@ -335,13 +335,13 @@ int MRIStepGetNumNonlinSolvConvFails(void* arkode_mem, long int* nnfails); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetNonlinSolvStats instead") int MRIStepGetNonlinSolvStats(void* arkode_mem, long int* nniters, long int* nnfails); -SUNDIALS_DEPRECATED_EXPORT_MSG("use MRIStepGetARKodeSolveFails instead") +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetNumStepSolveFails instead") int MRIStepGetNumStepSolveFails(void* arkode_mem, long int* nncfails); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetJac instead") int MRIStepGetJac(void* arkode_mem, SUNMatrix* J); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetJacTime instead") int MRIStepGetJacTime(void* arkode_mem, sunrealtype* t_J); -SUNDIALS_DEPRECATED_EXPORT_MSG("use MRIStepGetJacARKodes instead") +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetJacNumSteps instead") int MRIStepGetJacNumSteps(void* arkode_mem, long* nst_J); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetLinWorkSpace instead") int MRIStepGetLinWorkSpace(void* arkode_mem, long int* lenrwLS, From 554fa923c8216662219f277c4ea50e9e5996c077 Mon Sep 17 00:00:00 2001 From: David Gardner Date: Tue, 15 Oct 2024 12:58:53 -0700 Subject: [PATCH 10/89] Feature: ARKodeGetNumRhsEvals (#587) Add an ARKODE level function to get the number of RHS evaluations --------- Co-authored-by: Daniel R. Reynolds Co-authored-by: Steven Roberts --- CHANGELOG.md | 3 + .../kokkos/arkode_driver.cpp | 16 +++-- .../raja/arkode_driver.cpp | 16 +++-- .../source/Usage/ARKStep/User_callable.rst | 3 + .../source/Usage/ERKStep/User_callable.rst | 3 + .../source/Usage/MRIStep/User_callable.rst | 3 + .../source/Usage/SPRKStep/User_callable.rst | 3 + .../guide/source/Usage/User_callable.rst | 34 +++++++++++ doc/shared/RecentChanges.rst | 4 ++ .../ark_brusselator1D_task_local_nls.cpp | 10 ++-- .../CXX_parallel/ark_diffusion_reaction_p.cpp | 24 ++++---- examples/arkode/CXX_parallel/ark_heat2D_p.cpp | 6 +- .../arkode/CXX_parhyp/ark_heat2D_hypre_ls.cpp | 6 +- .../CXX_parhyp/ark_heat2D_hypre_pfmg.cpp | 6 +- .../CXX_parhyp/ark_heat2D_hypre_pfmg_imex.cpp | 9 ++- .../ark_heat2D_hypre_pfmg_imex_--np_2_2.out | 3 +- .../CXX_parhyp/ark_heat2D_hypre_pfmg_mri.cpp | 15 +++-- .../ark_heat2D_hypre_pfmg_mri_--np_2_2.out | 3 +- .../ark_advection_diffusion_reaction.hpp | 28 +++++---- .../arkode/CXX_serial/ark_analytic_sys.cpp | 6 +- examples/arkode/CXX_serial/ark_heat2D.cpp | 6 +- examples/arkode/CXX_serial/ark_kpr_Mt.cpp | 6 +- examples/arkode/CXX_serial/ark_pendulum.cpp | 7 ++- .../ark_brusselator1D_FEM_sludist.cpp | 6 +- .../ark_heat2D_hypre_pfmg_xbraid.cpp | 6 +- .../arkode/CXX_xbraid/ark_heat2D_p_xbraid.cpp | 6 +- .../arkode/CXX_xbraid/ark_heat2D_xbraid.cpp | 6 +- .../C_manyvector/ark_brusselator1D_manyvec.c | 6 +- .../arkode/C_openmp/ark_brusselator1D_omp.c | 6 +- examples/arkode/C_openmp/ark_heat1D_omp.c | 6 +- .../C_openmpdev/ark_analytic_nonlin_ompdev.c | 4 +- .../arkode/C_openmpdev/ark_heat1D_ompdev.c | 6 +- .../ark_brusselator1D_task_local_nls.c | 10 ++-- .../arkode/C_parallel/ark_diurnal_kry_bbd_p.c | 6 +- .../arkode/C_parallel/ark_diurnal_kry_p.c | 6 +- examples/arkode/C_parhyp/ark_diurnal_kry_ph.c | 6 +- .../arkode/C_serial/ark_KrylovDemo_prec.c | 12 ++-- examples/arkode/C_serial/ark_analytic.c | 6 +- examples/arkode/C_serial/ark_analytic_mels.c | 6 +- examples/arkode/C_serial/ark_brusselator.c | 6 +- examples/arkode/C_serial/ark_brusselator1D.c | 6 +- .../C_serial/ark_brusselator1D_FEM_slu.c | 6 +- .../C_serial/ark_brusselator1D_imexmri.c | 12 ++-- .../arkode/C_serial/ark_brusselator1D_klu.c | 6 +- .../arkode/C_serial/ark_brusselator_1D_mri.c | 10 ++-- examples/arkode/C_serial/ark_brusselator_fp.c | 6 +- .../arkode/C_serial/ark_brusselator_mri.c | 10 ++-- .../C_serial/ark_conserved_exp_entropy_ark.c | 7 ++- .../C_serial/ark_conserved_exp_entropy_erk.c | 4 +- .../C_serial/ark_dissipated_exp_entropy.c | 7 ++- examples/arkode/C_serial/ark_heat1D.c | 6 +- examples/arkode/C_serial/ark_kpr_mri.c | 12 ++-- .../arkode/C_serial/ark_onewaycouple_mri.c | 10 ++-- .../C_serial/ark_robertson_constraints.c | 6 +- examples/arkode/C_serial/ark_robertson_root.c | 6 +- .../arkode/C_serial/ark_twowaycouple_mri.c | 10 ++-- .../ark_analytic_complex_f2003.f90 | 3 +- .../F2003_custom/ark_brusselator1D_f2003.f90 | 3 +- ...ark_brusselator1D_task_local_nls_f2003.f90 | 14 +++-- .../F2003_parallel/ark_diag_kry_bbd_f2003.f90 | 20 +++++-- .../F2003_parallel/ark_diag_non_f2003.f90 | 8 +-- .../F2003_parallel/ark_heat2D_f2003.f90 | 10 +++- .../F2003_serial/ark_analytic_f2003.f90 | 7 +-- .../ark_bruss1D_FEM_klu_f2003.f90 | 10 +++- .../arkode/F2003_serial/ark_bruss_f2003.f90 | 10 +++- .../F2003_serial/ark_diurnal_kry_bp_f2003.f90 | 10 +++- .../arkode/F2003_serial/ark_kpr_mri_f2003.f90 | 7 ++- .../F2003_serial/ark_roberts_dnsL_f2003.f90 | 10 +++- .../F2003_serial/ark_roberts_dns_f2003.f90 | 10 +++- include/arkode/arkode.h | 2 + include/arkode/arkode_arkstep.h | 6 +- include/arkode/arkode_erkstep.h | 3 +- include/arkode/arkode_mristep.h | 5 +- include/arkode/arkode_sprkstep.h | 4 +- src/arkode/arkode.c | 1 + src/arkode/arkode_arkstep.c | 1 + src/arkode/arkode_arkstep_impl.h | 2 + src/arkode/arkode_arkstep_io.c | 51 ++++++++++++---- src/arkode/arkode_erkstep.c | 1 + src/arkode/arkode_erkstep_impl.h | 2 + src/arkode/arkode_erkstep_io.c | 39 ++++++++---- src/arkode/arkode_impl.h | 3 + src/arkode/arkode_io.c | 32 ++++++++++ src/arkode/arkode_mristep.c | 1 + src/arkode/arkode_mristep_impl.h | 2 + src/arkode/arkode_mristep_io.c | 51 ++++++++++++---- src/arkode/arkode_sprkstep.c | 1 + src/arkode/arkode_sprkstep_impl.h | 2 + src/arkode/arkode_sprkstep_io.c | 51 ++++++++++++---- src/arkode/fmod_int32/farkode_arkstep_mod.c | 32 +++++----- src/arkode/fmod_int32/farkode_arkstep_mod.f90 | 60 +++++++++---------- src/arkode/fmod_int32/farkode_erkstep_mod.c | 28 ++++----- src/arkode/fmod_int32/farkode_erkstep_mod.f90 | 52 ++++++++-------- src/arkode/fmod_int32/farkode_mod.c | 16 +++++ src/arkode/fmod_int32/farkode_mod.f90 | 30 ++++++++++ src/arkode/fmod_int32/farkode_mristep_mod.c | 32 +++++----- src/arkode/fmod_int32/farkode_mristep_mod.f90 | 60 +++++++++---------- src/arkode/fmod_int32/farkode_sprkstep_mod.c | 32 +++++----- .../fmod_int32/farkode_sprkstep_mod.f90 | 60 +++++++++---------- src/arkode/fmod_int64/farkode_arkstep_mod.c | 32 +++++----- src/arkode/fmod_int64/farkode_arkstep_mod.f90 | 60 +++++++++---------- src/arkode/fmod_int64/farkode_erkstep_mod.c | 28 ++++----- src/arkode/fmod_int64/farkode_erkstep_mod.f90 | 52 ++++++++-------- src/arkode/fmod_int64/farkode_mod.c | 16 +++++ src/arkode/fmod_int64/farkode_mod.f90 | 30 ++++++++++ src/arkode/fmod_int64/farkode_mristep_mod.c | 32 +++++----- src/arkode/fmod_int64/farkode_mristep_mod.f90 | 60 +++++++++---------- src/arkode/fmod_int64/farkode_sprkstep_mod.c | 32 +++++----- .../fmod_int64/farkode_sprkstep_mod.f90 | 60 +++++++++---------- test/answers | 2 +- .../CXX_parallel/ark_test_heat2D_mri.cpp | 12 ++-- .../CXX_serial/ark_test_analytic_sys_mri.cpp | 12 ++-- .../CXX_serial/ark_test_dahlquist_ark.cpp | 7 ++- .../CXX_serial/ark_test_dahlquist_erk.cpp | 4 +- .../CXX_serial/ark_test_dahlquist_mri.cpp | 7 ++- 115 files changed, 1070 insertions(+), 614 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 138ba4ada0..2aff004841 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,9 @@ using `ENABLE_KLU=ON` in combination with a static-only build of SuiteSparse. ### Deprecation Notices +The ARKODE stepper specific functions to retrieve the number of right-hand side +function evaluations have been deprecated. Use `ARKodeGetNumRhsEvals` instead. + ## Changes to SUNDIALS in release 7.1.1 ### Bug Fixes diff --git a/benchmarks/advection_reaction_3D/kokkos/arkode_driver.cpp b/benchmarks/advection_reaction_3D/kokkos/arkode_driver.cpp index 4f606bd7bf..8330eafb70 100644 --- a/benchmarks/advection_reaction_3D/kokkos/arkode_driver.cpp +++ b/benchmarks/advection_reaction_3D/kokkos/arkode_driver.cpp @@ -189,8 +189,10 @@ int EvolveProblemDIRK(N_Vector y, UserData* udata, UserOptions* uopt) check_retval(&retval, "ARKodeGetNumSteps", 1, udata->myid); retval = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_retval(&retval, "ARKodeGetNumStepAttempts", 1, udata->myid); - retval = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_retval(&retval, "ARKStepGetNumRhsEvals", 1, udata->myid); + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1, udata->myid); + retval = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1, udata->myid); retval = ARKodeGetNumErrTestFails(arkode_mem, &netf); check_retval(&retval, "ARKodeGetNumErrTestFails", 1, udata->myid); retval = ARKodeGetNumNonlinSolvIters(arkode_mem, &nni); @@ -392,8 +394,10 @@ int EvolveProblemIMEX(N_Vector y, UserData* udata, UserOptions* uopt) check_retval(&retval, "ARKodeGetNumSteps", 1, udata->myid); retval = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_retval(&retval, "ARKodeGetNumStepAttempts", 1, udata->myid); - retval = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_retval(&retval, "ARKStepGetNumRhsEvals", 1, udata->myid); + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1, udata->myid); + retval = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1, udata->myid); retval = ARKodeGetNumErrTestFails(arkode_mem, &netf); check_retval(&retval, "ARKodeGetNumErrTestFails", 1, udata->myid); retval = ARKodeGetNumNonlinSolvIters(arkode_mem, &nni); @@ -516,8 +520,8 @@ int EvolveProblemExplicit(N_Vector y, UserData* udata, UserOptions* uopt) check_retval(&retval, "ARKodeGetNumSteps", 1, udata->myid); retval = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_retval(&retval, "ARKodeGetNumStepAttempts", 1, udata->myid); - retval = ERKStepGetNumRhsEvals(arkode_mem, &nfe); - check_retval(&retval, "ERKStepGetNumRhsEvals", 1, udata->myid); + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1, udata->myid); retval = ARKodeGetNumErrTestFails(arkode_mem, &netf); check_retval(&retval, "ARKodeGetNumErrTestFails", 1, udata->myid); diff --git a/benchmarks/advection_reaction_3D/raja/arkode_driver.cpp b/benchmarks/advection_reaction_3D/raja/arkode_driver.cpp index 420c9d63c9..fd59c98f87 100644 --- a/benchmarks/advection_reaction_3D/raja/arkode_driver.cpp +++ b/benchmarks/advection_reaction_3D/raja/arkode_driver.cpp @@ -190,8 +190,10 @@ int EvolveProblemDIRK(N_Vector y, UserData* udata, UserOptions* uopt) check_retval(&retval, "ARKodeGetNumSteps", 1, udata->myid); retval = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_retval(&retval, "ARKodeGetNumStepAttempts", 1, udata->myid); - retval = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_retval(&retval, "ARKStepGetNumRhsEvals", 1, udata->myid); + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1, udata->myid); + retval = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1, udata->myid); retval = ARKodeGetNumErrTestFails(arkode_mem, &netf); check_retval(&retval, "ARKodeGetNumErrTestFails", 1, udata->myid); retval = ARKodeGetNumNonlinSolvIters(arkode_mem, &nni); @@ -394,8 +396,10 @@ int EvolveProblemIMEX(N_Vector y, UserData* udata, UserOptions* uopt) check_retval(&retval, "ARKodeGetNumSteps", 1, udata->myid); retval = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_retval(&retval, "ARKodeGetNumStepAttempts", 1, udata->myid); - retval = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_retval(&retval, "ARKStepGetNumRhsEvals", 1, udata->myid); + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1, udata->myid); + retval = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1, udata->myid); retval = ARKodeGetNumErrTestFails(arkode_mem, &netf); check_retval(&retval, "ARKodeGetNumErrTestFails", 1, udata->myid); retval = ARKodeGetNumNonlinSolvIters(arkode_mem, &nni); @@ -519,8 +523,8 @@ int EvolveProblemExplicit(N_Vector y, UserData* udata, UserOptions* uopt) check_retval(&retval, "ARKodeGetNumSteps", 1, udata->myid); retval = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_retval(&retval, "ARKodeGetNumStepAttempts", 1, udata->myid); - retval = ERKStepGetNumRhsEvals(arkode_mem, &nfe); - check_retval(&retval, "ERKStepGetNumRhsEvals", 1, udata->myid); + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1, udata->myid); retval = ARKodeGetNumErrTestFails(arkode_mem, &netf); check_retval(&retval, "ARKodeGetNumErrTestFails", 1, udata->myid); diff --git a/doc/arkode/guide/source/Usage/ARKStep/User_callable.rst b/doc/arkode/guide/source/Usage/ARKStep/User_callable.rst index 5a21f7ea15..bef540030c 100644 --- a/doc/arkode/guide/source/Usage/ARKStep/User_callable.rst +++ b/doc/arkode/guide/source/Usage/ARKStep/User_callable.rst @@ -3155,6 +3155,9 @@ Main solver optional output functions The *nfi_evals* value does not account for calls made to :math:`f^I` by a linear solver or preconditioner module. + .. deprecated:: x.y.z + + Use :c:func:`ARKodeGetNumRhsEvals` instead. .. c:function:: int ARKStepGetNumErrTestFails(void* arkode_mem, long int* netfails) diff --git a/doc/arkode/guide/source/Usage/ERKStep/User_callable.rst b/doc/arkode/guide/source/Usage/ERKStep/User_callable.rst index 5bbb3e1f63..6c7b7b9cdf 100644 --- a/doc/arkode/guide/source/Usage/ERKStep/User_callable.rst +++ b/doc/arkode/guide/source/Usage/ERKStep/User_callable.rst @@ -1739,6 +1739,9 @@ Main solver optional output functions * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory was ``NULL`` + .. deprecated:: x.y.z + + Use :c:func:`ARKodeGetNumRhsEvals` instead. .. c:function:: int ERKStepGetNumErrTestFails(void* arkode_mem, long int* netfails) diff --git a/doc/arkode/guide/source/Usage/MRIStep/User_callable.rst b/doc/arkode/guide/source/Usage/MRIStep/User_callable.rst index bf00365669..a6354a6037 100644 --- a/doc/arkode/guide/source/Usage/MRIStep/User_callable.rst +++ b/doc/arkode/guide/source/Usage/MRIStep/User_callable.rst @@ -1895,6 +1895,9 @@ Main solver optional output functions * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` + .. deprecated:: x.y.z + + Use :c:func:`ARKodeGetNumRhsEvals` instead. .. c:function:: int MRIStepGetNumStepSolveFails(void* arkode_mem, long int* ncnf) diff --git a/doc/arkode/guide/source/Usage/SPRKStep/User_callable.rst b/doc/arkode/guide/source/Usage/SPRKStep/User_callable.rst index 7d5950fa77..73bde21f90 100644 --- a/doc/arkode/guide/source/Usage/SPRKStep/User_callable.rst +++ b/doc/arkode/guide/source/Usage/SPRKStep/User_callable.rst @@ -784,6 +784,9 @@ Main solver optional output functions :retval ARK_SUCCESS: if successful :retval ARK_MEM_NULL: if the SPRKStep memory was ``NULL`` + .. deprecated:: x.y.z + + Use :c:func:`ARKodeGetNumRhsEvals` instead. .. c:function:: int SPRKStepGetCurrentMethod(void* arkode_mem, ARKodeSPRKTable *sprk_table) diff --git a/doc/arkode/guide/source/Usage/User_callable.rst b/doc/arkode/guide/source/Usage/User_callable.rst index fd9b572382..98de3a33b6 100644 --- a/doc/arkode/guide/source/Usage/User_callable.rst +++ b/doc/arkode/guide/source/Usage/User_callable.rst @@ -3165,6 +3165,7 @@ Name of constant associated with a return flag :c:func:`ARKodeGetReturnF No. of explicit stability-limited steps :c:func:`ARKodeGetNumExpSteps` No. of accuracy-limited steps :c:func:`ARKodeGetNumAccSteps` No. of attempted steps :c:func:`ARKodeGetNumStepAttempts` +No. of RHS evaluations :c:func:`ARKodeGetNumRhsEvals` No. of local error test failures that have occurred :c:func:`ARKodeGetNumErrTestFails` No. of failed steps due to a nonlinear solver failure :c:func:`ARKodeGetNumStepSolveFails` Estimated local truncation error vector :c:func:`ARKodeGetEstLocalErrors` @@ -3470,6 +3471,39 @@ Retrieve a pointer for user data :c:func:`ARKodeGetUserDat .. versionadded:: 6.1.0 +.. c:function:: int ARKodeGetNumRhsEvals(void* arkode_mem, int partition_index, long int* num_rhs_evals) + + Returns the number of calls to the user's right-hand side function (so far). + For implicit methods or methods with an implicit partition, the count does + not include calls made by a linear solver or preconditioner. + + :param arkode_mem: pointer to the ARKODE memory block. + :param num_partition: the right-hand side partition index: + + * For ERKStep, ``0`` corresponds to :math:`f(t,y)` + + * For ARKStep, ``0`` corresponds to :math:`f^E(t,y)` and + ``1`` to :math:`f^I(t,y)` + + * For MRIStep, ``0`` corresponds to :math:`f^E(t,y)` and + ``1`` to :math:`f^I(t,y)` + + * For SPRKStep, ``0`` corresponds to :math:`f_1(t,p)` and + ``1`` to :math:`f_2(t,q)` + + A negative index will return the sum of the evaluations for + each partition. + + :param num_rhs_evals: the number of right-hand side evaluations. + + :retval ARK_SUCCESS: the function exited successfully. + :retval ARK_MEM_NULL: if ``arkode_mem`` was ``NULL``. + :retval ARK_ILL_INPUT: if ``num_partiton`` was invalid for the stepper or + ``num_rhs_evals`` was ``NULL`` + + .. versionadded:: x.y.z + + .. c:function:: int ARKodeGetNumErrTestFails(void* arkode_mem, long int* netfails) Returns the number of local error test failures that diff --git a/doc/shared/RecentChanges.rst b/doc/shared/RecentChanges.rst index 6965215f07..875d45c9b7 100644 --- a/doc/shared/RecentChanges.rst +++ b/doc/shared/RecentChanges.rst @@ -43,3 +43,7 @@ Fixed a CMake configuration issue related to aliasing an ``ALIAS`` target when using ``ENABLE_KLU=ON`` in combination with a static-only build of SuiteSparse. **Deprecation Notices** + +The ARKODE stepper specific functions to retrieve the number of right-hand side +function evaluations have been deprecated. Use :c:func:`ARKodeGetNumRhsEvals` +instead. diff --git a/examples/arkode/CXX_parallel/ark_brusselator1D_task_local_nls.cpp b/examples/arkode/CXX_parallel/ark_brusselator1D_task_local_nls.cpp index a44b52ea67..cbf3f23bd4 100644 --- a/examples/arkode/CXX_parallel/ark_brusselator1D_task_local_nls.cpp +++ b/examples/arkode/CXX_parallel/ark_brusselator1D_task_local_nls.cpp @@ -334,8 +334,10 @@ int EvolveProblemIMEX(SUNContext ctx, N_Vector y, UserData* udata, check_retval(&retval, "ARKodeGetNumSteps", 1); retval = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_retval(&retval, "ARKodeGetNumStepAttempts", 1); - retval = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_retval(&retval, "ARKStepGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); retval = ARKodeGetNumErrTestFails(arkode_mem, &netf); check_retval(&retval, "ARKodeGetNumErrTestFails", 1); retval = ARKodeGetNumNonlinSolvIters(arkode_mem, &nni); @@ -443,8 +445,8 @@ int EvolveProblemExplicit(SUNContext ctx, N_Vector y, UserData* udata, check_retval(&retval, "ARKodeGetNumSteps", 1); retval = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_retval(&retval, "ARKodeGetNumStepAttempts", 1); - retval = ERKStepGetNumRhsEvals(arkode_mem, &nfe); - check_retval(&retval, "ERKStepGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); retval = ARKodeGetNumErrTestFails(arkode_mem, &netf); check_retval(&retval, "ARKodeGetNumErrTestFails", 1); diff --git a/examples/arkode/CXX_parallel/ark_diffusion_reaction_p.cpp b/examples/arkode/CXX_parallel/ark_diffusion_reaction_p.cpp index 5643211620..5dd2bbd43b 100644 --- a/examples/arkode/CXX_parallel/ark_diffusion_reaction_p.cpp +++ b/examples/arkode/CXX_parallel/ark_diffusion_reaction_p.cpp @@ -2600,8 +2600,10 @@ static int OutputStatsIMEX(void* arkode_mem, UserData* udata) if (check_flag(&flag, "ARKodeGetNumStepAttempts", 1)) { return -1; } flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); if (check_flag(&flag, "ARKodeGetNumErrTestFails", 1)) { return -1; } - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - if (check_flag(&flag, "ARKStepGetNumRhsEvals", 1)) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return -1; } if (udata->diffusion) { @@ -2675,11 +2677,11 @@ static int OutputStatsMRI(void* arkode_mem, MRIStepInnerStepper stepper, int flag; // Get slow integrator and solver stats - long int nsts, nfse, nfsi, nni, ncfn, nli, nlcf, nsetups, nfi_ls, nJv; + long int nsts, nfsi, nni, ncfn, nli, nlcf, nsetups, nfi_ls, nJv; flag = ARKodeGetNumSteps(arkode_mem, &nsts); if (check_flag(&flag, "ARKodeGetNumSteps", 1)) { return -1; } - flag = MRIStepGetNumRhsEvals(arkode_mem, &nfse, &nfsi); - if (check_flag(&flag, "MRIStepGetNumRhsEvals", 1)) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfsi); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvIters(arkode_mem, &nni); if (check_flag(&flag, "ARKodeGetNumNonlinSolvIters", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvConvFails(arkode_mem, &ncfn); @@ -2736,7 +2738,7 @@ static int OutputStatsMRI(void* arkode_mem, MRIStepInnerStepper stepper, void* inner_arkode_mem; MRIStepInnerStepper_GetContent(stepper, &inner_arkode_mem); - long int nstf, nstf_a, netff, nffe, nffi; + long int nstf, nstf_a, netff, nffe; flag = ARKodeGetNumSteps(inner_arkode_mem, &nstf); if (check_flag(&flag, "ARKodeGetNumSteps", 1)) { return -1; } @@ -2744,8 +2746,8 @@ static int OutputStatsMRI(void* arkode_mem, MRIStepInnerStepper stepper, if (check_flag(&flag, "ARKodeGetNumStepAttempts", 1)) { return -1; } flag = ARKodeGetNumErrTestFails(inner_arkode_mem, &netff); if (check_flag(&flag, "ARKodeGetNumErrTestFails", 1)) { return -1; } - flag = ARKStepGetNumRhsEvals(inner_arkode_mem, &nffe, &nffi); - if (check_flag(&flag, "ARKStepGetNumRhsEvals", 1)) { return -1; } + flag = ARKodeGetNumRhsEvals(inner_arkode_mem, 0, &nffe); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return -1; } cout << "Fast Integrator:" << endl; cout << " Steps = " << nstf << endl; @@ -2763,11 +2765,11 @@ static int OutputStatsMRICVODE(void* arkode_mem, MRIStepInnerStepper stepper, int flag; // Get slow integrator and solver stats - long int nsts, nfse, nfsi, nni, ncfn, nli, nlcf, nsetups, nfi_ls, nJv; + long int nsts, nfsi, nni, ncfn, nli, nlcf, nsetups, nfi_ls, nJv; flag = ARKodeGetNumSteps(arkode_mem, &nsts); if (check_flag(&flag, "ARKodeGetNumSteps", 1)) { return -1; } - flag = MRIStepGetNumRhsEvals(arkode_mem, &nfse, &nfsi); - if (check_flag(&flag, "MRIStepGetNumRhsEvals", 1)) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfsi); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvIters(arkode_mem, &nni); if (check_flag(&flag, "ARKodeGetNumNonlinSolvIters", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvConvFails(arkode_mem, &ncfn); diff --git a/examples/arkode/CXX_parallel/ark_heat2D_p.cpp b/examples/arkode/CXX_parallel/ark_heat2D_p.cpp index 0bf8d97ba7..ed59996da6 100644 --- a/examples/arkode/CXX_parallel/ark_heat2D_p.cpp +++ b/examples/arkode/CXX_parallel/ark_heat2D_p.cpp @@ -1819,15 +1819,15 @@ static int OutputStats(void* arkode_mem, UserData* udata) int flag; // Get integrator and solver stats - long int nst, nst_a, netf, nfe, nfi, nni, ncfn, nli, nlcf, nsetups, nfi_ls, nJv; + long int nst, nst_a, netf, nfi, nni, ncfn, nli, nlcf, nsetups, nfi_ls, nJv; flag = ARKodeGetNumSteps(arkode_mem, &nst); if (check_flag(&flag, "ARKodeGetNumSteps", 1)) { return -1; } flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); if (check_flag(&flag, "ARKodeGetNumStepAttempts", 1)) { return -1; } flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); if (check_flag(&flag, "ARKodeGetNumErrTestFails", 1)) { return -1; } - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - if (check_flag(&flag, "ARKStepGetNumRhsEvals", 1)) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvIters(arkode_mem, &nni); if (check_flag(&flag, "ARKodeGetNumNonlinSolvIters", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvConvFails(arkode_mem, &ncfn); diff --git a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_ls.cpp b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_ls.cpp index 14786d9c98..997bd4d787 100644 --- a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_ls.cpp +++ b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_ls.cpp @@ -2111,15 +2111,15 @@ static int OutputStats(void* arkode_mem, UserData* udata) int flag; // Get integrator and solver stats - long int nst, nst_a, netf, nfe, nfi, nni, ncfn, nli, nlcf, nsetups, nJeval; + long int nst, nst_a, netf, nfi, nni, ncfn, nli, nlcf, nsetups, nJeval; flag = ARKodeGetNumSteps(arkode_mem, &nst); if (check_flag(&flag, "ARKodeGetNumSteps", 1)) { return -1; } flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); if (check_flag(&flag, "ARKodeGetNumStepAttempts", 1)) { return -1; } flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); if (check_flag(&flag, "ARKodeGetNumErrTestFails", 1)) { return -1; } - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - if (check_flag(&flag, "ARKStepGetNumRhsEvals", 1)) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvIters(arkode_mem, &nni); if (check_flag(&flag, "ARKodeGetNumNonlinSolvIters", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvConvFails(arkode_mem, &ncfn); diff --git a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg.cpp b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg.cpp index d408bcdf78..69aa444334 100644 --- a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg.cpp +++ b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg.cpp @@ -2647,15 +2647,15 @@ static int OutputStats(void* arkode_mem, UserData* udata) int flag; // Get integrator and solver stats - long int nst, nst_a, netf, nfe, nfi, nni, ncfn, nli, nlcf, nsetups, nfi_ls, nJv; + long int nst, nst_a, netf, nfi, nni, ncfn, nli, nlcf, nsetups, nfi_ls, nJv; flag = ARKodeGetNumSteps(arkode_mem, &nst); if (check_flag(&flag, "ARKodeGetNumSteps", 1)) { return -1; } flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); if (check_flag(&flag, "ARKodeGetNumStepAttempts", 1)) { return -1; } flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); if (check_flag(&flag, "ARKodeGetNumErrTestFails", 1)) { return -1; } - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - if (check_flag(&flag, "ARKStepGetNumRhsEvals", 1)) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvIters(arkode_mem, &nni); if (check_flag(&flag, "ARKodeGetNumNonlinSolvIters", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvConvFails(arkode_mem, &ncfn); diff --git a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_imex.cpp b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_imex.cpp index ddf689ac47..9ca07cbfe1 100644 --- a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_imex.cpp +++ b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_imex.cpp @@ -2740,8 +2740,10 @@ static int OutputStats(void* arkode_mem, UserData* udata) if (check_flag(&flag, "ARKodeGetNumStepAttempts", 1)) { return -1; } flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); if (check_flag(&flag, "ARKodeGetNumErrTestFails", 1)) { return -1; } - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - if (check_flag(&flag, "ARKStepGetNumRhsEvals", 1)) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvIters(arkode_mem, &nni); if (check_flag(&flag, "ARKodeGetNumNonlinSolvIters", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvConvFails(arkode_mem, &ncfn); @@ -2761,7 +2763,8 @@ static int OutputStats(void* arkode_mem, UserData* udata) cout << " Steps = " << nst << endl; cout << " Step attempts = " << nst_a << endl; cout << " Error test fails = " << netf << endl; - cout << " RHS evals = " << nfi << endl; + cout << " Fe RHS evals = " << nfe << endl; + cout << " Fi RHS evals = " << nfi << endl; cout << " NLS iters = " << nni << endl; cout << " NLS fails = " << ncfn << endl; cout << " LS iters = " << nli << endl; diff --git a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_imex_--np_2_2.out b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_imex_--np_2_2.out index 66fc95aae1..429b9634d9 100644 --- a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_imex_--np_2_2.out +++ b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_imex_--np_2_2.out @@ -56,7 +56,8 @@ Final fast integrator statistics: Steps = 722 Step attempts = 722 Error test fails = 0 - RHS evals = 5444 + Fe RHS evals = 2890 + Fi RHS evals = 5444 NLS iters = 2554 NLS fails = 0 LS iters = 8545 diff --git a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_mri.cpp b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_mri.cpp index aa75c8b61c..ab2789c7ef 100644 --- a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_mri.cpp +++ b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_mri.cpp @@ -2707,15 +2707,15 @@ static int OutputFastStats(void* arkode_mem, UserData* udata) int flag; // Get integrator and solver stats - long int nst, nst_a, netf, nfe, nfi, nni, ncfn, nli, nlcf, nsetups, nJv; + long int nst, nst_a, netf, nfi, nni, ncfn, nli, nlcf, nsetups, nJv; flag = ARKodeGetNumSteps(arkode_mem, &nst); if (check_flag(&flag, "ARKodeGetNumSteps", 1)) { return -1; } flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); if (check_flag(&flag, "ARKodeGetNumStepAttempts", 1)) { return -1; } flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); if (check_flag(&flag, "ARKodeGetNumErrTestFails", 1)) { return -1; } - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - if (check_flag(&flag, "ARKStepGetNumRhsEvals", 1)) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvIters(arkode_mem, &nni); if (check_flag(&flag, "ARKodeGetNumNonlinSolvIters", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvConvFails(arkode_mem, &ncfn); @@ -2778,8 +2778,10 @@ static int OutputSlowStats(void* arkode_mem, UserData* udata) long int nst, nfe, nfi, nni, ncfn, nli, nlcf, nsetups, nJv; flag = ARKodeGetNumSteps(arkode_mem, &nst); if (check_flag(&flag, "ARKodeGetNumSteps", 1)) { return -1; } - flag = MRIStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - if (check_flag(&flag, "MRIStepGetNumRhsEvals", 1)) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvIters(arkode_mem, &nni); if (check_flag(&flag, "ARKodeGetNumNonlinSolvIters", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvConvFails(arkode_mem, &ncfn); @@ -2797,7 +2799,8 @@ static int OutputSlowStats(void* arkode_mem, UserData* udata) cout << setprecision(6); cout << " Steps = " << nst << endl; - cout << " RHS evals = " << nfi << endl; + cout << " Fe RHS evals = " << nfe << endl; + cout << " Fi RHS evals = " << nfi << endl; cout << " NLS iters = " << nni << endl; cout << " NLS fails = " << ncfn << endl; cout << " LS iters = " << nli << endl; diff --git a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_mri_--np_2_2.out b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_mri_--np_2_2.out index 5c1a518ea8..2a91f4f2ba 100644 --- a/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_mri_--np_2_2.out +++ b/examples/arkode/CXX_parhyp/ark_heat2D_hypre_pfmg_mri_--np_2_2.out @@ -56,7 +56,8 @@ Final slow integrator statistics: Steps = 1000 - RHS evals = 7355 + Fe RHS evals = 4000 + Fi RHS evals = 7355 NLS iters = 3355 NLS fails = 0 LS iters = 10603 diff --git a/examples/arkode/CXX_serial/ark_advection_diffusion_reaction.hpp b/examples/arkode/CXX_serial/ark_advection_diffusion_reaction.hpp index 9b50109742..59a429f09b 100644 --- a/examples/arkode/CXX_serial/ark_advection_diffusion_reaction.hpp +++ b/examples/arkode/CXX_serial/ark_advection_diffusion_reaction.hpp @@ -297,8 +297,8 @@ static int OutputStatsERK(void* arkode_mem, UserData& udata) if (check_flag(flag, "ARKodeGetNumStepAttempts")) { return -1; } flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); if (check_flag(flag, "ARKodeGetNumErrTestFails")) { return -1; } - flag = ERKStepGetNumRhsEvals(arkode_mem, &nfe); - if (check_flag(flag, "ERKStepGetNumRhsEvals")) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + if (check_flag(flag, "ARKodeGetNumRhsEvals")) { return -1; } cout << " Steps = " << nst << endl; cout << " Step attempts = " << nst_a << endl; @@ -321,8 +321,10 @@ static int OutputStatsARK(void* arkode_mem, UserData& udata) if (check_flag(flag, "ARKodeGetNumStepAttempts")) { return -1; } flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); if (check_flag(flag, "ARKodeGetNumErrTestFails")) { return -1; } - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - if (check_flag(flag, "ARKStepGetNumRhsEvals")) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + if (check_flag(flag, "ARKodeGetNumRhsEvals")) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + if (check_flag(flag, "ARKodeGetNumRhsEvals")) { return -1; } cout << fixed << setprecision(6); cout << " Steps = " << nst << endl; @@ -371,8 +373,10 @@ static int OutputStatsMRIARK(void* arkode_mem, MRIStepInnerStepper fast_mem, long int nst, nst_a, netf, nfe, nfi; flag = ARKodeGetNumSteps(arkode_mem, &nst); if (check_flag(flag, "ARKodeGetNumSteps")) { return -1; } - flag = MRIStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - if (check_flag(flag, "MRIStepGetNumRhsEvals")) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + if (check_flag(flag, "ARKodeGetNumRhsEvals")) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + if (check_flag(flag, "ARKodeGetNumRhsEvals")) { return -1; } cout << fixed << setprecision(6); cout << endl << "Slow Integrator:" << endl; @@ -419,8 +423,10 @@ static int OutputStatsMRIARK(void* arkode_mem, MRIStepInnerStepper fast_mem, if (check_flag(flag, "ARKodeGetNumStepAttempts")) { return -1; } flag = ARKodeGetNumErrTestFails(fast_arkode_mem, &netf); if (check_flag(flag, "ARKodeGetNumErrTestFails")) { return -1; } - flag = ARKStepGetNumRhsEvals(fast_arkode_mem, &nfe, &nfi); - if (check_flag(flag, "ARKStepGetNumRhsEvals")) { return -1; } + flag = ARKodeGetNumRhsEvals(fast_arkode_mem, 0, &nfe); + if (check_flag(flag, "ARKodeGetNumRhsEvals")) { return -1; } + flag = ARKodeGetNumRhsEvals(fast_arkode_mem, 1, &nfi); + if (check_flag(flag, "ARKodeGetNumRhsEvals")) { return -1; } cout << fixed << setprecision(6); cout << endl << "Fast Integrator:" << endl; @@ -507,8 +513,10 @@ static int OutputStatsMRICVODE(void* arkode_mem, MRIStepInnerStepper fast_mem, long int nsts, nfse, nfsi; flag = ARKodeGetNumSteps(arkode_mem, &nsts); if (check_flag(flag, "ARKodeGetNumSteps")) { return -1; } - flag = MRIStepGetNumRhsEvals(arkode_mem, &nfse, &nfsi); - if (check_flag(flag, "MRIStepGetNumRhsEvals")) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfse); + if (check_flag(flag, "ARKodeGetNumRhsEvals")) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfsi); + if (check_flag(flag, "ARKodeGetNumRhsEvals")) { return -1; } long int nni, ncfn; flag = ARKodeGetNumNonlinSolvIters(arkode_mem, &nni); diff --git a/examples/arkode/CXX_serial/ark_analytic_sys.cpp b/examples/arkode/CXX_serial/ark_analytic_sys.cpp index 944c40be1a..d48ce0abb9 100644 --- a/examples/arkode/CXX_serial/ark_analytic_sys.cpp +++ b/examples/arkode/CXX_serial/ark_analytic_sys.cpp @@ -239,8 +239,10 @@ int main() check_flag(&flag, "ARKodeGetNumSteps", 1); flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_flag(&flag, "ARKodeGetNumStepAttempts", 1); - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_flag(&flag, "ARKStepGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); flag = ARKodeGetNumLinSolvSetups(arkode_mem, &nsetups); check_flag(&flag, "ARKodeGetNumLinSolvSetups", 1); flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); diff --git a/examples/arkode/CXX_serial/ark_heat2D.cpp b/examples/arkode/CXX_serial/ark_heat2D.cpp index 3298eac1f9..4b75d703bb 100644 --- a/examples/arkode/CXX_serial/ark_heat2D.cpp +++ b/examples/arkode/CXX_serial/ark_heat2D.cpp @@ -1086,15 +1086,15 @@ static int OutputStats(void* arkode_mem, UserData* udata) int flag; // Get integrator and solver stats - long int nst, nst_a, netf, nfe, nfi, nni, ncfn, nli, nlcf, nsetups, nfi_ls, nJv; + long int nst, nst_a, netf, nfi, nni, ncfn, nli, nlcf, nsetups, nfi_ls, nJv; flag = ARKodeGetNumSteps(arkode_mem, &nst); if (check_flag(&flag, "ARKodeGetNumSteps", 1)) { return -1; } flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); if (check_flag(&flag, "ARKodeGetNumStepAttempts", 1)) { return -1; } flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); if (check_flag(&flag, "ARKodeGetNumErrTestFails", 1)) { return -1; } - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - if (check_flag(&flag, "ARKStepGetNumRhsEvals", 1)) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvIters(arkode_mem, &nni); if (check_flag(&flag, "ARKodeGetNumNonlinSolvIters", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvConvFails(arkode_mem, &ncfn); diff --git a/examples/arkode/CXX_serial/ark_kpr_Mt.cpp b/examples/arkode/CXX_serial/ark_kpr_Mt.cpp index bd945fa00b..f48f81bc84 100644 --- a/examples/arkode/CXX_serial/ark_kpr_Mt.cpp +++ b/examples/arkode/CXX_serial/ark_kpr_Mt.cpp @@ -575,8 +575,10 @@ static int adaptive_run(void* arkode_mem, N_Vector y, sunrealtype T0, if (check_retval(&retval, "ARKodeGetNumSteps", 1)) { return 1; } retval = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); if (check_retval(&retval, "ARKodeGetNumStepAttempts", 1)) { return 1; } - retval = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - if (check_retval(&retval, "ARKStepGetNumRhsEvals", 1)) { return 1; } + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + if (check_retval(&retval, "ARKodeGetNumRhsEvals", 1)) { return 1; } + retval = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + if (check_retval(&retval, "ARKodeGetNumRhsEvals", 1)) { return 1; } retval = ARKodeGetNumErrTestFails(arkode_mem, &netf); if (check_retval(&retval, "ARKodeGetNumErrTestFails", 1)) { return 1; } retval = ARKodeGetNumMassSetups(arkode_mem, &nmset); diff --git a/examples/arkode/CXX_serial/ark_pendulum.cpp b/examples/arkode/CXX_serial/ark_pendulum.cpp index 57c23ccc99..3cee00125b 100644 --- a/examples/arkode/CXX_serial/ark_pendulum.cpp +++ b/examples/arkode/CXX_serial/ark_pendulum.cpp @@ -300,8 +300,11 @@ int main(int argc, char* argv[]) flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); check_flag(flag, "ARKodeGetNumErrTestFails"); - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_flag(flag, "ARKStepGetNumRhsEvals"); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(flag, "ARKodeGetNumRhsEvals"); + + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_flag(flag, "ARKodeGetNumRhsEvals"); std::cout << std::endl; std::cout << "Final Solver Statistics:\n"; diff --git a/examples/arkode/CXX_superludist/ark_brusselator1D_FEM_sludist.cpp b/examples/arkode/CXX_superludist/ark_brusselator1D_FEM_sludist.cpp index 15f50ea46e..64ffd741a9 100644 --- a/examples/arkode/CXX_superludist/ark_brusselator1D_FEM_sludist.cpp +++ b/examples/arkode/CXX_superludist/ark_brusselator1D_FEM_sludist.cpp @@ -575,8 +575,10 @@ int main(int argc, char* argv[]) check_retval(&retval, "ARKodeGetNumSteps", 1); retval = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_retval(&retval, "ARKodeGetNumStepAttempts", 1); - retval = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_retval(&retval, "ARKStepGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); retval = ARKodeGetNumLinSolvSetups(arkode_mem, &nsetups); check_retval(&retval, "ARKodeGetNumLinSolvSetups", 1); retval = ARKodeGetNumErrTestFails(arkode_mem, &netf); diff --git a/examples/arkode/CXX_xbraid/ark_heat2D_hypre_pfmg_xbraid.cpp b/examples/arkode/CXX_xbraid/ark_heat2D_hypre_pfmg_xbraid.cpp index 987ba94a5d..0c4da9c70e 100644 --- a/examples/arkode/CXX_xbraid/ark_heat2D_hypre_pfmg_xbraid.cpp +++ b/examples/arkode/CXX_xbraid/ark_heat2D_hypre_pfmg_xbraid.cpp @@ -2902,15 +2902,15 @@ static int OutputStats(void* arkode_mem, UserData* udata) bool outproc = (udata->myid_w == 0); // Get integrator and solver stats - long int nst, nst_a, netf, nfe, nfi, nni, ncfn, nli, nlcf, nsetups, nfi_ls, nJv; + long int nst, nst_a, netf, nfi, nni, ncfn, nli, nlcf, nsetups, nfi_ls, nJv; flag = ARKodeGetNumSteps(arkode_mem, &nst); if (check_flag(&flag, "ARKodeGetNumSteps", 1)) { return -1; } flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); if (check_flag(&flag, "ARKodeGetNumStepAttempts", 1)) { return -1; } flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); if (check_flag(&flag, "ARKodeGetNumErrTestFails", 1)) { return -1; } - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - if (check_flag(&flag, "ARKStepGetNumRhsEvals", 1)) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvIters(arkode_mem, &nni); if (check_flag(&flag, "ARKodeGetNumNonlinSolvIters", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvConvFails(arkode_mem, &ncfn); diff --git a/examples/arkode/CXX_xbraid/ark_heat2D_p_xbraid.cpp b/examples/arkode/CXX_xbraid/ark_heat2D_p_xbraid.cpp index d6cc3b7319..466b1f7f9c 100644 --- a/examples/arkode/CXX_xbraid/ark_heat2D_p_xbraid.cpp +++ b/examples/arkode/CXX_xbraid/ark_heat2D_p_xbraid.cpp @@ -2052,15 +2052,15 @@ static int OutputStats(void* arkode_mem, UserData* udata) bool outproc = (udata->myid_w == 0); // Get integrator and solver stats - long int nst, nst_a, netf, nfe, nfi, nni, ncfn, nli, nlcf, nsetups, nfi_ls, nJv; + long int nst, nst_a, netf, nfi, nni, ncfn, nli, nlcf, nsetups, nfi_ls, nJv; flag = ARKodeGetNumSteps(arkode_mem, &nst); if (check_flag(&flag, "ARKodeGetNumSteps", 1)) { return -1; } flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); if (check_flag(&flag, "ARKodeGetNumStepAttempts", 1)) { return -1; } flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); if (check_flag(&flag, "ARKodeGetNumErrTestFails", 1)) { return -1; } - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - if (check_flag(&flag, "ARKStepGetNumRhsEvals", 1)) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvIters(arkode_mem, &nni); if (check_flag(&flag, "ARKodeGetNumNonlinSolvIters", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvConvFails(arkode_mem, &ncfn); diff --git a/examples/arkode/CXX_xbraid/ark_heat2D_xbraid.cpp b/examples/arkode/CXX_xbraid/ark_heat2D_xbraid.cpp index 3e6cd8b1d5..c330571584 100644 --- a/examples/arkode/CXX_xbraid/ark_heat2D_xbraid.cpp +++ b/examples/arkode/CXX_xbraid/ark_heat2D_xbraid.cpp @@ -1351,15 +1351,15 @@ static int OutputStats(void* arkode_mem, UserData* udata) bool outproc = (udata->myid_w == 0); // Get integrator and solver stats - long int nst, nst_a, netf, nfe, nfi, nni, ncfn, nli, nlcf, nsetups, nfi_ls, nJv; + long int nst, nst_a, netf, nfi, nni, ncfn, nli, nlcf, nsetups, nfi_ls, nJv; flag = ARKodeGetNumSteps(arkode_mem, &nst); if (check_flag(&flag, "ARKodeGetNumSteps", 1)) { return -1; } flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); if (check_flag(&flag, "ARKodeGetNumStepAttempts", 1)) { return -1; } flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); if (check_flag(&flag, "ARKodeGetNumErrTestFails", 1)) { return -1; } - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - if (check_flag(&flag, "ARKStepGetNumRhsEvals", 1)) { return -1; } + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvIters(arkode_mem, &nni); if (check_flag(&flag, "ARKodeGetNumNonlinSolvIters", 1)) { return -1; } flag = ARKodeGetNumNonlinSolvConvFails(arkode_mem, &ncfn); diff --git a/examples/arkode/C_manyvector/ark_brusselator1D_manyvec.c b/examples/arkode/C_manyvector/ark_brusselator1D_manyvec.c index 45ab77e455..fe21069373 100644 --- a/examples/arkode/C_manyvector/ark_brusselator1D_manyvec.c +++ b/examples/arkode/C_manyvector/ark_brusselator1D_manyvec.c @@ -292,8 +292,10 @@ int main(void) check_flag(&flag, "ARKodeGetNumSteps", 1); flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_flag(&flag, "ARKodeGetNumStepAttempts", 1); - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_flag(&flag, "ARKStepGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); flag = ARKodeGetNumLinSolvSetups(arkode_mem, &nsetups); check_flag(&flag, "ARKodeGetNumLinSolvSetups", 1); flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); diff --git a/examples/arkode/C_openmp/ark_brusselator1D_omp.c b/examples/arkode/C_openmp/ark_brusselator1D_omp.c index 1fc53f29d2..81cc915abc 100644 --- a/examples/arkode/C_openmp/ark_brusselator1D_omp.c +++ b/examples/arkode/C_openmp/ark_brusselator1D_omp.c @@ -323,8 +323,10 @@ int main(int argc, char* argv[]) check_flag(&flag, "ARKodeGetNumSteps", 1); flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_flag(&flag, "ARKodeGetNumStepAttempts", 1); - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_flag(&flag, "ARKStepGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); flag = ARKodeGetNumLinSolvSetups(arkode_mem, &nsetups); check_flag(&flag, "ARKodeGetNumLinSolvSetups", 1); flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); diff --git a/examples/arkode/C_openmp/ark_heat1D_omp.c b/examples/arkode/C_openmp/ark_heat1D_omp.c index 4fc8eb998b..2bdaa71ea4 100644 --- a/examples/arkode/C_openmp/ark_heat1D_omp.c +++ b/examples/arkode/C_openmp/ark_heat1D_omp.c @@ -215,8 +215,10 @@ int main(int argc, char* argv[]) check_flag(&flag, "ARKodeGetNumSteps", 1); flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_flag(&flag, "ARKodeGetNumStepAttempts", 1); - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_flag(&flag, "ARKStepGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); flag = ARKodeGetNumLinSolvSetups(arkode_mem, &nsetups); check_flag(&flag, "ARKodeGetNumLinSolvSetups", 1); flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); diff --git a/examples/arkode/C_openmpdev/ark_analytic_nonlin_ompdev.c b/examples/arkode/C_openmpdev/ark_analytic_nonlin_ompdev.c index 1f847e9dfe..15c909a73f 100644 --- a/examples/arkode/C_openmpdev/ark_analytic_nonlin_ompdev.c +++ b/examples/arkode/C_openmpdev/ark_analytic_nonlin_ompdev.c @@ -140,8 +140,8 @@ int main(void) check_flag(&flag, "ARKodeGetNumSteps", 1); flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_flag(&flag, "ARKodeGetNumStepAttempts", 1); - flag = ERKStepGetNumRhsEvals(arkode_mem, &nfe); - check_flag(&flag, "ERKStepGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); check_flag(&flag, "ARKodeGetNumErrTestFails", 1); diff --git a/examples/arkode/C_openmpdev/ark_heat1D_ompdev.c b/examples/arkode/C_openmpdev/ark_heat1D_ompdev.c index c6307e226f..56bad92e9b 100644 --- a/examples/arkode/C_openmpdev/ark_heat1D_ompdev.c +++ b/examples/arkode/C_openmpdev/ark_heat1D_ompdev.c @@ -211,8 +211,10 @@ int main(void) check_flag(&flag, "ARKodeGetNumSteps", 1); flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_flag(&flag, "ARKodeGetNumStepAttempts", 1); - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_flag(&flag, "ARKStepGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); flag = ARKodeGetNumLinSolvSetups(arkode_mem, &nsetups); check_flag(&flag, "ARKodeGetNumLinSolvSetups", 1); flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); diff --git a/examples/arkode/C_parallel/ark_brusselator1D_task_local_nls.c b/examples/arkode/C_parallel/ark_brusselator1D_task_local_nls.c index a35437e611..d3a71248c6 100644 --- a/examples/arkode/C_parallel/ark_brusselator1D_task_local_nls.c +++ b/examples/arkode/C_parallel/ark_brusselator1D_task_local_nls.c @@ -458,8 +458,10 @@ static int EvolveProblemIMEX(N_Vector y, UserData udata, UserOptions uopt, check_retval(&retval, "ARKodeGetNumSteps", 1); retval = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_retval(&retval, "ARKodeGetNumStepAttempts", 1); - retval = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_retval(&retval, "ARKStepGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); retval = ARKodeGetNumErrTestFails(arkode_mem, &netf); check_retval(&retval, "ARKodeGetNumErrTestFails", 1); retval = ARKodeGetNumNonlinSolvIters(arkode_mem, &nni); @@ -570,8 +572,8 @@ static int EvolveProblemExplicit(N_Vector y, UserData udata, UserOptions uopt, check_retval(&retval, "ARKodeGetNumSteps", 1); retval = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_retval(&retval, "ARKodeGetNumStepAttempts", 1); - retval = ERKStepGetNumRhsEvals(arkode_mem, &nfe); - check_retval(&retval, "ERKStepGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); retval = ARKodeGetNumErrTestFails(arkode_mem, &netf); check_retval(&retval, "ARKodeGetNumErrTestFails", 1); diff --git a/examples/arkode/C_parallel/ark_diurnal_kry_bbd_p.c b/examples/arkode/C_parallel/ark_diurnal_kry_bbd_p.c index 190b7c40ce..ced0c56894 100644 --- a/examples/arkode/C_parallel/ark_diurnal_kry_bbd_p.c +++ b/examples/arkode/C_parallel/ark_diurnal_kry_bbd_p.c @@ -481,8 +481,10 @@ static void PrintFinalStats(void* arkode_mem) check_flag(&flag, "ARKodeGetWorkSpace", 1, 0); flag = ARKodeGetNumSteps(arkode_mem, &nst); check_flag(&flag, "ARKodeGetNumSteps", 1, 0); - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_flag(&flag, "ARKStepGetNumRhsEvals", 1, 0); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1, 0); + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1, 0); flag = ARKodeGetNumLinSolvSetups(arkode_mem, &nsetups); check_flag(&flag, "ARKodeGetNumLinSolvSetups", 1, 0); flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); diff --git a/examples/arkode/C_parallel/ark_diurnal_kry_p.c b/examples/arkode/C_parallel/ark_diurnal_kry_p.c index b5d9941480..4f8f39634a 100644 --- a/examples/arkode/C_parallel/ark_diurnal_kry_p.c +++ b/examples/arkode/C_parallel/ark_diurnal_kry_p.c @@ -474,8 +474,10 @@ static void PrintFinalStats(void* arkode_mem) check_flag(&flag, "ARKodeGetWorkSpace", 1, 0); flag = ARKodeGetNumSteps(arkode_mem, &nst); check_flag(&flag, "ARKodeGetNumSteps", 1, 0); - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_flag(&flag, "ARKStepGetNumRhsEvals", 1, 0); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1, 0); + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1, 0); flag = ARKodeGetNumLinSolvSetups(arkode_mem, &nsetups); check_flag(&flag, "ARKodeGetNumLinSolvSetups", 1, 0); flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); diff --git a/examples/arkode/C_parhyp/ark_diurnal_kry_ph.c b/examples/arkode/C_parhyp/ark_diurnal_kry_ph.c index 59dfc3d0f4..10f88144aa 100644 --- a/examples/arkode/C_parhyp/ark_diurnal_kry_ph.c +++ b/examples/arkode/C_parhyp/ark_diurnal_kry_ph.c @@ -486,8 +486,10 @@ static void PrintFinalStats(void* arkode_mem) check_flag(&flag, "ARKodeGetWorkSpace", 1, 0); flag = ARKodeGetNumSteps(arkode_mem, &nst); check_flag(&flag, "ARKodeGetNumSteps", 1, 0); - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_flag(&flag, "ARKStepGetNumRhsEvals", 1, 0); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1, 0); + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1, 0); flag = ARKodeGetNumLinSolvSetups(arkode_mem, &nsetups); check_flag(&flag, "ARKodeGetNumLinSolvSetups", 1, 0); flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); diff --git a/examples/arkode/C_serial/ark_KrylovDemo_prec.c b/examples/arkode/C_serial/ark_KrylovDemo_prec.c index 501ff55e80..31ba755240 100644 --- a/examples/arkode/C_serial/ark_KrylovDemo_prec.c +++ b/examples/arkode/C_serial/ark_KrylovDemo_prec.c @@ -643,8 +643,10 @@ static void PrintOutput(void* arkode_mem, sunrealtype t) flag = ARKodeGetNumSteps(arkode_mem, &nst); check_flag(&flag, "ARKodeGetNumSteps", 1); - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_flag(&flag, "ARKStepGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); flag = ARKodeGetNumNonlinSolvIters(arkode_mem, &nni); check_flag(&flag, "ARKodeGetNumNonlinSolvIters", 1); flag = ARKodeGetLastStep(arkode_mem, &hu); @@ -678,8 +680,10 @@ static void PrintFinalStats(void* arkode_mem) check_flag(&flag, "ARKodeGetWorkSpace", 1); flag = ARKodeGetNumSteps(arkode_mem, &nst); check_flag(&flag, "ARKodeGetNumSteps", 1); - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_flag(&flag, "ARKStepGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); flag = ARKodeGetNumLinSolvSetups(arkode_mem, &nsetups); check_flag(&flag, "ARKodeGetNumLinSolvSetups", 1); flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); diff --git a/examples/arkode/C_serial/ark_analytic.c b/examples/arkode/C_serial/ark_analytic.c index 152a95133d..a15bde944d 100644 --- a/examples/arkode/C_serial/ark_analytic.c +++ b/examples/arkode/C_serial/ark_analytic.c @@ -169,8 +169,10 @@ int main(void) check_flag(&flag, "ARKodeGetNumSteps", 1); flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_flag(&flag, "ARKodeGetNumStepAttempts", 1); - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_flag(&flag, "ARKStepGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); flag = ARKodeGetNumLinSolvSetups(arkode_mem, &nsetups); check_flag(&flag, "ARKodeGetNumLinSolvSetups", 1); flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); diff --git a/examples/arkode/C_serial/ark_analytic_mels.c b/examples/arkode/C_serial/ark_analytic_mels.c index 95dca9fbc2..eaa7236d0f 100644 --- a/examples/arkode/C_serial/ark_analytic_mels.c +++ b/examples/arkode/C_serial/ark_analytic_mels.c @@ -153,8 +153,10 @@ int main(void) check_retval(&retval, "ARKodeGetNumSteps", 1); retval = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_retval(&retval, "ARKodeGetNumStepAttempts", 1); - retval = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_retval(&retval, "ARKStepGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); retval = ARKodeGetNumLinSolvSetups(arkode_mem, &nsetups); check_retval(&retval, "ARKodeGetNumLinSolvSetups", 1); retval = ARKodeGetNumErrTestFails(arkode_mem, &netf); diff --git a/examples/arkode/C_serial/ark_brusselator.c b/examples/arkode/C_serial/ark_brusselator.c index a501f997e2..d766a773d6 100644 --- a/examples/arkode/C_serial/ark_brusselator.c +++ b/examples/arkode/C_serial/ark_brusselator.c @@ -250,8 +250,10 @@ int main(void) check_flag(&flag, "ARKodeGetNumSteps", 1); flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_flag(&flag, "ARKodeGetNumStepAttempts", 1); - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_flag(&flag, "ARKStepGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); flag = ARKodeGetNumLinSolvSetups(arkode_mem, &nsetups); check_flag(&flag, "ARKodeGetNumLinSolvSetups", 1); flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); diff --git a/examples/arkode/C_serial/ark_brusselator1D.c b/examples/arkode/C_serial/ark_brusselator1D.c index e0c803561e..28a40201c8 100644 --- a/examples/arkode/C_serial/ark_brusselator1D.c +++ b/examples/arkode/C_serial/ark_brusselator1D.c @@ -299,8 +299,10 @@ int main(void) check_flag(&flag, "ARKodeGetNumSteps", 1); flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_flag(&flag, "ARKodeGetNumStepAttempts", 1); - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_flag(&flag, "ARKStepGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); flag = ARKodeGetNumLinSolvSetups(arkode_mem, &nsetups); check_flag(&flag, "ARKodeGetNumLinSolvSetups", 1); flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); diff --git a/examples/arkode/C_serial/ark_brusselator1D_FEM_slu.c b/examples/arkode/C_serial/ark_brusselator1D_FEM_slu.c index 2978d2f77c..d3dcbc36e6 100644 --- a/examples/arkode/C_serial/ark_brusselator1D_FEM_slu.c +++ b/examples/arkode/C_serial/ark_brusselator1D_FEM_slu.c @@ -404,8 +404,10 @@ int main(int argc, char* argv[]) check_retval(&retval, "ARKodeGetNumSteps", 1); retval = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_retval(&retval, "ARKodeGetNumStepAttempts", 1); - retval = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_retval(&retval, "ARKStepGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); retval = ARKodeGetNumLinSolvSetups(arkode_mem, &nsetups); check_retval(&retval, "ARKodeGetNumLinSolvSetups", 1); retval = ARKodeGetNumErrTestFails(arkode_mem, &netf); diff --git a/examples/arkode/C_serial/ark_brusselator1D_imexmri.c b/examples/arkode/C_serial/ark_brusselator1D_imexmri.c index 1d52164719..a779faeb04 100644 --- a/examples/arkode/C_serial/ark_brusselator1D_imexmri.c +++ b/examples/arkode/C_serial/ark_brusselator1D_imexmri.c @@ -752,14 +752,18 @@ int main(int argc, char* argv[]) /* Get some slow integrator statistics */ retval = ARKodeGetNumSteps(arkode_mem, &nsts); check_retval(&retval, "ARKodeGetNumSteps", 1); - retval = MRIStepGetNumRhsEvals(arkode_mem, &nfse, &nfsi); - check_retval(&retval, "MRIStepGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfse); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfsi); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); /* Get some fast integrator statistics */ retval = ARKodeGetNumSteps(inner_arkode_mem, &nstf); check_retval(&retval, "ARKodeGetNumSteps", 1); - retval = ARKStepGetNumRhsEvals(inner_arkode_mem, &nffe, &nffi); - check_retval(&retval, "ARKStepGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(inner_arkode_mem, 0, &nffe); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(inner_arkode_mem, 1, &nffi); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); /* Print some final statistics */ printf("\nFinal Solver Statistics:\n"); diff --git a/examples/arkode/C_serial/ark_brusselator1D_klu.c b/examples/arkode/C_serial/ark_brusselator1D_klu.c index d9831a948a..19d25fc221 100644 --- a/examples/arkode/C_serial/ark_brusselator1D_klu.c +++ b/examples/arkode/C_serial/ark_brusselator1D_klu.c @@ -314,8 +314,10 @@ int main(void) check_flag(&flag, "ARKodeGetNumSteps", 1); flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_flag(&flag, "ARKodeGetNumStepAttempts", 1); - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_flag(&flag, "ARKStepGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); flag = ARKodeGetNumLinSolvSetups(arkode_mem, &nsetups); check_flag(&flag, "ARKodeGetNumLinSolvSetups", 1); flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); diff --git a/examples/arkode/C_serial/ark_brusselator_1D_mri.c b/examples/arkode/C_serial/ark_brusselator_1D_mri.c index 54398dcf71..0dc4323bc3 100644 --- a/examples/arkode/C_serial/ark_brusselator_1D_mri.c +++ b/examples/arkode/C_serial/ark_brusselator_1D_mri.c @@ -136,7 +136,7 @@ int main(int argc, char* argv[]) FILE *FID, *UFID, *VFID, *WFID; /* output file pointers */ int iout; /* output counter */ long int nsts, nstf, nstf_a, netf; /* step stats */ - long int nfse, nfsi, nffe, nffi; /* RHS stats */ + long int nfse, nffi; /* RHS stats */ long int nsetups, nje, nfeLS; /* linear solver stats */ long int nni, ncfn; /* nonlinear solver stats */ sunindextype NEQ; /* number of equations */ @@ -349,16 +349,16 @@ int main(int argc, char* argv[]) /* Get some slow integrator statistics */ retval = ARKodeGetNumSteps(arkode_mem, &nsts); check_retval(&retval, "ARKodeGetNumSteps", 1); - retval = MRIStepGetNumRhsEvals(arkode_mem, &nfse, &nfsi); - check_retval(&retval, "MRIStepGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfse); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); /* Get some fast integrator statistics */ retval = ARKodeGetNumSteps(inner_arkode_mem, &nstf); check_retval(&retval, "ARKodeGetNumSteps", 1); retval = ARKodeGetNumStepAttempts(inner_arkode_mem, &nstf_a); check_retval(&retval, "ARKodeGetNumStepAttempts", 1); - retval = ARKStepGetNumRhsEvals(inner_arkode_mem, &nffe, &nffi); - check_retval(&retval, "ARKStepGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(inner_arkode_mem, 1, &nffi); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); retval = ARKodeGetNumLinSolvSetups(inner_arkode_mem, &nsetups); check_retval(&retval, "ARKodeGetNumLinSolvSetups", 1); retval = ARKodeGetNumErrTestFails(inner_arkode_mem, &netf); diff --git a/examples/arkode/C_serial/ark_brusselator_fp.c b/examples/arkode/C_serial/ark_brusselator_fp.c index 518eeccdb8..56f93c1423 100644 --- a/examples/arkode/C_serial/ark_brusselator_fp.c +++ b/examples/arkode/C_serial/ark_brusselator_fp.c @@ -249,8 +249,10 @@ int main(int argc, char* argv[]) check_flag(&flag, "ARKodeGetNumSteps", 1); flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_flag(&flag, "ARKodeGetNumStepAttempts", 1); - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_flag(&flag, "ARKStepGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); check_flag(&flag, "ARKodeGetNumErrTestFails", 1); flag = ARKodeGetNumNonlinSolvIters(arkode_mem, &nni); diff --git a/examples/arkode/C_serial/ark_brusselator_mri.c b/examples/arkode/C_serial/ark_brusselator_mri.c index 1ea84c3ee5..67d2c57b80 100644 --- a/examples/arkode/C_serial/ark_brusselator_mri.c +++ b/examples/arkode/C_serial/ark_brusselator_mri.c @@ -81,7 +81,7 @@ int main(void) FILE* UFID; sunrealtype t, tout; int iout; - long int nsts, nstf, nfse, nfsi, nff, tmp; + long int nsts, nstf, nfse, nff; /* * Initialization @@ -219,14 +219,14 @@ int main(void) /* Get some slow integrator statistics */ retval = ARKodeGetNumSteps(arkode_mem, &nsts); check_retval(&retval, "ARKodeGetNumSteps", 1); - retval = MRIStepGetNumRhsEvals(arkode_mem, &nfse, &nfsi); - check_retval(&retval, "MRIStepGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfse); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); /* Get some fast integrator statistics */ retval = ARKodeGetNumSteps(inner_arkode_mem, &nstf); check_retval(&retval, "ARKodeGetNumSteps", 1); - retval = ARKStepGetNumRhsEvals(inner_arkode_mem, &nff, &tmp); - check_retval(&retval, "ARKStepGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(inner_arkode_mem, 0, &nff); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); /* Print some final statistics */ printf("\nFinal Solver Statistics:\n"); diff --git a/examples/arkode/C_serial/ark_conserved_exp_entropy_ark.c b/examples/arkode/C_serial/ark_conserved_exp_entropy_ark.c index c9570e8bec..e1962d01fe 100644 --- a/examples/arkode/C_serial/ark_conserved_exp_entropy_ark.c +++ b/examples/arkode/C_serial/ark_conserved_exp_entropy_ark.c @@ -340,8 +340,11 @@ int main(int argc, char* argv[]) flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); check_flag(flag, "ARKodeGetNumErrTestFails"); - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_flag(flag, "ARKStepGetNumRhsEvals"); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(flag, "ARKodeGetNumRhsEvals"); + + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_flag(flag, "ARKodeGetNumRhsEvals"); printf("\nFinal Solver Statistics:\n"); printf(" Internal solver steps = %li (attempted = %li)\n", nst, nst_a); diff --git a/examples/arkode/C_serial/ark_conserved_exp_entropy_erk.c b/examples/arkode/C_serial/ark_conserved_exp_entropy_erk.c index 6b73b0d999..47bd3fa6e6 100644 --- a/examples/arkode/C_serial/ark_conserved_exp_entropy_erk.c +++ b/examples/arkode/C_serial/ark_conserved_exp_entropy_erk.c @@ -300,8 +300,8 @@ int main(int argc, char* argv[]) flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); check_flag(flag, "ARKodeGetNumErrTestFails"); - flag = ERKStepGetNumRhsEvals(arkode_mem, &nfe); - check_flag(flag, "ERKStepGetNumRhsEvals"); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(flag, "ARKodeGetNumRhsEvals"); printf("\nFinal Solver Statistics:\n"); printf(" Internal solver steps = %li (attempted = %li)\n", nst, nst_a); diff --git a/examples/arkode/C_serial/ark_dissipated_exp_entropy.c b/examples/arkode/C_serial/ark_dissipated_exp_entropy.c index 5b071b61ae..1b7dc0ad38 100644 --- a/examples/arkode/C_serial/ark_dissipated_exp_entropy.c +++ b/examples/arkode/C_serial/ark_dissipated_exp_entropy.c @@ -318,8 +318,11 @@ int main(int argc, char* argv[]) flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); check_flag(flag, "ARKodeGetNumErrTestFails"); - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_flag(flag, "ARKStepGetNumRhsEvals"); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(flag, "ARKodeGetNumRhsEvals"); + + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_flag(flag, "ARKodeGetNumRhsEvals"); printf("\nFinal Solver Statistics:\n"); printf(" Internal solver steps = %li (attempted = %li)\n", nst, nst_a); diff --git a/examples/arkode/C_serial/ark_heat1D.c b/examples/arkode/C_serial/ark_heat1D.c index 6bed4a20c8..e796d0119f 100644 --- a/examples/arkode/C_serial/ark_heat1D.c +++ b/examples/arkode/C_serial/ark_heat1D.c @@ -200,8 +200,10 @@ int main(void) check_flag(&flag, "ARKodeGetNumSteps", 1); flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_flag(&flag, "ARKodeGetNumStepAttempts", 1); - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_flag(&flag, "ARKStepGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); flag = ARKodeGetNumLinSolvSetups(arkode_mem, &nsetups); check_flag(&flag, "ARKodeGetNumLinSolvSetups", 1); flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); diff --git a/examples/arkode/C_serial/ark_kpr_mri.c b/examples/arkode/C_serial/ark_kpr_mri.c index 2ae783435e..f119998632 100644 --- a/examples/arkode/C_serial/ark_kpr_mri.c +++ b/examples/arkode/C_serial/ark_kpr_mri.c @@ -158,7 +158,7 @@ int main(int argc, char* argv[]) sunrealtype hf, gamma, beta, t, tout, rpar[3]; sunrealtype uerr, verr, uerrtot, verrtot, errtot; int iout; - long int nsts, nstf, nfse, nfsi, nff, nnif, nncf, njef, nnis, nncs, njes, tmp; + long int nsts, nstf, nfse, nfsi, nff, nnif, nncf, njef, nnis, nncs, njes; /* * Initialization @@ -626,14 +626,16 @@ int main(int argc, char* argv[]) /* Get some slow integrator statistics */ retval = ARKodeGetNumSteps(arkode_mem, &nsts); check_retval(&retval, "ARKodeGetNumSteps", 1); - retval = MRIStepGetNumRhsEvals(arkode_mem, &nfse, &nfsi); - check_retval(&retval, "MRIStepGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfse); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfsi); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); /* Get some fast integrator statistics */ retval = ARKodeGetNumSteps(inner_arkode_mem, &nstf); check_retval(&retval, "ARKodeGetNumSteps", 1); - retval = ARKStepGetNumRhsEvals(inner_arkode_mem, &nff, &tmp); - check_retval(&retval, "ARKStepGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(inner_arkode_mem, 0, &nff); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); /* Print some final statistics */ printf("\nFinal Solver Statistics:\n"); diff --git a/examples/arkode/C_serial/ark_onewaycouple_mri.c b/examples/arkode/C_serial/ark_onewaycouple_mri.c index ad6776e7bb..78e1ede79c 100644 --- a/examples/arkode/C_serial/ark_onewaycouple_mri.c +++ b/examples/arkode/C_serial/ark_onewaycouple_mri.c @@ -95,7 +95,7 @@ int main(void) sunrealtype t, tout; sunrealtype error = SUN_RCONST(0.0); int iout; - long int nsts, nstf, nfse, nfsi, nff, tmp; + long int nsts, nstf, nfse, nff; /* * Initialization @@ -228,14 +228,14 @@ int main(void) /* Get some slow integrator statistics */ retval = ARKodeGetNumSteps(arkode_mem, &nsts); check_retval(&retval, "ARKodeGetNumSteps", 1); - retval = MRIStepGetNumRhsEvals(arkode_mem, &nfse, &nfsi); - check_retval(&retval, "MRIStepGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfse); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); /* Get some fast integrator statistics */ retval = ARKodeGetNumSteps(inner_arkode_mem, &nstf); check_retval(&retval, "ARKodeGetNumSteps", 1); - retval = ARKStepGetNumRhsEvals(inner_arkode_mem, &nff, &tmp); - check_retval(&retval, "ARKStepGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(inner_arkode_mem, 0, &nff); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); /* Print some final statistics */ printf("\nFinal Solver Statistics:\n"); diff --git a/examples/arkode/C_serial/ark_robertson_constraints.c b/examples/arkode/C_serial/ark_robertson_constraints.c index 2e5062d0e5..532149b212 100644 --- a/examples/arkode/C_serial/ark_robertson_constraints.c +++ b/examples/arkode/C_serial/ark_robertson_constraints.c @@ -204,8 +204,10 @@ int main(void) check_flag(&flag, "ARKodeGetNumSteps", 1); flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_flag(&flag, "ARKodeGetNumStepAttempts", 1); - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_flag(&flag, "ARKStepGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); flag = ARKodeGetNumLinSolvSetups(arkode_mem, &nsetups); check_flag(&flag, "ARKodeGetNumLinSolvSetups", 1); flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); diff --git a/examples/arkode/C_serial/ark_robertson_root.c b/examples/arkode/C_serial/ark_robertson_root.c index 846a1bdb04..ae8e476394 100644 --- a/examples/arkode/C_serial/ark_robertson_root.c +++ b/examples/arkode/C_serial/ark_robertson_root.c @@ -214,8 +214,10 @@ int main(void) check_flag(&flag, "ARKodeGetNumSteps", 1); flag = ARKodeGetNumStepAttempts(arkode_mem, &nst_a); check_flag(&flag, "ARKodeGetNumStepAttempts", 1); - flag = ARKStepGetNumRhsEvals(arkode_mem, &nfe, &nfi); - check_flag(&flag, "ARKStepGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfe); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); + flag = ARKodeGetNumRhsEvals(arkode_mem, 1, &nfi); + check_flag(&flag, "ARKodeGetNumRhsEvals", 1); flag = ARKodeGetNumLinSolvSetups(arkode_mem, &nsetups); check_flag(&flag, "ARKodeGetNumLinSolvSetups", 1); flag = ARKodeGetNumErrTestFails(arkode_mem, &netf); diff --git a/examples/arkode/C_serial/ark_twowaycouple_mri.c b/examples/arkode/C_serial/ark_twowaycouple_mri.c index 4a099d99a4..67b5415850 100644 --- a/examples/arkode/C_serial/ark_twowaycouple_mri.c +++ b/examples/arkode/C_serial/ark_twowaycouple_mri.c @@ -78,7 +78,7 @@ int main(void) FILE* UFID; sunrealtype t, tout; int iout; - long int nsts, nstf, nfse, nfsi, nff, tmp; + long int nsts, nstf, nfse, nff; /* Create the SUNDIALS context object for this simulation */ SUNContext ctx; @@ -195,14 +195,14 @@ int main(void) /* Get some slow integrator statistics */ retval = ARKodeGetNumSteps(arkode_mem, &nsts); check_retval(&retval, "ARKodeGetNumSteps", 1); - retval = MRIStepGetNumRhsEvals(arkode_mem, &nfse, &nfsi); - check_retval(&retval, "MRIStepGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, &nfse); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); /* Get some fast integrator statistics */ retval = ARKodeGetNumSteps(inner_arkode_mem, &nstf); check_retval(&retval, "ARKodeGetNumSteps", 1); - retval = ARKStepGetNumRhsEvals(inner_arkode_mem, &nff, &tmp); - check_retval(&retval, "ARKStepGetNumRhsEvals", 1); + retval = ARKodeGetNumRhsEvals(inner_arkode_mem, 0, &nff); + check_retval(&retval, "ARKodeGetNumRhsEvals", 1); /* Print some final statistics */ printf("\nFinal Solver Statistics:\n"); diff --git a/examples/arkode/F2003_custom/ark_analytic_complex_f2003.f90 b/examples/arkode/F2003_custom/ark_analytic_complex_f2003.f90 index e371c7af08..23a5919068 100644 --- a/examples/arkode/F2003_custom/ark_analytic_complex_f2003.f90 +++ b/examples/arkode/F2003_custom/ark_analytic_complex_f2003.f90 @@ -235,14 +235,13 @@ subroutine ARKStepStats(arkode_mem) integer(c_long) :: nsteps(1) ! num steps integer(c_long) :: nst_a(1) ! num steps attempted integer(c_long) :: nfe(1) ! num explicit function evals - integer(c_long) :: nfi(1) ! num implicit function evals integer(c_long) :: netfails(1) ! num error test fails !======= Internals ============ ierr = FARKodeGetNumSteps(arkode_mem, nsteps) ierr = FARKodeGetNumStepAttempts(arkode_mem, nst_a) - ierr = FARKStepGetNumRhsEvals(arkode_mem, nfe, nfi) + ierr = FARKodeGetNumRhsEvals(arkode_mem, 0, nfe) ierr = FARKodeGetNumErrTestFails(arkode_mem, netfails) print *, ' ' diff --git a/examples/arkode/F2003_custom/ark_brusselator1D_f2003.f90 b/examples/arkode/F2003_custom/ark_brusselator1D_f2003.f90 index 71e577acd5..e837b4e684 100644 --- a/examples/arkode/F2003_custom/ark_brusselator1D_f2003.f90 +++ b/examples/arkode/F2003_custom/ark_brusselator1D_f2003.f90 @@ -433,7 +433,8 @@ subroutine ARKStepStats(arkode_mem) ierr = FARKodeGetNumSteps(arkode_mem, nsteps) ierr = FARKodeGetNumStepAttempts(arkode_mem, nst_a) - ierr = FARKStepGetNumRhsEvals(arkode_mem, nfe, nfi) + ierr = FARKodeGetNumRhsEvals(arkode_mem, 0, nfe) + ierr = FARKodeGetNumRhsEvals(arkode_mem, 1, nfi) ierr = FARKodeGetNumLinRhsEvals(arkode_mem, nfeLS) ierr = FARKodeGetNumLinSolvSetups(arkode_mem, nlinsetups) ierr = FARKodeGetNumJacEvals(arkode_mem, nje) diff --git a/examples/arkode/F2003_parallel/ark_brusselator1D_task_local_nls_f2003.f90 b/examples/arkode/F2003_parallel/ark_brusselator1D_task_local_nls_f2003.f90 index 7d17efaaf3..9b30cbc70a 100644 --- a/examples/arkode/F2003_parallel/ark_brusselator1D_task_local_nls_f2003.f90 +++ b/examples/arkode/F2003_parallel/ark_brusselator1D_task_local_nls_f2003.f90 @@ -1362,9 +1362,15 @@ subroutine EvolveProblemIMEX(sunvec_y) call MPI_Abort(comm, 1, ierr) end if - retval = FARKStepGetNumRhsEvals(arkode_mem, nfe, nfi) + retval = FARKodeGetNumRhsEvals(arkode_mem, 0, nfe) if (retval /= 0) then - print *, "Error: FARKStepGetNumRhsEvals returned ", retval + print *, 'Error in FARKodeGetNumRhsEvals, retval = ', retval, '; halting' + call MPI_Abort(comm, 1, ierr) + end if + + retval = FARKodeGetNumRhsEvals(arkode_mem, 1, nfi) + if (retval /= 0) then + print *, 'Error in FARKodeGetNumRhsEvals, retval = ', retval, '; halting' call MPI_Abort(comm, 1, ierr) end if @@ -1586,9 +1592,9 @@ subroutine EvolveProblemExplicit(sunvec_y) call MPI_Abort(comm, 1, ierr) end if - retval = FERKStepGetNumRhsEvals(arkode_mem, nfe) + retval = FARKodeGetNumRhsEvals(arkode_mem, 0, nfe) if (retval /= 0) then - print *, "Error: FERKStepGetNumRhsEvals returned ", retval + print *, "Error: FARKodeGetNumRhsEvals returned ", retval call MPI_Abort(comm, 1, ierr) end if diff --git a/examples/arkode/F2003_parallel/ark_diag_kry_bbd_f2003.f90 b/examples/arkode/F2003_parallel/ark_diag_kry_bbd_f2003.f90 index 8c67715974..d963fea725 100644 --- a/examples/arkode/F2003_parallel/ark_diag_kry_bbd_f2003.f90 +++ b/examples/arkode/F2003_parallel/ark_diag_kry_bbd_f2003.f90 @@ -360,9 +360,15 @@ program driver call MPI_Abort(comm, 1, ierr) end if - retval = FARKStepGetNumRhsEvals(arkode_mem, nfe, nfi) + retval = FARKodeGetNumRhsEvals(arkode_mem, 0, nfe) if (retval /= 0) then - print *, "Error: FARKStepGetNumRhsEvals returned ", retval + print *, 'Error in FARKodeGetNumRhsEvals, retval = ', retval, '; halting' + call MPI_Abort(comm, 1, ierr) + end if + + retval = FARKodeGetNumRhsEvals(arkode_mem, 1, nfi) + if (retval /= 0) then + print *, 'Error in FARKodeGetNumRhsEvals, retval = ', retval, '; halting' call MPI_Abort(comm, 1, ierr) end if @@ -406,9 +412,15 @@ program driver call MPI_Abort(comm, 1, ierr) end if - retval = FARKStepGetNumRhsEvals(arkode_mem, nfe, nfi) + retval = FARKodeGetNumRhsEvals(arkode_mem, 0, nfe) + if (retval /= 0) then + print *, 'Error in FARKodeGetNumRhsEvals, retval = ', retval, '; halting' + call MPI_Abort(comm, 1, ierr) + end if + + retval = FARKodeGetNumRhsEvals(arkode_mem, 1, nfi) if (retval /= 0) then - print *, "Error: FARKStepGetNumRhsEvals returned ", retval + print *, 'Error in FARKodeGetNumRhsEvals, retval = ', retval, '; halting' call MPI_Abort(comm, 1, ierr) end if diff --git a/examples/arkode/F2003_parallel/ark_diag_non_f2003.f90 b/examples/arkode/F2003_parallel/ark_diag_non_f2003.f90 index d3bfc3a55f..3282e22832 100644 --- a/examples/arkode/F2003_parallel/ark_diag_non_f2003.f90 +++ b/examples/arkode/F2003_parallel/ark_diag_non_f2003.f90 @@ -235,9 +235,9 @@ program driver call MPI_Abort(comm, 1, ierr) end if - retval = FERKStepGetNumRhsEvals(arkode_mem, nfe) + retval = FARKodeGetNumRhsEvals(arkode_mem, 0, nfe) if (retval /= 0) then - print *, "Error: FERKStepGetNumRhsEvals returned ", retval + print *, "Error: FARKodeGetNumRhsEvals returned ", retval call MPI_Abort(comm, 1, ierr) end if @@ -281,9 +281,9 @@ program driver call MPI_Abort(comm, 1, ierr) end if - retval = FERKStepGetNumRhsEvals(arkode_mem, nfe) + retval = FARKodeGetNumRhsEvals(arkode_mem, 0, nfe) if (retval /= 0) then - print *, "Error: FERKStepGetNumRhsEvals returned ", retval + print *, "Error: FARKodeGetNumRhsEvals returned ", retval call MPI_Abort(comm, 1, ierr) end if diff --git a/examples/arkode/F2003_parallel/ark_heat2D_f2003.f90 b/examples/arkode/F2003_parallel/ark_heat2D_f2003.f90 index e024dc9dff..60fd288894 100644 --- a/examples/arkode/F2003_parallel/ark_heat2D_f2003.f90 +++ b/examples/arkode/F2003_parallel/ark_heat2D_f2003.f90 @@ -884,9 +884,15 @@ program driver call MPI_Abort(comm, 1, ierr) end if - retval = FARKStepGetNumRhsEvals(arkode_mem, nfe, nfi) + retval = FARKodeGetNumRhsEvals(arkode_mem, 0, nfe) if (retval /= 0) then - print *, "Error: FARKStepGetNumRhsEvals returned ", retval + print *, "Error: FARKodeGetNumRhsEvals returned ", retval + call MPI_Abort(comm, 1, ierr) + end if + + retval = FARKodeGetNumRhsEvals(arkode_mem, 1, nfi) + if (retval /= 0) then + print *, "Error: FARKodeGetNumRhsEvals returned ", retval call MPI_Abort(comm, 1, ierr) end if diff --git a/examples/arkode/F2003_serial/ark_analytic_f2003.f90 b/examples/arkode/F2003_serial/ark_analytic_f2003.f90 index 62551f623f..0fa90fe945 100644 --- a/examples/arkode/F2003_serial/ark_analytic_f2003.f90 +++ b/examples/arkode/F2003_serial/ark_analytic_f2003.f90 @@ -267,8 +267,6 @@ subroutine ARKStepStats(arkode_mem) integer(c_long) :: nsteps(1) ! num steps integer(c_long) :: nst_a(1) ! num steps attempted - integer(c_long) :: nfe(1) ! num explicit function evals - integer(c_long) :: nfi(1) ! num implicit function evals integer(c_long) :: nfevals(1) ! num function evals integer(c_long) :: nlinsetups(1) ! num linear solver setups integer(c_long) :: netfails(1) ! num error test fails @@ -296,12 +294,11 @@ subroutine ARKStepStats(arkode_mem) stop 1 end if - ierr = FARKStepGetNumRhsEvals(arkode_mem, nfe, nfi) + ierr = FARKodeGetNumRhsEvals(arkode_mem, -1, nfevals) if (ierr /= 0) then - print *, 'Error in FARKStepGetNumRhsEvals, retval = ', ierr, '; halting' + print *, 'Error in FARKodeGetNumRhsEvals, retval = ', ierr, '; halting' stop 1 end if - nfevals = nfe + nfi ierr = FARKodeGetActualInitStep(arkode_mem, hinused) if (ierr /= 0) then diff --git a/examples/arkode/F2003_serial/ark_bruss1D_FEM_klu_f2003.f90 b/examples/arkode/F2003_serial/ark_bruss1D_FEM_klu_f2003.f90 index 0d63e260cf..4072dc30f8 100644 --- a/examples/arkode/F2003_serial/ark_bruss1D_FEM_klu_f2003.f90 +++ b/examples/arkode/F2003_serial/ark_bruss1D_FEM_klu_f2003.f90 @@ -1342,9 +1342,15 @@ subroutine ARKStepStats(arkode_mem) stop 1 end if - ierr = FARKStepGetNumRhsEvals(arkode_mem, nfe, nfi) + ierr = FARKodeGetNumRhsEvals(arkode_mem, 0, nfe) if (ierr /= 0) then - print *, 'Error in FARKStepGetNumRhsEvals, retval = ', ierr, '; halting' + print *, 'Error in FARKodeGetNumRhsEvals, retval = ', ierr, '; halting' + stop 1 + end if + + ierr = FARKodeGetNumRhsEvals(arkode_mem, 1, nfi) + if (ierr /= 0) then + print *, 'Error in FARKodeGetNumRhsEvals, retval = ', ierr, '; halting' stop 1 end if diff --git a/examples/arkode/F2003_serial/ark_bruss_f2003.f90 b/examples/arkode/F2003_serial/ark_bruss_f2003.f90 index 2b6579cf20..0f9905740e 100644 --- a/examples/arkode/F2003_serial/ark_bruss_f2003.f90 +++ b/examples/arkode/F2003_serial/ark_bruss_f2003.f90 @@ -450,9 +450,15 @@ subroutine ARKStepStats(arkode_mem) stop 1 end if - ierr = FARKStepGetNumRhsEvals(arkode_mem, nfe, nfi) + ierr = FARKodeGetNumRhsEvals(arkode_mem, 0, nfe) if (ierr /= 0) then - print *, 'Error in FARKStepGetNumRhsEvals, retval = ', ierr, '; halting' + print *, 'Error in FARKodeGetNumRhsEvals, retval = ', ierr, '; halting' + stop 1 + end if + + ierr = FARKodeGetNumRhsEvals(arkode_mem, 1, nfi) + if (ierr /= 0) then + print *, 'Error in FARKodeGetNumRhsEvals, retval = ', ierr, '; halting' stop 1 end if diff --git a/examples/arkode/F2003_serial/ark_diurnal_kry_bp_f2003.f90 b/examples/arkode/F2003_serial/ark_diurnal_kry_bp_f2003.f90 index ae64d613b6..8c6b9aa594 100644 --- a/examples/arkode/F2003_serial/ark_diurnal_kry_bp_f2003.f90 +++ b/examples/arkode/F2003_serial/ark_diurnal_kry_bp_f2003.f90 @@ -438,9 +438,15 @@ subroutine ARKStepStats(arkode_mem) stop 1 end if - ierr = FARKStepGetNumRhsEvals(arkode_mem, nfe, nfi) + ierr = FARKodeGetNumRhsEvals(arkode_mem, 0, nfe) if (ierr /= 0) then - print *, 'Error in FARKStepGetNumRhsEvals, ierr = ', ierr, '; halting' + print *, 'Error in FARKodeGetNumRhsEvals, retval = ', ierr, '; halting' + stop 1 + end if + + ierr = FARKodeGetNumRhsEvals(arkode_mem, 1, nfi) + if (ierr /= 0) then + print *, 'Error in FARKodeGetNumRhsEvals, retval = ', ierr, '; halting' stop 1 end if diff --git a/examples/arkode/F2003_serial/ark_kpr_mri_f2003.f90 b/examples/arkode/F2003_serial/ark_kpr_mri_f2003.f90 index 330e54f6b7..7556117b4d 100644 --- a/examples/arkode/F2003_serial/ark_kpr_mri_f2003.f90 +++ b/examples/arkode/F2003_serial/ark_kpr_mri_f2003.f90 @@ -602,7 +602,7 @@ program main real(c_double), allocatable :: As(:, :), bs(:), cs(:), ds(:) ! Arrays for slow Butcher table, NOTE: must be in row-major order integer(c_int) :: iout, argc, argi integer(c_long) :: nsts(1), nstf(1), nfse(1), nfsi(1), nff(1) - integer(c_long) :: nnif(1), nncf(1), njef(1), nnis(1), nncs(1), njes(1), tmp(1) + integer(c_long) :: nnif(1), nncf(1), njef(1), nnis(1), nncs(1), njes(1) character(len=32), dimension(:), allocatable :: argv ! @@ -1057,11 +1057,12 @@ program main ! Get some slow integrator statistics retval = FARKodeGetNumSteps(arkode_mem, nsts) - retval = FMRIStepGetNumRhsEvals(arkode_mem, nfse, nfsi) + retval = FARKodeGetNumRhsEvals(arkode_mem, 0, nfse) + retval = FARKodeGetNumRhsEvals(arkode_mem, 1, nfsi) ! Get some fast integrator statistics retval = FARKodeGetNumSteps(inner_arkode_mem, nstf) - retval = FARKStepGetNumRhsEvals(inner_arkode_mem, nff, tmp) + retval = FARKodeGetNumRhsEvals(inner_arkode_mem, 0, nff) ! Print some final statistics print *, "Final Solver Statistics:" diff --git a/examples/arkode/F2003_serial/ark_roberts_dnsL_f2003.f90 b/examples/arkode/F2003_serial/ark_roberts_dnsL_f2003.f90 index 2c5016d2d2..6739eb4f2b 100644 --- a/examples/arkode/F2003_serial/ark_roberts_dnsL_f2003.f90 +++ b/examples/arkode/F2003_serial/ark_roberts_dnsL_f2003.f90 @@ -568,9 +568,15 @@ subroutine PrintFinalStats(arkode_mem) stop 1 end if - retval = FARKStepGetNumRhsEvals(arkode_mem, nfe, nfi) + retval = FARKodeGetNumRhsEvals(arkode_mem, 0, nfe) if (retval /= 0) then - print *, 'Error in FARKStepGetNumRhsEvals, retval = ', retval, '; halting' + print *, 'Error in FARKodeGetNumRhsEvals, retval = ', retval, '; halting' + stop 1 + end if + + retval = FARKodeGetNumRhsEvals(arkode_mem, 1, nfi) + if (retval /= 0) then + print *, 'Error in FARKodeGetNumRhsEvals, retval = ', retval, '; halting' stop 1 end if diff --git a/examples/arkode/F2003_serial/ark_roberts_dns_f2003.f90 b/examples/arkode/F2003_serial/ark_roberts_dns_f2003.f90 index 79c3395ffa..d26cf5f56f 100644 --- a/examples/arkode/F2003_serial/ark_roberts_dns_f2003.f90 +++ b/examples/arkode/F2003_serial/ark_roberts_dns_f2003.f90 @@ -570,9 +570,15 @@ subroutine PrintFinalStats(arkode_mem) stop 1 end if - retval = FARKStepGetNumRhsEvals(arkode_mem, nfe, nfi) + retval = FARKodeGetNumRhsEvals(arkode_mem, 0, nfe) if (retval /= 0) then - print *, 'Error in FARKStepGetNumRhsEvals, retval = ', retval, '; halting' + print *, 'Error in FARKodeGetNumRhsEvals, retval = ', retval, '; halting' + stop 1 + end if + + retval = FARKodeGetNumRhsEvals(arkode_mem, 1, nfi) + if (retval /= 0) then + print *, 'Error in FARKodeGetNumRhsEvals, retval = ', retval, '; halting' stop 1 end if diff --git a/include/arkode/arkode.h b/include/arkode/arkode.h index f4e0667d72..f33ec560dc 100644 --- a/include/arkode/arkode.h +++ b/include/arkode/arkode.h @@ -294,6 +294,8 @@ SUNDIALS_EXPORT int ARKodeComputeState(void* arkode_mem, N_Vector zcor, N_Vector z); /* Optional output functions (general) */ +SUNDIALS_EXPORT int ARKodeGetNumRhsEvals(void* arkode_mem, int partition_index, + long int* num_rhs_evals); SUNDIALS_EXPORT int ARKodeGetNumStepAttempts(void* arkode_mem, long int* step_attempts); SUNDIALS_EXPORT int ARKodeGetWorkSpace(void* arkode_mem, long int* lenrw, diff --git a/include/arkode/arkode_arkstep.h b/include/arkode/arkode_arkstep.h index f7a6f112f5..9a0cfbb5a1 100644 --- a/include/arkode/arkode_arkstep.h +++ b/include/arkode/arkode_arkstep.h @@ -86,8 +86,6 @@ SUNDIALS_EXPORT int ARKStepSetTableName(void* arkode_mem, const char* itable, const char* etable); /* Optional output functions */ -SUNDIALS_EXPORT int ARKStepGetNumRhsEvals(void* arkode_mem, long int* nfe_evals, - long int* nfi_evals); SUNDIALS_EXPORT int ARKStepGetCurrentButcherTables(void* arkode_mem, ARKodeButcherTable* Bi, ARKodeButcherTable* Be); @@ -430,7 +428,9 @@ SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetNumRelaxSolveFails instead") int ARKStepGetNumRelaxSolveFails(void* arkode_mem, long int* fails); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetNumRelaxSolveIters instead") int ARKStepGetNumRelaxSolveIters(void* arkode_mem, long int* iters); - +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetNumRhsEvals instead") +int ARKStepGetNumRhsEvals(void* arkode_mem, long int* nfe_evals, + long int* nfi_evals); #ifdef __cplusplus } #endif diff --git a/include/arkode/arkode_erkstep.h b/include/arkode/arkode_erkstep.h index c40bab8112..ea5ad629b9 100644 --- a/include/arkode/arkode_erkstep.h +++ b/include/arkode/arkode_erkstep.h @@ -59,7 +59,6 @@ SUNDIALS_EXPORT int ERKStepSetTableNum(void* arkode_mem, SUNDIALS_EXPORT int ERKStepSetTableName(void* arkode_mem, const char* etable); /* Optional output functions */ -SUNDIALS_EXPORT int ERKStepGetNumRhsEvals(void* arkode_mem, long int* nfevals); SUNDIALS_EXPORT int ERKStepGetCurrentButcherTable(void* arkode_mem, ARKodeButcherTable* B); @@ -244,6 +243,8 @@ SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetNumRelaxSolveFails instead") int ERKStepGetNumRelaxSolveFails(void* arkode_mem, long int* fails); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetNumRelaxSolveIters instead") int ERKStepGetNumRelaxSolveIters(void* arkode_mem, long int* iters); +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetNumRhsEvals instead") +int ERKStepGetNumRhsEvals(void* arkode_mem, long int* nfevals); #ifdef __cplusplus } diff --git a/include/arkode/arkode_mristep.h b/include/arkode/arkode_mristep.h index 7fa2219e1e..828272948a 100644 --- a/include/arkode/arkode_mristep.h +++ b/include/arkode/arkode_mristep.h @@ -160,8 +160,6 @@ SUNDIALS_EXPORT int MRIStepSetPostInnerFn(void* arkode_mem, MRIStepPostInnerFn postfn); /* Optional output functions */ -SUNDIALS_EXPORT int MRIStepGetNumRhsEvals(void* arkode_mem, long int* nfse_evals, - long int* nfsi_evals); SUNDIALS_EXPORT int MRIStepGetCurrentCoupling(void* arkode_mem, MRIStepCoupling* MRIC); SUNDIALS_EXPORT int MRIStepGetLastInnerStepFlag(void* arkode_mem, int* flag); @@ -370,6 +368,9 @@ SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeFree instead") void MRIStepFree(void** arkode_mem); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodePrintMem instead") void MRIStepPrintMem(void* arkode_mem, FILE* outfile); +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetNumRhsEvals instead") +int MRIStepGetNumRhsEvals(void* arkode_mem, long int* nfse_evals, + long int* nfsi_evals); #ifdef __cplusplus } diff --git a/include/arkode/arkode_sprkstep.h b/include/arkode/arkode_sprkstep.h index 3e4519cd40..e4ed5733ff 100644 --- a/include/arkode/arkode_sprkstep.h +++ b/include/arkode/arkode_sprkstep.h @@ -57,8 +57,6 @@ SUNDIALS_EXPORT int SPRKStepSetMethodName(void* arkode_mem, const char* method); /* Optional output functions */ SUNDIALS_EXPORT int SPRKStepGetCurrentMethod(void* arkode_mem, ARKodeSPRKTable* sprk_storage); -SUNDIALS_EXPORT int SPRKStepGetNumRhsEvals(void* arkode_mem, long int* nf1, - long int* nf2); /* -------------------------------------------------------------------------- * Deprecated Functions -- all are superseded by shared ARKODE-level routines @@ -126,6 +124,8 @@ int SPRKStepGetStepStats(void* arkode_mem, long int* nsteps, sunrealtype* hcur, sunrealtype* tcur); SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeFree instead") void SPRKStepFree(void** arkode_mem); +SUNDIALS_DEPRECATED_EXPORT_MSG("use ARKodeGetNumRhsEvals instead") +int SPRKStepGetNumRhsEvals(void* arkode_mem, long int* nf1, long int* nf2); #ifdef __cplusplus } diff --git a/src/arkode/arkode.c b/src/arkode/arkode.c index 378471e507..6d66929483 100644 --- a/src/arkode/arkode.c +++ b/src/arkode/arkode.c @@ -1429,6 +1429,7 @@ ARKodeMem arkCreate(SUNContext sunctx) ark_mem->step_setmaxnonliniters = NULL; ark_mem->step_setnonlinconvcoef = NULL; ark_mem->step_setstagepredictfn = NULL; + ark_mem->step_getnumrhsevals = NULL; ark_mem->step_getnumlinsolvsetups = NULL; ark_mem->step_getestlocalerrors = NULL; ark_mem->step_getcurrentgamma = NULL; diff --git a/src/arkode/arkode_arkstep.c b/src/arkode/arkode_arkstep.c index 3a4b00622a..e1ed9c0f66 100644 --- a/src/arkode/arkode_arkstep.c +++ b/src/arkode/arkode_arkstep.c @@ -131,6 +131,7 @@ void* ARKStepCreate(ARKRhsFn fe, ARKRhsFn fi, sunrealtype t0, N_Vector y0, ark_mem->step_setmaxnonliniters = arkStep_SetMaxNonlinIters; ark_mem->step_setnonlinconvcoef = arkStep_SetNonlinConvCoef; ark_mem->step_setstagepredictfn = arkStep_SetStagePredictFn; + ark_mem->step_getnumrhsevals = arkStep_GetNumRhsEvals; ark_mem->step_getnumlinsolvsetups = arkStep_GetNumLinSolvSetups; ark_mem->step_getcurrentgamma = arkStep_GetCurrentGamma; ark_mem->step_getestlocalerrors = arkStep_GetEstLocalErrors; diff --git a/src/arkode/arkode_arkstep_impl.h b/src/arkode/arkode_arkstep_impl.h index 8af982cd1b..806101a98b 100644 --- a/src/arkode/arkode_arkstep_impl.h +++ b/src/arkode/arkode_arkstep_impl.h @@ -207,6 +207,8 @@ int arkStep_SetMaxNonlinIters(ARKodeMem ark_mem, int maxcor); int arkStep_SetNonlinConvCoef(ARKodeMem ark_mem, sunrealtype nlscoef); int arkStep_SetStagePredictFn(ARKodeMem ark_mem, ARKStagePredictFn PredictStage); int arkStep_SetDeduceImplicitRhs(ARKodeMem ark_mem, sunbooleantype deduce); +int arkStep_GetNumRhsEvals(ARKodeMem ark_mem, int partition_index, + long int* rhs_evals); int arkStep_GetEstLocalErrors(ARKodeMem ark_mem, N_Vector ele); int arkStep_GetCurrentGamma(ARKodeMem ark_mem, sunrealtype* gamma); int arkStep_GetNonlinearSystemData(ARKodeMem ark_mem, sunrealtype* tcur, diff --git a/src/arkode/arkode_arkstep_io.c b/src/arkode/arkode_arkstep_io.c index ae90b65387..c629e4d8e6 100644 --- a/src/arkode/arkode_arkstep_io.c +++ b/src/arkode/arkode_arkstep_io.c @@ -521,23 +521,52 @@ int ARKStepSetTableName(void* arkode_mem, const char* itable, const char* etable /*--------------------------------------------------------------- ARKStepGetNumRhsEvals: - Returns the current number of calls to fe and fi + Returns the current number of calls ---------------------------------------------------------------*/ +int arkStep_GetNumRhsEvals(ARKodeMem ark_mem, int partition_index, + long int* rhs_evals) +{ + ARKodeARKStepMem step_mem = NULL; + + /* access ARKodeARKStepMem structure */ + int retval = arkStep_AccessStepMem(ark_mem, __func__, &step_mem); + if (retval != ARK_SUCCESS) { return retval; } + + if (rhs_evals == NULL) + { + arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "rhs_evals is NULL"); + return ARK_ILL_INPUT; + } + + if (partition_index > 1) + { + arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "Invalid partition index"); + return ARK_ILL_INPUT; + } + + switch (partition_index) + { + case 0: *rhs_evals = step_mem->nfe; break; + case 1: *rhs_evals = step_mem->nfi; break; + default: *rhs_evals = step_mem->nfe + step_mem->nfi; break; + } + + return ARK_SUCCESS; +} + int ARKStepGetNumRhsEvals(void* arkode_mem, long int* fe_evals, long int* fi_evals) { - ARKodeMem ark_mem; - ARKodeARKStepMem step_mem; - int retval; + int retval = ARK_SUCCESS; - /* access ARKodeMem and ARKodeARKStepMem structures */ - retval = arkStep_AccessARKODEStepMem(arkode_mem, __func__, &ark_mem, &step_mem); - if (retval != ARK_SUCCESS) { return (retval); } + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, fe_evals); + if (retval != ARK_SUCCESS) { return retval; } - /* get values from step_mem */ - *fe_evals = step_mem->nfe; - *fi_evals = step_mem->nfi; + retval = ARKodeGetNumRhsEvals(arkode_mem, 1, fi_evals); + if (retval != ARK_SUCCESS) { return retval; } - return (ARK_SUCCESS); + return ARK_SUCCESS; } /*--------------------------------------------------------------- diff --git a/src/arkode/arkode_erkstep.c b/src/arkode/arkode_erkstep.c index 766ca9e217..3eaa11ca9d 100644 --- a/src/arkode/arkode_erkstep.c +++ b/src/arkode/arkode_erkstep.c @@ -102,6 +102,7 @@ void* ERKStepCreate(ARKRhsFn f, sunrealtype t0, N_Vector y0, SUNContext sunctx) ark_mem->step_setdefaults = erkStep_SetDefaults; ark_mem->step_setrelaxfn = erkStep_SetRelaxFn; ark_mem->step_setorder = erkStep_SetOrder; + ark_mem->step_getnumrhsevals = erkStep_GetNumRhsEvals; ark_mem->step_getestlocalerrors = erkStep_GetEstLocalErrors; ark_mem->step_supports_adaptive = SUNTRUE; ark_mem->step_supports_relaxation = SUNTRUE; diff --git a/src/arkode/arkode_erkstep_impl.h b/src/arkode/arkode_erkstep_impl.h index 794f112550..fc30ad1651 100644 --- a/src/arkode/arkode_erkstep_impl.h +++ b/src/arkode/arkode_erkstep_impl.h @@ -82,6 +82,8 @@ int erkStep_Resize(ARKodeMem ark_mem, N_Vector y0, sunrealtype hscale, sunrealtype t0, ARKVecResizeFn resize, void* resize_data); void erkStep_Free(ARKodeMem ark_mem); void erkStep_PrintMem(ARKodeMem ark_mem, FILE* outfile); +int erkStep_GetNumRhsEvals(ARKodeMem ark_mem, int partition_index, + long int* rhs_evals); int erkStep_GetEstLocalErrors(ARKodeMem ark_mem, N_Vector ele); /* Internal utility routines */ diff --git a/src/arkode/arkode_erkstep_io.c b/src/arkode/arkode_erkstep_io.c index 77987b4245..61bb740654 100644 --- a/src/arkode/arkode_erkstep_io.c +++ b/src/arkode/arkode_erkstep_io.c @@ -167,22 +167,39 @@ int ERKStepSetTableName(void* arkode_mem, const char* etable) /*--------------------------------------------------------------- ERKStepGetNumRhsEvals: - Returns the current number of calls to f + Returns the current number of RHS calls ---------------------------------------------------------------*/ -int ERKStepGetNumRhsEvals(void* arkode_mem, long int* fevals) +int erkStep_GetNumRhsEvals(ARKodeMem ark_mem, int partition_index, + long int* rhs_evals) { - ARKodeMem ark_mem; - ARKodeERKStepMem step_mem; - int retval; + ARKodeERKStepMem step_mem = NULL; - /* access ARKodeMem and ARKodeERKStepMem structures */ - retval = erkStep_AccessARKODEStepMem(arkode_mem, __func__, &ark_mem, &step_mem); - if (retval != ARK_SUCCESS) { return (retval); } + /* access ARKodeERKStepMem structure */ + int retval = erkStep_AccessStepMem(ark_mem, __func__, &step_mem); + if (retval != ARK_SUCCESS) { return retval; } - /* get values from step_mem */ - *fevals = step_mem->nfe; + if (rhs_evals == NULL) + { + arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "rhs_evals is NULL"); + return ARK_ILL_INPUT; + } - return (ARK_SUCCESS); + if (partition_index > 0) + { + arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "Invalid partition index"); + return ARK_ILL_INPUT; + } + + *rhs_evals = step_mem->nfe; + + return ARK_SUCCESS; +} + +int ERKStepGetNumRhsEvals(void* arkode_mem, long int* fevals) +{ + return ARKodeGetNumRhsEvals(arkode_mem, 0, fevals); } /*--------------------------------------------------------------- diff --git a/src/arkode/arkode_impl.h b/src/arkode/arkode_impl.h index fff9d2e693..f9383fe1de 100644 --- a/src/arkode/arkode_impl.h +++ b/src/arkode/arkode_impl.h @@ -224,6 +224,8 @@ typedef void (*ARKTimestepFree)(ARKodeMem ark_mem); typedef void (*ARKTimestepPrintMem)(ARKodeMem ark_mem, FILE* outfile); typedef int (*ARKTimestepSetDefaults)(ARKodeMem ark_mem); typedef int (*ARKTimestepSetOrder)(ARKodeMem ark_mem, int maxord); +typedef int (*ARKTimestepGetNumRhsEvals)(ARKodeMem ark_mem, int partition_index, + long int* num_rhs_evals); /* time stepper interface functions -- temporal adaptivity */ typedef int (*ARKTimestepGetEstLocalErrors)(ARKodeMem ark_mem, N_Vector ele); @@ -406,6 +408,7 @@ struct ARKodeMemRec ARKTimestepPrintMem step_printmem; ARKTimestepSetDefaults step_setdefaults; ARKTimestepSetOrder step_setorder; + ARKTimestepGetNumRhsEvals step_getnumrhsevals; /* Time stepper module -- temporal adaptivity */ sunbooleantype step_supports_adaptive; diff --git a/src/arkode/arkode_io.c b/src/arkode/arkode_io.c index dd1325f794..670b1fd9d0 100644 --- a/src/arkode/arkode_io.c +++ b/src/arkode/arkode_io.c @@ -1999,6 +1999,38 @@ int ARKodeSetMaxConvFails(void* arkode_mem, int maxncf) ARKODE optional output utility functions ===============================================================*/ +/*--------------------------------------------------------------- + ARKodeGetNumStepAttempts: + + Returns the current number of RHS evaluations + ---------------------------------------------------------------*/ +int ARKodeGetNumRhsEvals(void* arkode_mem, int partition_index, + long int* num_rhs_evals) +{ + ARKodeMem ark_mem; + if (arkode_mem == NULL) + { + arkProcessError(NULL, ARK_MEM_NULL, __LINE__, __func__, __FILE__, + MSG_ARK_NO_MEM); + return ARK_MEM_NULL; + } + ark_mem = (ARKodeMem)arkode_mem; + + /* Call stepper routine (if provided) */ + if (ark_mem->step_getnumrhsevals) + { + return ark_mem->step_getnumrhsevals(arkode_mem, partition_index, + num_rhs_evals); + } + else + { + arkProcessError(ark_mem, ARK_STEPPER_UNSUPPORTED, __LINE__, __func__, + __FILE__, + "time-stepping module does not support this function"); + return ARK_STEPPER_UNSUPPORTED; + } +} + /*--------------------------------------------------------------- ARKodeGetNumStepAttempts: diff --git a/src/arkode/arkode_mristep.c b/src/arkode/arkode_mristep.c index 8e5875c12f..32c26e1de0 100644 --- a/src/arkode/arkode_mristep.c +++ b/src/arkode/arkode_mristep.c @@ -131,6 +131,7 @@ void* MRIStepCreate(ARKRhsFn fse, ARKRhsFn fsi, sunrealtype t0, N_Vector y0, ark_mem->step_setmaxnonliniters = mriStep_SetMaxNonlinIters; ark_mem->step_setnonlinconvcoef = mriStep_SetNonlinConvCoef; ark_mem->step_setstagepredictfn = mriStep_SetStagePredictFn; + ark_mem->step_getnumrhsevals = mriStep_GetNumRhsEvals; ark_mem->step_getnumlinsolvsetups = mriStep_GetNumLinSolvSetups; ark_mem->step_getcurrentgamma = mriStep_GetCurrentGamma; ark_mem->step_getnonlinearsystemdata = mriStep_GetNonlinearSystemData; diff --git a/src/arkode/arkode_mristep_impl.h b/src/arkode/arkode_mristep_impl.h index 29caf263c3..f631307e07 100644 --- a/src/arkode/arkode_mristep_impl.h +++ b/src/arkode/arkode_mristep_impl.h @@ -219,6 +219,8 @@ int mriStep_SetMaxNonlinIters(ARKodeMem ark_mem, int maxcor); int mriStep_SetNonlinConvCoef(ARKodeMem ark_mem, sunrealtype nlscoef); int mriStep_SetStagePredictFn(ARKodeMem ark_mem, ARKStagePredictFn PredictStage); int mriStep_SetDeduceImplicitRhs(ARKodeMem ark_mem, sunbooleantype deduce); +int mriStep_GetNumRhsEvals(ARKodeMem ark_mem, int partition_index, + long int* rhs_evals); int mriStep_GetCurrentGamma(ARKodeMem ark_mem, sunrealtype* gamma); int mriStep_GetNonlinearSystemData(ARKodeMem ark_mem, sunrealtype* tcur, N_Vector* zpred, N_Vector* z, N_Vector* Fi, diff --git a/src/arkode/arkode_mristep_io.c b/src/arkode/arkode_mristep_io.c index 1ad11ab59e..712debfaea 100644 --- a/src/arkode/arkode_mristep_io.c +++ b/src/arkode/arkode_mristep_io.c @@ -131,24 +131,53 @@ int MRIStepSetPostInnerFn(void* arkode_mem, MRIStepPostInnerFn postfn) /*--------------------------------------------------------------- MRIStepGetNumRhsEvals: - Returns the current number of calls to fse and fsi + Returns the current number of RHS calls ---------------------------------------------------------------*/ +int mriStep_GetNumRhsEvals(ARKodeMem ark_mem, int partition_index, + long int* rhs_evals) +{ + ARKodeMRIStepMem step_mem = NULL; + + /* access ARKodeMRIStepMem structure */ + int retval = mriStep_AccessStepMem(ark_mem, __func__, &step_mem); + if (retval != ARK_SUCCESS) { return retval; } + + if (rhs_evals == NULL) + { + arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "rhs_evals is NULL"); + return ARK_ILL_INPUT; + } + + if (partition_index > 1) + { + arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "Invalid partition index"); + return ARK_ILL_INPUT; + } + + switch (partition_index) + { + case 0: *rhs_evals = step_mem->nfse; break; + case 1: *rhs_evals = step_mem->nfsi; break; + default: *rhs_evals = step_mem->nfse + step_mem->nfsi; break; + } + + return ARK_SUCCESS; +} + int MRIStepGetNumRhsEvals(void* arkode_mem, long int* nfse_evals, long int* nfsi_evals) { - ARKodeMem ark_mem; - ARKodeMRIStepMem step_mem; - int retval; + int retval = ARK_SUCCESS; - /* access ARKodeMem and ARKodeMRIStepMem structures */ - retval = mriStep_AccessARKODEStepMem(arkode_mem, __func__, &ark_mem, &step_mem); - if (retval != ARK_SUCCESS) { return (retval); } + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, nfse_evals); + if (retval != ARK_SUCCESS) { return retval; } - /* get number of fse and fsi evals from step_mem */ - *nfse_evals = step_mem->nfse; - *nfsi_evals = step_mem->nfsi; + retval = ARKodeGetNumRhsEvals(arkode_mem, 1, nfsi_evals); + if (retval != ARK_SUCCESS) { return retval; } - return (ARK_SUCCESS); + return ARK_SUCCESS; } /*--------------------------------------------------------------- diff --git a/src/arkode/arkode_sprkstep.c b/src/arkode/arkode_sprkstep.c index f7f67248c4..6c3cf4a669 100644 --- a/src/arkode/arkode_sprkstep.c +++ b/src/arkode/arkode_sprkstep.c @@ -125,6 +125,7 @@ void* SPRKStepCreate(ARKRhsFn f1, ARKRhsFn f2, sunrealtype t0, N_Vector y0, ark_mem->step_free = sprkStep_Free; ark_mem->step_setdefaults = sprkStep_SetDefaults; ark_mem->step_setorder = sprkStep_SetOrder; + ark_mem->step_getnumrhsevals = sprkStep_GetNumRhsEvals; ark_mem->step_mem = (void*)step_mem; /* Set default values for optional inputs */ diff --git a/src/arkode/arkode_sprkstep_impl.h b/src/arkode/arkode_sprkstep_impl.h index 0493106586..d94f5c5c80 100644 --- a/src/arkode/arkode_sprkstep_impl.h +++ b/src/arkode/arkode_sprkstep_impl.h @@ -83,6 +83,8 @@ int sprkStep_Resize(ARKodeMem ark_mem, N_Vector y0, sunrealtype hscale, sunrealtype t0, ARKVecResizeFn resize, void* resize_data); void sprkStep_Free(ARKodeMem ark_mem); void sprkStep_PrintMem(ARKodeMem ark_mem, FILE* outfile); +int sprkStep_GetNumRhsEvals(ARKodeMem ark_mem, int partition_index, + long int* rhs_evals); /* Internal utility routines */ int sprkStep_AccessARKODEStepMem(void* arkode_mem, const char* fname, diff --git a/src/arkode/arkode_sprkstep_io.c b/src/arkode/arkode_sprkstep_io.c index 88378f14ca..8dc76a9234 100644 --- a/src/arkode/arkode_sprkstep_io.c +++ b/src/arkode/arkode_sprkstep_io.c @@ -154,23 +154,52 @@ int SPRKStepGetCurrentMethod(void* arkode_mem, ARKodeSPRKTable* sprk_storage) /*--------------------------------------------------------------- SPRKStepGetNumRhsEvals: - Returns the current number of calls to f1 and f2 + Returns the current number of RHS calls ---------------------------------------------------------------*/ -int SPRKStepGetNumRhsEvals(void* arkode_mem, long int* nf1, long int* nf2) +int sprkStep_GetNumRhsEvals(ARKodeMem ark_mem, int partition_index, + long int* rhs_evals) { - ARKodeMem ark_mem = NULL; ARKodeSPRKStepMem step_mem = NULL; - int retval = 0; - /* access ARKodeMem and ARKodeSPRKStepMem structures */ - retval = sprkStep_AccessARKODEStepMem(arkode_mem, __func__, &ark_mem, - &step_mem); - if (retval != ARK_SUCCESS) { return (retval); } + /* access ARKodeSPRKStepMem structure */ + int retval = sprkStep_AccessStepMem(ark_mem, __func__, &step_mem); + if (retval != ARK_SUCCESS) { return retval; } - *nf1 = step_mem->nf1; - *nf2 = step_mem->nf2; + if (rhs_evals == NULL) + { + arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "rhs_evals is NULL"); + return ARK_ILL_INPUT; + } - return (ARK_SUCCESS); + if (partition_index > 1) + { + arkProcessError(ark_mem, ARK_ILL_INPUT, __LINE__, __func__, __FILE__, + "Invalid partition index"); + return ARK_ILL_INPUT; + } + + switch (partition_index) + { + case 0: *rhs_evals = step_mem->nf1; break; + case 1: *rhs_evals = step_mem->nf2; break; + default: *rhs_evals = step_mem->nf1 + step_mem->nf2; break; + } + + return ARK_SUCCESS; +} + +int SPRKStepGetNumRhsEvals(void* arkode_mem, long int* nf1, long int* nf2) +{ + int retval = ARK_SUCCESS; + + retval = ARKodeGetNumRhsEvals(arkode_mem, 0, nf1); + if (retval != ARK_SUCCESS) { return retval; } + + retval = ARKodeGetNumRhsEvals(arkode_mem, 1, nf2); + if (retval != ARK_SUCCESS) { return retval; } + + return ARK_SUCCESS; } /*=============================================================== diff --git a/src/arkode/fmod_int32/farkode_arkstep_mod.c b/src/arkode/fmod_int32/farkode_arkstep_mod.c index 4791bedcdc..944fd591b0 100644 --- a/src/arkode/fmod_int32/farkode_arkstep_mod.c +++ b/src/arkode/fmod_int32/farkode_arkstep_mod.c @@ -361,22 +361,6 @@ SWIGEXPORT int _wrap_FARKStepSetTableName(void *farg1, SwigArrayWrapper *farg2, } -SWIGEXPORT int _wrap_FARKStepGetNumRhsEvals(void *farg1, long *farg2, long *farg3) { - int fresult ; - void *arg1 = (void *) 0 ; - long *arg2 = (long *) 0 ; - long *arg3 = (long *) 0 ; - int result; - - arg1 = (void *)(farg1); - arg2 = (long *)(farg2); - arg3 = (long *)(farg3); - result = (int)ARKStepGetNumRhsEvals(arg1,arg2,arg3); - fresult = (int)(result); - return fresult; -} - - SWIGEXPORT int _wrap_FARKStepGetCurrentButcherTables(void *farg1, void *farg2, void *farg3) { int fresult ; void *arg1 = (void *) 0 ; @@ -2657,4 +2641,20 @@ SWIGEXPORT int _wrap_FARKStepGetNumRelaxSolveIters(void *farg1, long *farg2) { } +SWIGEXPORT int _wrap_FARKStepGetNumRhsEvals(void *farg1, long *farg2, long *farg3) { + int fresult ; + void *arg1 = (void *) 0 ; + long *arg2 = (long *) 0 ; + long *arg3 = (long *) 0 ; + int result; + + arg1 = (void *)(farg1); + arg2 = (long *)(farg2); + arg3 = (long *)(farg3); + result = (int)ARKStepGetNumRhsEvals(arg1,arg2,arg3); + fresult = (int)(result); + return fresult; +} + + diff --git a/src/arkode/fmod_int32/farkode_arkstep_mod.f90 b/src/arkode/fmod_int32/farkode_arkstep_mod.f90 index cc0373f1eb..ae1f6659eb 100644 --- a/src/arkode/fmod_int32/farkode_arkstep_mod.f90 +++ b/src/arkode/fmod_int32/farkode_arkstep_mod.f90 @@ -60,7 +60,6 @@ module farkode_arkstep_mod integer(C_SIZE_T), public :: size = 0 end type public :: FARKStepSetTableName - public :: FARKStepGetNumRhsEvals public :: FARKStepGetCurrentButcherTables public :: FARKStepGetTimestepperStats public :: FARKStepCreateMRIStepInnerStepper @@ -218,6 +217,7 @@ module farkode_arkstep_mod public :: FARKStepGetNumRelaxBoundFails public :: FARKStepGetNumRelaxSolveFails public :: FARKStepGetNumRelaxSolveIters + public :: FARKStepGetNumRhsEvals ! WRAPPER DECLARATIONS interface @@ -302,16 +302,6 @@ function swigc_FARKStepSetTableName(farg1, farg2, farg3) & integer(C_INT) :: fresult end function -function swigc_FARKStepGetNumRhsEvals(farg1, farg2, farg3) & -bind(C, name="_wrap_FARKStepGetNumRhsEvals") & -result(fresult) -use, intrinsic :: ISO_C_BINDING -type(C_PTR), value :: farg1 -type(C_PTR), value :: farg2 -type(C_PTR), value :: farg3 -integer(C_INT) :: fresult -end function - function swigc_FARKStepGetCurrentButcherTables(farg1, farg2, farg3) & bind(C, name="_wrap_FARKStepGetCurrentButcherTables") & result(fresult) @@ -1772,6 +1762,16 @@ function swigc_FARKStepGetNumRelaxSolveIters(farg1, farg2) & integer(C_INT) :: fresult end function +function swigc_FARKStepGetNumRhsEvals(farg1, farg2, farg3) & +bind(C, name="_wrap_FARKStepGetNumRhsEvals") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +type(C_PTR), value :: farg3 +integer(C_INT) :: fresult +end function + end interface @@ -1949,25 +1949,6 @@ function FARKStepSetTableName(arkode_mem, itable, etable) & swig_result = fresult end function -function FARKStepGetNumRhsEvals(arkode_mem, nfe_evals, nfi_evals) & -result(swig_result) -use, intrinsic :: ISO_C_BINDING -integer(C_INT) :: swig_result -type(C_PTR) :: arkode_mem -integer(C_LONG), dimension(*), target, intent(inout) :: nfe_evals -integer(C_LONG), dimension(*), target, intent(inout) :: nfi_evals -integer(C_INT) :: fresult -type(C_PTR) :: farg1 -type(C_PTR) :: farg2 -type(C_PTR) :: farg3 - -farg1 = arkode_mem -farg2 = c_loc(nfe_evals(1)) -farg3 = c_loc(nfi_evals(1)) -fresult = swigc_FARKStepGetNumRhsEvals(farg1, farg2, farg3) -swig_result = fresult -end function - function FARKStepGetCurrentButcherTables(arkode_mem, bi, be) & result(swig_result) use, intrinsic :: ISO_C_BINDING @@ -4621,5 +4602,24 @@ function FARKStepGetNumRelaxSolveIters(arkode_mem, iters) & swig_result = fresult end function +function FARKStepGetNumRhsEvals(arkode_mem, nfe_evals, nfi_evals) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: arkode_mem +integer(C_LONG), dimension(*), target, intent(inout) :: nfe_evals +integer(C_LONG), dimension(*), target, intent(inout) :: nfi_evals +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 +type(C_PTR) :: farg3 + +farg1 = arkode_mem +farg2 = c_loc(nfe_evals(1)) +farg3 = c_loc(nfi_evals(1)) +fresult = swigc_FARKStepGetNumRhsEvals(farg1, farg2, farg3) +swig_result = fresult +end function + end module diff --git a/src/arkode/fmod_int32/farkode_erkstep_mod.c b/src/arkode/fmod_int32/farkode_erkstep_mod.c index 5def57befc..c5fee45581 100644 --- a/src/arkode/fmod_int32/farkode_erkstep_mod.c +++ b/src/arkode/fmod_int32/farkode_erkstep_mod.c @@ -311,20 +311,6 @@ SWIGEXPORT int _wrap_FERKStepSetTableName(void *farg1, SwigArrayWrapper *farg2) } -SWIGEXPORT int _wrap_FERKStepGetNumRhsEvals(void *farg1, long *farg2) { - int fresult ; - void *arg1 = (void *) 0 ; - long *arg2 = (long *) 0 ; - int result; - - arg1 = (void *)(farg1); - arg2 = (long *)(farg2); - result = (int)ERKStepGetNumRhsEvals(arg1,arg2); - fresult = (int)(result); - return fresult; -} - - SWIGEXPORT int _wrap_FERKStepGetCurrentButcherTable(void *farg1, void *farg2) { int fresult ; void *arg1 = (void *) 0 ; @@ -1560,4 +1546,18 @@ SWIGEXPORT int _wrap_FERKStepGetNumRelaxSolveIters(void *farg1, long *farg2) { } +SWIGEXPORT int _wrap_FERKStepGetNumRhsEvals(void *farg1, long *farg2) { + int fresult ; + void *arg1 = (void *) 0 ; + long *arg2 = (long *) 0 ; + int result; + + arg1 = (void *)(farg1); + arg2 = (long *)(farg2); + result = (int)ERKStepGetNumRhsEvals(arg1,arg2); + fresult = (int)(result); + return fresult; +} + + diff --git a/src/arkode/fmod_int32/farkode_erkstep_mod.f90 b/src/arkode/fmod_int32/farkode_erkstep_mod.f90 index 291dc643d5..70531d6a64 100644 --- a/src/arkode/fmod_int32/farkode_erkstep_mod.f90 +++ b/src/arkode/fmod_int32/farkode_erkstep_mod.f90 @@ -44,7 +44,6 @@ module farkode_erkstep_mod integer(C_SIZE_T), public :: size = 0 end type public :: FERKStepSetTableName - public :: FERKStepGetNumRhsEvals public :: FERKStepGetCurrentButcherTable public :: FERKStepGetTimestepperStats public :: FERKStepResize @@ -130,6 +129,7 @@ module farkode_erkstep_mod public :: FERKStepGetNumRelaxBoundFails public :: FERKStepGetNumRelaxSolveFails public :: FERKStepGetNumRelaxSolveIters + public :: FERKStepGetNumRhsEvals ! WRAPPER DECLARATIONS interface @@ -183,15 +183,6 @@ function swigc_FERKStepSetTableName(farg1, farg2) & integer(C_INT) :: fresult end function -function swigc_FERKStepGetNumRhsEvals(farg1, farg2) & -bind(C, name="_wrap_FERKStepGetNumRhsEvals") & -result(fresult) -use, intrinsic :: ISO_C_BINDING -type(C_PTR), value :: farg1 -type(C_PTR), value :: farg2 -integer(C_INT) :: fresult -end function - function swigc_FERKStepGetCurrentButcherTable(farg1, farg2) & bind(C, name="_wrap_FERKStepGetCurrentButcherTable") & result(fresult) @@ -985,6 +976,15 @@ function swigc_FERKStepGetNumRelaxSolveIters(farg1, farg2) & integer(C_INT) :: fresult end function +function swigc_FERKStepGetNumRhsEvals(farg1, farg2) & +bind(C, name="_wrap_FERKStepGetNumRhsEvals") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +integer(C_INT) :: fresult +end function + end interface @@ -1101,22 +1101,6 @@ function FERKStepSetTableName(arkode_mem, etable) & swig_result = fresult end function -function FERKStepGetNumRhsEvals(arkode_mem, nfevals) & -result(swig_result) -use, intrinsic :: ISO_C_BINDING -integer(C_INT) :: swig_result -type(C_PTR) :: arkode_mem -integer(C_LONG), dimension(*), target, intent(inout) :: nfevals -integer(C_INT) :: fresult -type(C_PTR) :: farg1 -type(C_PTR) :: farg2 - -farg1 = arkode_mem -farg2 = c_loc(nfevals(1)) -fresult = swigc_FERKStepGetNumRhsEvals(farg1, farg2) -swig_result = fresult -end function - function FERKStepGetCurrentButcherTable(arkode_mem, b) & result(swig_result) use, intrinsic :: ISO_C_BINDING @@ -2562,5 +2546,21 @@ function FERKStepGetNumRelaxSolveIters(arkode_mem, iters) & swig_result = fresult end function +function FERKStepGetNumRhsEvals(arkode_mem, nfevals) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: arkode_mem +integer(C_LONG), dimension(*), target, intent(inout) :: nfevals +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 + +farg1 = arkode_mem +farg2 = c_loc(nfevals(1)) +fresult = swigc_FERKStepGetNumRhsEvals(farg1, farg2) +swig_result = fresult +end function + end module diff --git a/src/arkode/fmod_int32/farkode_mod.c b/src/arkode/fmod_int32/farkode_mod.c index 1423d2e582..52f187e8c4 100644 --- a/src/arkode/fmod_int32/farkode_mod.c +++ b/src/arkode/fmod_int32/farkode_mod.c @@ -1193,6 +1193,22 @@ SWIGEXPORT int _wrap_FARKodeComputeState(void *farg1, N_Vector farg2, N_Vector f } +SWIGEXPORT int _wrap_FARKodeGetNumRhsEvals(void *farg1, int const *farg2, long *farg3) { + int fresult ; + void *arg1 = (void *) 0 ; + int arg2 ; + long *arg3 = (long *) 0 ; + int result; + + arg1 = (void *)(farg1); + arg2 = (int)(*farg2); + arg3 = (long *)(farg3); + result = (int)ARKodeGetNumRhsEvals(arg1,arg2,arg3); + fresult = (int)(result); + return fresult; +} + + SWIGEXPORT int _wrap_FARKodeGetNumStepAttempts(void *farg1, long *farg2) { int fresult ; void *arg1 = (void *) 0 ; diff --git a/src/arkode/fmod_int32/farkode_mod.f90 b/src/arkode/fmod_int32/farkode_mod.f90 index 366867f40a..d5eefa63da 100644 --- a/src/arkode/fmod_int32/farkode_mod.f90 +++ b/src/arkode/fmod_int32/farkode_mod.f90 @@ -163,6 +163,7 @@ module farkode_mod public :: FARKodeEvolve public :: FARKodeGetDky public :: FARKodeComputeState + public :: FARKodeGetNumRhsEvals public :: FARKodeGetNumStepAttempts public :: FARKodeGetWorkSpace public :: FARKodeGetNumSteps @@ -1019,6 +1020,16 @@ function swigc_FARKodeComputeState(farg1, farg2, farg3) & integer(C_INT) :: fresult end function +function swigc_FARKodeGetNumRhsEvals(farg1, farg2, farg3) & +bind(C, name="_wrap_FARKodeGetNumRhsEvals") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +integer(C_INT), intent(in) :: farg2 +type(C_PTR), value :: farg3 +integer(C_INT) :: fresult +end function + function swigc_FARKodeGetNumStepAttempts(farg1, farg2) & bind(C, name="_wrap_FARKodeGetNumStepAttempts") & result(fresult) @@ -3381,6 +3392,25 @@ function FARKodeComputeState(arkode_mem, zcor, z) & swig_result = fresult end function +function FARKodeGetNumRhsEvals(arkode_mem, partition_index, num_rhs_evals) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: arkode_mem +integer(C_INT), intent(in) :: partition_index +integer(C_LONG), dimension(*), target, intent(inout) :: num_rhs_evals +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +integer(C_INT) :: farg2 +type(C_PTR) :: farg3 + +farg1 = arkode_mem +farg2 = partition_index +farg3 = c_loc(num_rhs_evals(1)) +fresult = swigc_FARKodeGetNumRhsEvals(farg1, farg2, farg3) +swig_result = fresult +end function + function FARKodeGetNumStepAttempts(arkode_mem, step_attempts) & result(swig_result) use, intrinsic :: ISO_C_BINDING diff --git a/src/arkode/fmod_int32/farkode_mristep_mod.c b/src/arkode/fmod_int32/farkode_mristep_mod.c index 35721938c4..8b6a72b660 100644 --- a/src/arkode/fmod_int32/farkode_mristep_mod.c +++ b/src/arkode/fmod_int32/farkode_mristep_mod.c @@ -713,22 +713,6 @@ SWIGEXPORT int _wrap_FMRIStepSetPostInnerFn(void *farg1, MRIStepPostInnerFn farg } -SWIGEXPORT int _wrap_FMRIStepGetNumRhsEvals(void *farg1, long *farg2, long *farg3) { - int fresult ; - void *arg1 = (void *) 0 ; - long *arg2 = (long *) 0 ; - long *arg3 = (long *) 0 ; - int result; - - arg1 = (void *)(farg1); - arg2 = (long *)(farg2); - arg3 = (long *)(farg3); - result = (int)MRIStepGetNumRhsEvals(arg1,arg2,arg3); - fresult = (int)(result); - return fresult; -} - - SWIGEXPORT int _wrap_FMRIStepGetCurrentCoupling(void *farg1, void *farg2) { int fresult ; void *arg1 = (void *) 0 ; @@ -2111,4 +2095,20 @@ SWIGEXPORT void _wrap_FMRIStepPrintMem(void *farg1, void *farg2) { } +SWIGEXPORT int _wrap_FMRIStepGetNumRhsEvals(void *farg1, long *farg2, long *farg3) { + int fresult ; + void *arg1 = (void *) 0 ; + long *arg2 = (long *) 0 ; + long *arg3 = (long *) 0 ; + int result; + + arg1 = (void *)(farg1); + arg2 = (long *)(farg2); + arg3 = (long *)(farg3); + result = (int)MRIStepGetNumRhsEvals(arg1,arg2,arg3); + fresult = (int)(result); + return fresult; +} + + diff --git a/src/arkode/fmod_int32/farkode_mristep_mod.f90 b/src/arkode/fmod_int32/farkode_mristep_mod.f90 index 74a3de5637..ecba398b89 100644 --- a/src/arkode/fmod_int32/farkode_mristep_mod.f90 +++ b/src/arkode/fmod_int32/farkode_mristep_mod.f90 @@ -129,7 +129,6 @@ module farkode_mristep_mod public :: FMRIStepSetCoupling public :: FMRIStepSetPreInnerFn public :: FMRIStepSetPostInnerFn - public :: FMRIStepGetNumRhsEvals public :: FMRIStepGetCurrentCoupling public :: FMRIStepGetLastInnerStepFlag public :: FMRIStepInnerStepper_Create @@ -226,6 +225,7 @@ module farkode_mristep_mod public :: FMRIStepGetLinReturnFlagName public :: FMRIStepFree public :: FMRIStepPrintMem + public :: FMRIStepGetNumRhsEvals ! WRAPPER DECLARATIONS interface @@ -503,16 +503,6 @@ function swigc_FMRIStepSetPostInnerFn(farg1, farg2) & integer(C_INT) :: fresult end function -function swigc_FMRIStepGetNumRhsEvals(farg1, farg2, farg3) & -bind(C, name="_wrap_FMRIStepGetNumRhsEvals") & -result(fresult) -use, intrinsic :: ISO_C_BINDING -type(C_PTR), value :: farg1 -type(C_PTR), value :: farg2 -type(C_PTR), value :: farg3 -integer(C_INT) :: fresult -end function - function swigc_FMRIStepGetCurrentCoupling(farg1, farg2) & bind(C, name="_wrap_FMRIStepGetCurrentCoupling") & result(fresult) @@ -1402,6 +1392,16 @@ subroutine swigc_FMRIStepPrintMem(farg1, farg2) & type(C_PTR), value :: farg2 end subroutine +function swigc_FMRIStepGetNumRhsEvals(farg1, farg2, farg3) & +bind(C, name="_wrap_FMRIStepGetNumRhsEvals") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +type(C_PTR), value :: farg3 +integer(C_INT) :: fresult +end function + end interface @@ -1883,25 +1883,6 @@ function FMRIStepSetPostInnerFn(arkode_mem, postfn) & swig_result = fresult end function -function FMRIStepGetNumRhsEvals(arkode_mem, nfse_evals, nfsi_evals) & -result(swig_result) -use, intrinsic :: ISO_C_BINDING -integer(C_INT) :: swig_result -type(C_PTR) :: arkode_mem -integer(C_LONG), dimension(*), target, intent(inout) :: nfse_evals -integer(C_LONG), dimension(*), target, intent(inout) :: nfsi_evals -integer(C_INT) :: fresult -type(C_PTR) :: farg1 -type(C_PTR) :: farg2 -type(C_PTR) :: farg3 - -farg1 = arkode_mem -farg2 = c_loc(nfse_evals(1)) -farg3 = c_loc(nfsi_evals(1)) -fresult = swigc_FMRIStepGetNumRhsEvals(farg1, farg2, farg3) -swig_result = fresult -end function - function FMRIStepGetCurrentCoupling(arkode_mem, mric) & result(swig_result) use, intrinsic :: ISO_C_BINDING @@ -3512,5 +3493,24 @@ subroutine FMRIStepPrintMem(arkode_mem, outfile) call swigc_FMRIStepPrintMem(farg1, farg2) end subroutine +function FMRIStepGetNumRhsEvals(arkode_mem, nfse_evals, nfsi_evals) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: arkode_mem +integer(C_LONG), dimension(*), target, intent(inout) :: nfse_evals +integer(C_LONG), dimension(*), target, intent(inout) :: nfsi_evals +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 +type(C_PTR) :: farg3 + +farg1 = arkode_mem +farg2 = c_loc(nfse_evals(1)) +farg3 = c_loc(nfsi_evals(1)) +fresult = swigc_FMRIStepGetNumRhsEvals(farg1, farg2, farg3) +swig_result = fresult +end function + end module diff --git a/src/arkode/fmod_int32/farkode_sprkstep_mod.c b/src/arkode/fmod_int32/farkode_sprkstep_mod.c index 28cfb297d4..f2888129b1 100644 --- a/src/arkode/fmod_int32/farkode_sprkstep_mod.c +++ b/src/arkode/fmod_int32/farkode_sprkstep_mod.c @@ -329,22 +329,6 @@ SWIGEXPORT int _wrap_FSPRKStepGetCurrentMethod(void *farg1, void *farg2) { } -SWIGEXPORT int _wrap_FSPRKStepGetNumRhsEvals(void *farg1, long *farg2, long *farg3) { - int fresult ; - void *arg1 = (void *) 0 ; - long *arg2 = (long *) 0 ; - long *arg3 = (long *) 0 ; - int result; - - arg1 = (void *)(farg1); - arg2 = (long *)(farg2); - arg3 = (long *)(farg3); - result = (int)SPRKStepGetNumRhsEvals(arg1,arg2,arg3); - fresult = (int)(result); - return fresult; -} - - SWIGEXPORT int _wrap_FSPRKStepReset(void *farg1, double const *farg2, N_Vector farg3) { int fresult ; void *arg1 = (void *) 0 ; @@ -764,4 +748,20 @@ SWIGEXPORT void _wrap_FSPRKStepFree(void *farg1) { } +SWIGEXPORT int _wrap_FSPRKStepGetNumRhsEvals(void *farg1, long *farg2, long *farg3) { + int fresult ; + void *arg1 = (void *) 0 ; + long *arg2 = (long *) 0 ; + long *arg3 = (long *) 0 ; + int result; + + arg1 = (void *)(farg1); + arg2 = (long *)(farg2); + arg3 = (long *)(farg3); + result = (int)SPRKStepGetNumRhsEvals(arg1,arg2,arg3); + fresult = (int)(result); + return fresult; +} + + diff --git a/src/arkode/fmod_int32/farkode_sprkstep_mod.f90 b/src/arkode/fmod_int32/farkode_sprkstep_mod.f90 index 82217e7b1b..55f3b8f3f0 100644 --- a/src/arkode/fmod_int32/farkode_sprkstep_mod.f90 +++ b/src/arkode/fmod_int32/farkode_sprkstep_mod.f90 @@ -44,7 +44,6 @@ module farkode_sprkstep_mod end type public :: FSPRKStepSetMethodName public :: FSPRKStepGetCurrentMethod - public :: FSPRKStepGetNumRhsEvals public :: FSPRKStepReset public :: FSPRKStepRootInit public :: FSPRKStepSetRootDirection @@ -74,6 +73,7 @@ module farkode_sprkstep_mod public :: FSPRKStepWriteParameters public :: FSPRKStepGetStepStats public :: FSPRKStepFree + public :: FSPRKStepGetNumRhsEvals ! WRAPPER DECLARATIONS interface @@ -138,16 +138,6 @@ function swigc_FSPRKStepGetCurrentMethod(farg1, farg2) & integer(C_INT) :: fresult end function -function swigc_FSPRKStepGetNumRhsEvals(farg1, farg2, farg3) & -bind(C, name="_wrap_FSPRKStepGetNumRhsEvals") & -result(fresult) -use, intrinsic :: ISO_C_BINDING -type(C_PTR), value :: farg1 -type(C_PTR), value :: farg2 -type(C_PTR), value :: farg3 -integer(C_INT) :: fresult -end function - function swigc_FSPRKStepReset(farg1, farg2, farg3) & bind(C, name="_wrap_FSPRKStepReset") & result(fresult) @@ -421,6 +411,16 @@ subroutine swigc_FSPRKStepFree(farg1) & type(C_PTR), value :: farg1 end subroutine +function swigc_FSPRKStepGetNumRhsEvals(farg1, farg2, farg3) & +bind(C, name="_wrap_FSPRKStepGetNumRhsEvals") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +type(C_PTR), value :: farg3 +integer(C_INT) :: fresult +end function + end interface @@ -559,25 +559,6 @@ function FSPRKStepGetCurrentMethod(arkode_mem, sprk_storage) & swig_result = fresult end function -function FSPRKStepGetNumRhsEvals(arkode_mem, nf1, nf2) & -result(swig_result) -use, intrinsic :: ISO_C_BINDING -integer(C_INT) :: swig_result -type(C_PTR) :: arkode_mem -integer(C_LONG), dimension(*), target, intent(inout) :: nf1 -integer(C_LONG), dimension(*), target, intent(inout) :: nf2 -integer(C_INT) :: fresult -type(C_PTR) :: farg1 -type(C_PTR) :: farg2 -type(C_PTR) :: farg3 - -farg1 = arkode_mem -farg2 = c_loc(nf1(1)) -farg3 = c_loc(nf2(1)) -fresult = swigc_FSPRKStepGetNumRhsEvals(farg1, farg2, farg3) -swig_result = fresult -end function - function FSPRKStepReset(arkode_mem, tr, yr) & result(swig_result) use, intrinsic :: ISO_C_BINDING @@ -1077,5 +1058,24 @@ subroutine FSPRKStepFree(arkode_mem) call swigc_FSPRKStepFree(farg1) end subroutine +function FSPRKStepGetNumRhsEvals(arkode_mem, nf1, nf2) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: arkode_mem +integer(C_LONG), dimension(*), target, intent(inout) :: nf1 +integer(C_LONG), dimension(*), target, intent(inout) :: nf2 +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 +type(C_PTR) :: farg3 + +farg1 = arkode_mem +farg2 = c_loc(nf1(1)) +farg3 = c_loc(nf2(1)) +fresult = swigc_FSPRKStepGetNumRhsEvals(farg1, farg2, farg3) +swig_result = fresult +end function + end module diff --git a/src/arkode/fmod_int64/farkode_arkstep_mod.c b/src/arkode/fmod_int64/farkode_arkstep_mod.c index 4791bedcdc..944fd591b0 100644 --- a/src/arkode/fmod_int64/farkode_arkstep_mod.c +++ b/src/arkode/fmod_int64/farkode_arkstep_mod.c @@ -361,22 +361,6 @@ SWIGEXPORT int _wrap_FARKStepSetTableName(void *farg1, SwigArrayWrapper *farg2, } -SWIGEXPORT int _wrap_FARKStepGetNumRhsEvals(void *farg1, long *farg2, long *farg3) { - int fresult ; - void *arg1 = (void *) 0 ; - long *arg2 = (long *) 0 ; - long *arg3 = (long *) 0 ; - int result; - - arg1 = (void *)(farg1); - arg2 = (long *)(farg2); - arg3 = (long *)(farg3); - result = (int)ARKStepGetNumRhsEvals(arg1,arg2,arg3); - fresult = (int)(result); - return fresult; -} - - SWIGEXPORT int _wrap_FARKStepGetCurrentButcherTables(void *farg1, void *farg2, void *farg3) { int fresult ; void *arg1 = (void *) 0 ; @@ -2657,4 +2641,20 @@ SWIGEXPORT int _wrap_FARKStepGetNumRelaxSolveIters(void *farg1, long *farg2) { } +SWIGEXPORT int _wrap_FARKStepGetNumRhsEvals(void *farg1, long *farg2, long *farg3) { + int fresult ; + void *arg1 = (void *) 0 ; + long *arg2 = (long *) 0 ; + long *arg3 = (long *) 0 ; + int result; + + arg1 = (void *)(farg1); + arg2 = (long *)(farg2); + arg3 = (long *)(farg3); + result = (int)ARKStepGetNumRhsEvals(arg1,arg2,arg3); + fresult = (int)(result); + return fresult; +} + + diff --git a/src/arkode/fmod_int64/farkode_arkstep_mod.f90 b/src/arkode/fmod_int64/farkode_arkstep_mod.f90 index cc0373f1eb..ae1f6659eb 100644 --- a/src/arkode/fmod_int64/farkode_arkstep_mod.f90 +++ b/src/arkode/fmod_int64/farkode_arkstep_mod.f90 @@ -60,7 +60,6 @@ module farkode_arkstep_mod integer(C_SIZE_T), public :: size = 0 end type public :: FARKStepSetTableName - public :: FARKStepGetNumRhsEvals public :: FARKStepGetCurrentButcherTables public :: FARKStepGetTimestepperStats public :: FARKStepCreateMRIStepInnerStepper @@ -218,6 +217,7 @@ module farkode_arkstep_mod public :: FARKStepGetNumRelaxBoundFails public :: FARKStepGetNumRelaxSolveFails public :: FARKStepGetNumRelaxSolveIters + public :: FARKStepGetNumRhsEvals ! WRAPPER DECLARATIONS interface @@ -302,16 +302,6 @@ function swigc_FARKStepSetTableName(farg1, farg2, farg3) & integer(C_INT) :: fresult end function -function swigc_FARKStepGetNumRhsEvals(farg1, farg2, farg3) & -bind(C, name="_wrap_FARKStepGetNumRhsEvals") & -result(fresult) -use, intrinsic :: ISO_C_BINDING -type(C_PTR), value :: farg1 -type(C_PTR), value :: farg2 -type(C_PTR), value :: farg3 -integer(C_INT) :: fresult -end function - function swigc_FARKStepGetCurrentButcherTables(farg1, farg2, farg3) & bind(C, name="_wrap_FARKStepGetCurrentButcherTables") & result(fresult) @@ -1772,6 +1762,16 @@ function swigc_FARKStepGetNumRelaxSolveIters(farg1, farg2) & integer(C_INT) :: fresult end function +function swigc_FARKStepGetNumRhsEvals(farg1, farg2, farg3) & +bind(C, name="_wrap_FARKStepGetNumRhsEvals") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +type(C_PTR), value :: farg3 +integer(C_INT) :: fresult +end function + end interface @@ -1949,25 +1949,6 @@ function FARKStepSetTableName(arkode_mem, itable, etable) & swig_result = fresult end function -function FARKStepGetNumRhsEvals(arkode_mem, nfe_evals, nfi_evals) & -result(swig_result) -use, intrinsic :: ISO_C_BINDING -integer(C_INT) :: swig_result -type(C_PTR) :: arkode_mem -integer(C_LONG), dimension(*), target, intent(inout) :: nfe_evals -integer(C_LONG), dimension(*), target, intent(inout) :: nfi_evals -integer(C_INT) :: fresult -type(C_PTR) :: farg1 -type(C_PTR) :: farg2 -type(C_PTR) :: farg3 - -farg1 = arkode_mem -farg2 = c_loc(nfe_evals(1)) -farg3 = c_loc(nfi_evals(1)) -fresult = swigc_FARKStepGetNumRhsEvals(farg1, farg2, farg3) -swig_result = fresult -end function - function FARKStepGetCurrentButcherTables(arkode_mem, bi, be) & result(swig_result) use, intrinsic :: ISO_C_BINDING @@ -4621,5 +4602,24 @@ function FARKStepGetNumRelaxSolveIters(arkode_mem, iters) & swig_result = fresult end function +function FARKStepGetNumRhsEvals(arkode_mem, nfe_evals, nfi_evals) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: arkode_mem +integer(C_LONG), dimension(*), target, intent(inout) :: nfe_evals +integer(C_LONG), dimension(*), target, intent(inout) :: nfi_evals +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 +type(C_PTR) :: farg3 + +farg1 = arkode_mem +farg2 = c_loc(nfe_evals(1)) +farg3 = c_loc(nfi_evals(1)) +fresult = swigc_FARKStepGetNumRhsEvals(farg1, farg2, farg3) +swig_result = fresult +end function + end module diff --git a/src/arkode/fmod_int64/farkode_erkstep_mod.c b/src/arkode/fmod_int64/farkode_erkstep_mod.c index 5def57befc..c5fee45581 100644 --- a/src/arkode/fmod_int64/farkode_erkstep_mod.c +++ b/src/arkode/fmod_int64/farkode_erkstep_mod.c @@ -311,20 +311,6 @@ SWIGEXPORT int _wrap_FERKStepSetTableName(void *farg1, SwigArrayWrapper *farg2) } -SWIGEXPORT int _wrap_FERKStepGetNumRhsEvals(void *farg1, long *farg2) { - int fresult ; - void *arg1 = (void *) 0 ; - long *arg2 = (long *) 0 ; - int result; - - arg1 = (void *)(farg1); - arg2 = (long *)(farg2); - result = (int)ERKStepGetNumRhsEvals(arg1,arg2); - fresult = (int)(result); - return fresult; -} - - SWIGEXPORT int _wrap_FERKStepGetCurrentButcherTable(void *farg1, void *farg2) { int fresult ; void *arg1 = (void *) 0 ; @@ -1560,4 +1546,18 @@ SWIGEXPORT int _wrap_FERKStepGetNumRelaxSolveIters(void *farg1, long *farg2) { } +SWIGEXPORT int _wrap_FERKStepGetNumRhsEvals(void *farg1, long *farg2) { + int fresult ; + void *arg1 = (void *) 0 ; + long *arg2 = (long *) 0 ; + int result; + + arg1 = (void *)(farg1); + arg2 = (long *)(farg2); + result = (int)ERKStepGetNumRhsEvals(arg1,arg2); + fresult = (int)(result); + return fresult; +} + + diff --git a/src/arkode/fmod_int64/farkode_erkstep_mod.f90 b/src/arkode/fmod_int64/farkode_erkstep_mod.f90 index 291dc643d5..70531d6a64 100644 --- a/src/arkode/fmod_int64/farkode_erkstep_mod.f90 +++ b/src/arkode/fmod_int64/farkode_erkstep_mod.f90 @@ -44,7 +44,6 @@ module farkode_erkstep_mod integer(C_SIZE_T), public :: size = 0 end type public :: FERKStepSetTableName - public :: FERKStepGetNumRhsEvals public :: FERKStepGetCurrentButcherTable public :: FERKStepGetTimestepperStats public :: FERKStepResize @@ -130,6 +129,7 @@ module farkode_erkstep_mod public :: FERKStepGetNumRelaxBoundFails public :: FERKStepGetNumRelaxSolveFails public :: FERKStepGetNumRelaxSolveIters + public :: FERKStepGetNumRhsEvals ! WRAPPER DECLARATIONS interface @@ -183,15 +183,6 @@ function swigc_FERKStepSetTableName(farg1, farg2) & integer(C_INT) :: fresult end function -function swigc_FERKStepGetNumRhsEvals(farg1, farg2) & -bind(C, name="_wrap_FERKStepGetNumRhsEvals") & -result(fresult) -use, intrinsic :: ISO_C_BINDING -type(C_PTR), value :: farg1 -type(C_PTR), value :: farg2 -integer(C_INT) :: fresult -end function - function swigc_FERKStepGetCurrentButcherTable(farg1, farg2) & bind(C, name="_wrap_FERKStepGetCurrentButcherTable") & result(fresult) @@ -985,6 +976,15 @@ function swigc_FERKStepGetNumRelaxSolveIters(farg1, farg2) & integer(C_INT) :: fresult end function +function swigc_FERKStepGetNumRhsEvals(farg1, farg2) & +bind(C, name="_wrap_FERKStepGetNumRhsEvals") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +integer(C_INT) :: fresult +end function + end interface @@ -1101,22 +1101,6 @@ function FERKStepSetTableName(arkode_mem, etable) & swig_result = fresult end function -function FERKStepGetNumRhsEvals(arkode_mem, nfevals) & -result(swig_result) -use, intrinsic :: ISO_C_BINDING -integer(C_INT) :: swig_result -type(C_PTR) :: arkode_mem -integer(C_LONG), dimension(*), target, intent(inout) :: nfevals -integer(C_INT) :: fresult -type(C_PTR) :: farg1 -type(C_PTR) :: farg2 - -farg1 = arkode_mem -farg2 = c_loc(nfevals(1)) -fresult = swigc_FERKStepGetNumRhsEvals(farg1, farg2) -swig_result = fresult -end function - function FERKStepGetCurrentButcherTable(arkode_mem, b) & result(swig_result) use, intrinsic :: ISO_C_BINDING @@ -2562,5 +2546,21 @@ function FERKStepGetNumRelaxSolveIters(arkode_mem, iters) & swig_result = fresult end function +function FERKStepGetNumRhsEvals(arkode_mem, nfevals) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: arkode_mem +integer(C_LONG), dimension(*), target, intent(inout) :: nfevals +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 + +farg1 = arkode_mem +farg2 = c_loc(nfevals(1)) +fresult = swigc_FERKStepGetNumRhsEvals(farg1, farg2) +swig_result = fresult +end function + end module diff --git a/src/arkode/fmod_int64/farkode_mod.c b/src/arkode/fmod_int64/farkode_mod.c index 7b2c3c9811..b092ee9d57 100644 --- a/src/arkode/fmod_int64/farkode_mod.c +++ b/src/arkode/fmod_int64/farkode_mod.c @@ -1193,6 +1193,22 @@ SWIGEXPORT int _wrap_FARKodeComputeState(void *farg1, N_Vector farg2, N_Vector f } +SWIGEXPORT int _wrap_FARKodeGetNumRhsEvals(void *farg1, int const *farg2, long *farg3) { + int fresult ; + void *arg1 = (void *) 0 ; + int arg2 ; + long *arg3 = (long *) 0 ; + int result; + + arg1 = (void *)(farg1); + arg2 = (int)(*farg2); + arg3 = (long *)(farg3); + result = (int)ARKodeGetNumRhsEvals(arg1,arg2,arg3); + fresult = (int)(result); + return fresult; +} + + SWIGEXPORT int _wrap_FARKodeGetNumStepAttempts(void *farg1, long *farg2) { int fresult ; void *arg1 = (void *) 0 ; diff --git a/src/arkode/fmod_int64/farkode_mod.f90 b/src/arkode/fmod_int64/farkode_mod.f90 index e627472572..ffb3eedfac 100644 --- a/src/arkode/fmod_int64/farkode_mod.f90 +++ b/src/arkode/fmod_int64/farkode_mod.f90 @@ -163,6 +163,7 @@ module farkode_mod public :: FARKodeEvolve public :: FARKodeGetDky public :: FARKodeComputeState + public :: FARKodeGetNumRhsEvals public :: FARKodeGetNumStepAttempts public :: FARKodeGetWorkSpace public :: FARKodeGetNumSteps @@ -1019,6 +1020,16 @@ function swigc_FARKodeComputeState(farg1, farg2, farg3) & integer(C_INT) :: fresult end function +function swigc_FARKodeGetNumRhsEvals(farg1, farg2, farg3) & +bind(C, name="_wrap_FARKodeGetNumRhsEvals") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +integer(C_INT), intent(in) :: farg2 +type(C_PTR), value :: farg3 +integer(C_INT) :: fresult +end function + function swigc_FARKodeGetNumStepAttempts(farg1, farg2) & bind(C, name="_wrap_FARKodeGetNumStepAttempts") & result(fresult) @@ -3381,6 +3392,25 @@ function FARKodeComputeState(arkode_mem, zcor, z) & swig_result = fresult end function +function FARKodeGetNumRhsEvals(arkode_mem, partition_index, num_rhs_evals) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: arkode_mem +integer(C_INT), intent(in) :: partition_index +integer(C_LONG), dimension(*), target, intent(inout) :: num_rhs_evals +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +integer(C_INT) :: farg2 +type(C_PTR) :: farg3 + +farg1 = arkode_mem +farg2 = partition_index +farg3 = c_loc(num_rhs_evals(1)) +fresult = swigc_FARKodeGetNumRhsEvals(farg1, farg2, farg3) +swig_result = fresult +end function + function FARKodeGetNumStepAttempts(arkode_mem, step_attempts) & result(swig_result) use, intrinsic :: ISO_C_BINDING diff --git a/src/arkode/fmod_int64/farkode_mristep_mod.c b/src/arkode/fmod_int64/farkode_mristep_mod.c index c2e254fa54..5ddb7d077a 100644 --- a/src/arkode/fmod_int64/farkode_mristep_mod.c +++ b/src/arkode/fmod_int64/farkode_mristep_mod.c @@ -713,22 +713,6 @@ SWIGEXPORT int _wrap_FMRIStepSetPostInnerFn(void *farg1, MRIStepPostInnerFn farg } -SWIGEXPORT int _wrap_FMRIStepGetNumRhsEvals(void *farg1, long *farg2, long *farg3) { - int fresult ; - void *arg1 = (void *) 0 ; - long *arg2 = (long *) 0 ; - long *arg3 = (long *) 0 ; - int result; - - arg1 = (void *)(farg1); - arg2 = (long *)(farg2); - arg3 = (long *)(farg3); - result = (int)MRIStepGetNumRhsEvals(arg1,arg2,arg3); - fresult = (int)(result); - return fresult; -} - - SWIGEXPORT int _wrap_FMRIStepGetCurrentCoupling(void *farg1, void *farg2) { int fresult ; void *arg1 = (void *) 0 ; @@ -2111,4 +2095,20 @@ SWIGEXPORT void _wrap_FMRIStepPrintMem(void *farg1, void *farg2) { } +SWIGEXPORT int _wrap_FMRIStepGetNumRhsEvals(void *farg1, long *farg2, long *farg3) { + int fresult ; + void *arg1 = (void *) 0 ; + long *arg2 = (long *) 0 ; + long *arg3 = (long *) 0 ; + int result; + + arg1 = (void *)(farg1); + arg2 = (long *)(farg2); + arg3 = (long *)(farg3); + result = (int)MRIStepGetNumRhsEvals(arg1,arg2,arg3); + fresult = (int)(result); + return fresult; +} + + diff --git a/src/arkode/fmod_int64/farkode_mristep_mod.f90 b/src/arkode/fmod_int64/farkode_mristep_mod.f90 index 782c3c1df9..be5bb7445a 100644 --- a/src/arkode/fmod_int64/farkode_mristep_mod.f90 +++ b/src/arkode/fmod_int64/farkode_mristep_mod.f90 @@ -129,7 +129,6 @@ module farkode_mristep_mod public :: FMRIStepSetCoupling public :: FMRIStepSetPreInnerFn public :: FMRIStepSetPostInnerFn - public :: FMRIStepGetNumRhsEvals public :: FMRIStepGetCurrentCoupling public :: FMRIStepGetLastInnerStepFlag public :: FMRIStepInnerStepper_Create @@ -226,6 +225,7 @@ module farkode_mristep_mod public :: FMRIStepGetLinReturnFlagName public :: FMRIStepFree public :: FMRIStepPrintMem + public :: FMRIStepGetNumRhsEvals ! WRAPPER DECLARATIONS interface @@ -503,16 +503,6 @@ function swigc_FMRIStepSetPostInnerFn(farg1, farg2) & integer(C_INT) :: fresult end function -function swigc_FMRIStepGetNumRhsEvals(farg1, farg2, farg3) & -bind(C, name="_wrap_FMRIStepGetNumRhsEvals") & -result(fresult) -use, intrinsic :: ISO_C_BINDING -type(C_PTR), value :: farg1 -type(C_PTR), value :: farg2 -type(C_PTR), value :: farg3 -integer(C_INT) :: fresult -end function - function swigc_FMRIStepGetCurrentCoupling(farg1, farg2) & bind(C, name="_wrap_FMRIStepGetCurrentCoupling") & result(fresult) @@ -1402,6 +1392,16 @@ subroutine swigc_FMRIStepPrintMem(farg1, farg2) & type(C_PTR), value :: farg2 end subroutine +function swigc_FMRIStepGetNumRhsEvals(farg1, farg2, farg3) & +bind(C, name="_wrap_FMRIStepGetNumRhsEvals") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +type(C_PTR), value :: farg3 +integer(C_INT) :: fresult +end function + end interface @@ -1883,25 +1883,6 @@ function FMRIStepSetPostInnerFn(arkode_mem, postfn) & swig_result = fresult end function -function FMRIStepGetNumRhsEvals(arkode_mem, nfse_evals, nfsi_evals) & -result(swig_result) -use, intrinsic :: ISO_C_BINDING -integer(C_INT) :: swig_result -type(C_PTR) :: arkode_mem -integer(C_LONG), dimension(*), target, intent(inout) :: nfse_evals -integer(C_LONG), dimension(*), target, intent(inout) :: nfsi_evals -integer(C_INT) :: fresult -type(C_PTR) :: farg1 -type(C_PTR) :: farg2 -type(C_PTR) :: farg3 - -farg1 = arkode_mem -farg2 = c_loc(nfse_evals(1)) -farg3 = c_loc(nfsi_evals(1)) -fresult = swigc_FMRIStepGetNumRhsEvals(farg1, farg2, farg3) -swig_result = fresult -end function - function FMRIStepGetCurrentCoupling(arkode_mem, mric) & result(swig_result) use, intrinsic :: ISO_C_BINDING @@ -3512,5 +3493,24 @@ subroutine FMRIStepPrintMem(arkode_mem, outfile) call swigc_FMRIStepPrintMem(farg1, farg2) end subroutine +function FMRIStepGetNumRhsEvals(arkode_mem, nfse_evals, nfsi_evals) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: arkode_mem +integer(C_LONG), dimension(*), target, intent(inout) :: nfse_evals +integer(C_LONG), dimension(*), target, intent(inout) :: nfsi_evals +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 +type(C_PTR) :: farg3 + +farg1 = arkode_mem +farg2 = c_loc(nfse_evals(1)) +farg3 = c_loc(nfsi_evals(1)) +fresult = swigc_FMRIStepGetNumRhsEvals(farg1, farg2, farg3) +swig_result = fresult +end function + end module diff --git a/src/arkode/fmod_int64/farkode_sprkstep_mod.c b/src/arkode/fmod_int64/farkode_sprkstep_mod.c index 28cfb297d4..f2888129b1 100644 --- a/src/arkode/fmod_int64/farkode_sprkstep_mod.c +++ b/src/arkode/fmod_int64/farkode_sprkstep_mod.c @@ -329,22 +329,6 @@ SWIGEXPORT int _wrap_FSPRKStepGetCurrentMethod(void *farg1, void *farg2) { } -SWIGEXPORT int _wrap_FSPRKStepGetNumRhsEvals(void *farg1, long *farg2, long *farg3) { - int fresult ; - void *arg1 = (void *) 0 ; - long *arg2 = (long *) 0 ; - long *arg3 = (long *) 0 ; - int result; - - arg1 = (void *)(farg1); - arg2 = (long *)(farg2); - arg3 = (long *)(farg3); - result = (int)SPRKStepGetNumRhsEvals(arg1,arg2,arg3); - fresult = (int)(result); - return fresult; -} - - SWIGEXPORT int _wrap_FSPRKStepReset(void *farg1, double const *farg2, N_Vector farg3) { int fresult ; void *arg1 = (void *) 0 ; @@ -764,4 +748,20 @@ SWIGEXPORT void _wrap_FSPRKStepFree(void *farg1) { } +SWIGEXPORT int _wrap_FSPRKStepGetNumRhsEvals(void *farg1, long *farg2, long *farg3) { + int fresult ; + void *arg1 = (void *) 0 ; + long *arg2 = (long *) 0 ; + long *arg3 = (long *) 0 ; + int result; + + arg1 = (void *)(farg1); + arg2 = (long *)(farg2); + arg3 = (long *)(farg3); + result = (int)SPRKStepGetNumRhsEvals(arg1,arg2,arg3); + fresult = (int)(result); + return fresult; +} + + diff --git a/src/arkode/fmod_int64/farkode_sprkstep_mod.f90 b/src/arkode/fmod_int64/farkode_sprkstep_mod.f90 index 82217e7b1b..55f3b8f3f0 100644 --- a/src/arkode/fmod_int64/farkode_sprkstep_mod.f90 +++ b/src/arkode/fmod_int64/farkode_sprkstep_mod.f90 @@ -44,7 +44,6 @@ module farkode_sprkstep_mod end type public :: FSPRKStepSetMethodName public :: FSPRKStepGetCurrentMethod - public :: FSPRKStepGetNumRhsEvals public :: FSPRKStepReset public :: FSPRKStepRootInit public :: FSPRKStepSetRootDirection @@ -74,6 +73,7 @@ module farkode_sprkstep_mod public :: FSPRKStepWriteParameters public :: FSPRKStepGetStepStats public :: FSPRKStepFree + public :: FSPRKStepGetNumRhsEvals ! WRAPPER DECLARATIONS interface @@ -138,16 +138,6 @@ function swigc_FSPRKStepGetCurrentMethod(farg1, farg2) & integer(C_INT) :: fresult end function -function swigc_FSPRKStepGetNumRhsEvals(farg1, farg2, farg3) & -bind(C, name="_wrap_FSPRKStepGetNumRhsEvals") & -result(fresult) -use, intrinsic :: ISO_C_BINDING -type(C_PTR), value :: farg1 -type(C_PTR), value :: farg2 -type(C_PTR), value :: farg3 -integer(C_INT) :: fresult -end function - function swigc_FSPRKStepReset(farg1, farg2, farg3) & bind(C, name="_wrap_FSPRKStepReset") & result(fresult) @@ -421,6 +411,16 @@ subroutine swigc_FSPRKStepFree(farg1) & type(C_PTR), value :: farg1 end subroutine +function swigc_FSPRKStepGetNumRhsEvals(farg1, farg2, farg3) & +bind(C, name="_wrap_FSPRKStepGetNumRhsEvals") & +result(fresult) +use, intrinsic :: ISO_C_BINDING +type(C_PTR), value :: farg1 +type(C_PTR), value :: farg2 +type(C_PTR), value :: farg3 +integer(C_INT) :: fresult +end function + end interface @@ -559,25 +559,6 @@ function FSPRKStepGetCurrentMethod(arkode_mem, sprk_storage) & swig_result = fresult end function -function FSPRKStepGetNumRhsEvals(arkode_mem, nf1, nf2) & -result(swig_result) -use, intrinsic :: ISO_C_BINDING -integer(C_INT) :: swig_result -type(C_PTR) :: arkode_mem -integer(C_LONG), dimension(*), target, intent(inout) :: nf1 -integer(C_LONG), dimension(*), target, intent(inout) :: nf2 -integer(C_INT) :: fresult -type(C_PTR) :: farg1 -type(C_PTR) :: farg2 -type(C_PTR) :: farg3 - -farg1 = arkode_mem -farg2 = c_loc(nf1(1)) -farg3 = c_loc(nf2(1)) -fresult = swigc_FSPRKStepGetNumRhsEvals(farg1, farg2, farg3) -swig_result = fresult -end function - function FSPRKStepReset(arkode_mem, tr, yr) & result(swig_result) use, intrinsic :: ISO_C_BINDING @@ -1077,5 +1058,24 @@ subroutine FSPRKStepFree(arkode_mem) call swigc_FSPRKStepFree(farg1) end subroutine +function FSPRKStepGetNumRhsEvals(arkode_mem, nf1, nf2) & +result(swig_result) +use, intrinsic :: ISO_C_BINDING +integer(C_INT) :: swig_result +type(C_PTR) :: arkode_mem +integer(C_LONG), dimension(*), target, intent(inout) :: nf1 +integer(C_LONG), dimension(*), target, intent(inout) :: nf2 +integer(C_INT) :: fresult +type(C_PTR) :: farg1 +type(C_PTR) :: farg2 +type(C_PTR) :: farg3 + +farg1 = arkode_mem +farg2 = c_loc(nf1(1)) +farg3 = c_loc(nf2(1)) +fresult = swigc_FSPRKStepGetNumRhsEvals(farg1, farg2, farg3) +swig_result = fresult +end function + end module diff --git a/test/answers b/test/answers index c9da3649ff..b8fc1d686f 160000 --- a/test/answers +++ b/test/answers @@ -1 +1 @@ -Subproject commit c9da3649ffcf693b0a6f8c12690e42ef83993bdd +Subproject commit b8fc1d686fabbc1c8e609ff3253cedf9588986ac diff --git a/test/unit_tests/arkode/CXX_parallel/ark_test_heat2D_mri.cpp b/test/unit_tests/arkode/CXX_parallel/ark_test_heat2D_mri.cpp index 00008a1f11..303d85f057 100644 --- a/test/unit_tests/arkode/CXX_parallel/ark_test_heat2D_mri.cpp +++ b/test/unit_tests/arkode/CXX_parallel/ark_test_heat2D_mri.cpp @@ -320,8 +320,10 @@ int main(int argc, char* argv[]) if (check_flag(&flag, "ARKodeEvolve", 1)) { return 1; } flag = ARKodeGetNumSteps(arkstep_mem, &ark_nst); if (check_flag(&flag, "ARKodeGetNumSteps", 1)) { return 1; } - flag = ARKStepGetNumRhsEvals(arkstep_mem, &ark_nfe, &ark_nfi); - if (check_flag(&flag, "ARKStepGetNumRhsEvals", 1)) { return 1; } + flag = ARKodeGetNumRhsEvals(arkstep_mem, 0, &ark_nfe); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return 1; } + flag = ARKodeGetNumRhsEvals(arkstep_mem, 1, &ark_nfi); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return 1; } flag = ARKodeGetNumLinSolvSetups(arkstep_mem, &ark_nsetups); if (check_flag(&flag, "ARKodeGetNumLinSolvSetups", 1)) { return 1; } flag = ARKodeGetNumNonlinSolvIters(arkstep_mem, &ark_nni); @@ -363,8 +365,10 @@ int main(int argc, char* argv[]) if (check_flag(&flag, "ARKodeEvolve", 1)) { return 1; } flag = ARKodeGetNumSteps(mristep_mem, &mri_nst); if (check_flag(&flag, "ARKodeGetNumSteps", 1)) { return 1; } - flag = MRIStepGetNumRhsEvals(mristep_mem, &mri_nfse, &mri_nfsi); - if (check_flag(&flag, "MRIStepGetNumRhsEvals", 1)) { return 1; } + flag = ARKodeGetNumRhsEvals(mristep_mem, 0, &mri_nfse); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return 1; } + flag = ARKodeGetNumRhsEvals(mristep_mem, 1, &mri_nfsi); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return 1; } flag = ARKodeGetNumLinSolvSetups(mristep_mem, &mri_nsetups); if (check_flag(&flag, "ARKodeGetNumLinSolvSetups", 1)) { return 1; } flag = ARKodeGetNumNonlinSolvIters(mristep_mem, &mri_nni); diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_analytic_sys_mri.cpp b/test/unit_tests/arkode/CXX_serial/ark_test_analytic_sys_mri.cpp index a31e3d81e0..c56ac4292d 100644 --- a/test/unit_tests/arkode/CXX_serial/ark_test_analytic_sys_mri.cpp +++ b/test/unit_tests/arkode/CXX_serial/ark_test_analytic_sys_mri.cpp @@ -243,8 +243,10 @@ int main(int argc, char* argv[]) if (check_flag(&flag, "ARKodeGetCurrentTime", 1)) { return 1; } flag = ARKodeGetNumSteps(arkstep_mem, &ark_nst); if (check_flag(&flag, "ARKodeGetNumSteps", 1)) { return 1; } - flag = ARKStepGetNumRhsEvals(arkstep_mem, &ark_nfe, &ark_nfi); - if (check_flag(&flag, "ARKStepGetNumRhsEvals", 1)) { return 1; } + flag = ARKodeGetNumRhsEvals(arkstep_mem, 0, &ark_nfe); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return 1; } + flag = ARKodeGetNumRhsEvals(arkstep_mem, 1, &ark_nfi); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return 1; } flag = ARKodeGetNumNonlinSolvIters(arkstep_mem, &ark_nni); if (check_flag(&flag, "ARKodeGetNumNonlinSolvIters", 1)) { return 1; } flag = ARKodeGetNumNonlinSolvConvFails(arkstep_mem, &ark_ncfn); @@ -284,8 +286,10 @@ int main(int argc, char* argv[]) if (check_flag(&flag, "ARKodeGetCurrentTime", 1)) { return 1; } flag = ARKodeGetNumSteps(mristep_mem, &mri_nst); if (check_flag(&flag, "ARKodeGetNumSteps", 1)) { return 1; } - flag = MRIStepGetNumRhsEvals(mristep_mem, &mri_nfse, &mri_nfsi); - if (check_flag(&flag, "MRIStepGetNumRhsEvals", 1)) { return 1; } + flag = ARKodeGetNumRhsEvals(mristep_mem, 0, &mri_nfse); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return 1; } + flag = ARKodeGetNumRhsEvals(mristep_mem, 1, &mri_nfsi); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return 1; } flag = ARKodeGetNumNonlinSolvIters(mristep_mem, &mri_nni); if (check_flag(&flag, "ARKodeGetNumNonlinSolvIters", 1)) { return 1; } flag = ARKodeGetNumNonlinSolvConvFails(mristep_mem, &mri_ncfn); diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_ark.cpp b/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_ark.cpp index 22d6856800..0a0fe13fe5 100644 --- a/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_ark.cpp +++ b/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_ark.cpp @@ -866,8 +866,11 @@ int check_rhs_evals(rk_type r_type, void* arkstep_mem, long int nfe_expected, if (check_flag(&flag, "ARKodeGetNumSteps", 1)) { return 1; } long int nfe, nfi; - flag = ARKStepGetNumRhsEvals(arkstep_mem, &nfe, &nfi); - if (check_flag(&flag, "ARKStepGetNumRhsEvals", 1)) { return 1; } + flag = ARKodeGetNumRhsEvals(arkstep_mem, 0, &nfe); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return 1; } + + flag = ARKodeGetNumRhsEvals(arkstep_mem, 1, &nfi); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return 1; } if (r_type == rk_type::expl || r_type == rk_type::imex) { diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_erk.cpp b/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_erk.cpp index 2de9d17dca..525da5509f 100644 --- a/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_erk.cpp +++ b/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_erk.cpp @@ -452,8 +452,8 @@ int check_rhs_evals(void* erkstep_mem, long int nfe_expected) if (check_flag(&flag, "ARKodeGetNumSteps", 1)) { return 1; } long int nfe; - flag = ERKStepGetNumRhsEvals(erkstep_mem, &nfe); - if (check_flag(&flag, "ERKStepGetNumRhsEvals", 1)) { return 1; } + flag = ARKodeGetNumRhsEvals(erkstep_mem, 0, &nfe); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return 1; } std::cout << "Fe RHS evals:\n" << " actual: " << nfe << "\n" diff --git a/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_mri.cpp b/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_mri.cpp index 202e1780ef..966d5425fb 100644 --- a/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_mri.cpp +++ b/test/unit_tests/arkode/CXX_serial/ark_test_dahlquist_mri.cpp @@ -402,8 +402,11 @@ int run_tests(MRISTEP_METHOD_TYPE type, ProblemOptions& prob_opts, flag = ARKodeGetNumSteps(mristep_mem, &mri_nst); if (check_flag(&flag, "ARKodeGetNumSteps", 1)) { return 1; } - flag = MRIStepGetNumRhsEvals(mristep_mem, &mri_nfse, &mri_nfsi); - if (check_flag(&flag, "MRIStepGetNumRhsEvals", 1)) { return 1; } + flag = ARKodeGetNumRhsEvals(mristep_mem, 0, &mri_nfse); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return 1; } + + flag = ARKodeGetNumRhsEvals(mristep_mem, 1, &mri_nfsi); + if (check_flag(&flag, "ARKodeGetNumRhsEvals", 1)) { return 1; } if (type == MRISTEP_IMPLICIT || type == MRISTEP_IMEX) { From 2216f53f98aed221c422c074644ab26e3f36a0c9 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Thu, 17 Oct 2024 14:01:56 -0700 Subject: [PATCH 11/89] Update changelog --- CHANGELOG.md | 8 ++++++++ doc/shared/RecentChanges.rst | 14 ++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2aff004841..7a2184439e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,14 @@ ### New Features and Enhancements +The following DIRK schemes now have coefficients accurate to quad precision: +* `ARKODE_BILLINGTON_3_3_2` +* `ARKODE_KVAERNO_4_2_3` +* `ARKODE_CASH_5_2_4` +* `ARKODE_CASH_5_3_4` +* `ARKODE_KVAERNO_5_3_4` +* `ARKODE_KVAERNO_7_4_5` + The default value of `CMAKE_CUDA_ARCHITECTURES` is no longer set to `70` and is now determined automatically by CMake. The previous default was only valid for Volta GPUs while the automatically selected value will vary across compilers and diff --git a/doc/shared/RecentChanges.rst b/doc/shared/RecentChanges.rst index 875d45c9b7..2be479f59c 100644 --- a/doc/shared/RecentChanges.rst +++ b/doc/shared/RecentChanges.rst @@ -2,6 +2,20 @@ **New Features and Enhancements** +The following DIRK schemes now have coefficients accurate to quad precision: + +* ``ARKODE_BILLINGTON_3_3_2`` + +* ``ARKODE_KVAERNO_4_2_3`` + +* ``ARKODE_CASH_5_2_4`` + +* ``ARKODE_CASH_5_3_4`` + +* ``ARKODE_KVAERNO_5_3_4`` + +* ``ARKODE_KVAERNO_7_4_5`` + The default value of :cmakeop:`CMAKE_CUDA_ARCHITECTURES` is no longer set to ``70`` and is now determined automatically by CMake. The previous default was only valid for Volta GPUs while the automatically selected value will vary From 5e7e715e2f7326cd71d81372d3066617f36a56e3 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Thu, 17 Oct 2024 14:05:21 -0700 Subject: [PATCH 12/89] Use trees for order checking --- src/arkode/arkode_butcher.c | 4257 +++-------------------------------- 1 file changed, 360 insertions(+), 3897 deletions(-) diff --git a/src/arkode/arkode_butcher.c b/src/arkode/arkode_butcher.c index 6b9a71cdeb..72f321049f 100644 --- a/src/arkode/arkode_butcher.c +++ b/src/arkode/arkode_butcher.c @@ -21,143 +21,7 @@ #include "arkode_impl.h" -/* tolerance for checking order conditions */ -#define TOL (SUNRsqrt(SUN_UNIT_ROUNDOFF)) - -/* Private utility functions for checking method order */ -static int arkode_butcher_mv(sunrealtype** A, sunrealtype* x, int s, - sunrealtype* b); -static int arkode_butcher_vv(sunrealtype* x, sunrealtype* y, int s, - sunrealtype* z); -static int arkode_butcher_vp(sunrealtype* x, int l, int s, sunrealtype* z); -static int arkode_butcher_dot(sunrealtype* x, sunrealtype* y, int s, - sunrealtype* d); -static sunbooleantype arkode_butcher_rowsum(sunrealtype** A, sunrealtype* c, - int s); -static sunbooleantype arkode_butcher_order1(sunrealtype* b, int s); -static sunbooleantype arkode_butcher_order2(sunrealtype* b, sunrealtype* c, - int s); -static sunbooleantype arkode_butcher_order3a(sunrealtype* b, sunrealtype* c1, - sunrealtype* c2, int s); -static sunbooleantype arkode_butcher_order3b(sunrealtype* b, sunrealtype** A, - sunrealtype* c, int s); -static sunbooleantype arkode_butcher_order4a(sunrealtype* b, sunrealtype* c1, - sunrealtype* c2, sunrealtype* c3, - int s); -static sunbooleantype arkode_butcher_order4b(sunrealtype* b, sunrealtype* c1, - sunrealtype** A, sunrealtype* c2, - int s); -static sunbooleantype arkode_butcher_order4c(sunrealtype* b, sunrealtype** A, - sunrealtype* c1, sunrealtype* c2, - int s); -static sunbooleantype arkode_butcher_order4d(sunrealtype* b, sunrealtype** A1, - sunrealtype** A2, sunrealtype* c, - int s); -static sunbooleantype arkode_butcher_order5a(sunrealtype* b, sunrealtype* c1, - sunrealtype* c2, sunrealtype* c3, - sunrealtype* c4, int s); -static sunbooleantype arkode_butcher_order5b(sunrealtype* b, sunrealtype* c1, - sunrealtype* c2, sunrealtype** A, - sunrealtype* c3, int s); -static sunbooleantype arkode_butcher_order5c(sunrealtype* b, sunrealtype** A1, - sunrealtype* c1, sunrealtype** A2, - sunrealtype* c2, int s); -static sunbooleantype arkode_butcher_order5d(sunrealtype* b, sunrealtype* c1, - sunrealtype** A, sunrealtype* c2, - sunrealtype* c3, int s); -static sunbooleantype arkode_butcher_order5e(sunrealtype* b, sunrealtype** A, - sunrealtype* c1, sunrealtype* c2, - sunrealtype* c3, int s); -static sunbooleantype arkode_butcher_order5f(sunrealtype* b, sunrealtype* c1, - sunrealtype** A1, sunrealtype** A2, - sunrealtype* c2, int s); -static sunbooleantype arkode_butcher_order5g(sunrealtype* b, sunrealtype** A1, - sunrealtype* c1, sunrealtype** A2, - sunrealtype* c2, int s); -static sunbooleantype arkode_butcher_order5h(sunrealtype* b, sunrealtype** A1, - sunrealtype** A2, sunrealtype* c1, - sunrealtype* c2, int s); -static sunbooleantype arkode_butcher_order5i(sunrealtype* b, sunrealtype** A1, - sunrealtype** A2, sunrealtype** A3, - sunrealtype* c, int s); -static sunbooleantype arkode_butcher_order6a(sunrealtype* b, sunrealtype* c1, - sunrealtype* c2, sunrealtype* c3, - sunrealtype* c4, sunrealtype* c5, - int s); -static sunbooleantype arkode_butcher_order6b(sunrealtype* b, sunrealtype* c1, - sunrealtype* c2, sunrealtype* c3, - sunrealtype** A, sunrealtype* c4, - int s); -static sunbooleantype arkode_butcher_order6c(sunrealtype* b, sunrealtype* c1, - sunrealtype** A1, sunrealtype* c2, - sunrealtype** A2, sunrealtype* c3, - int s); -static sunbooleantype arkode_butcher_order6d(sunrealtype* b, sunrealtype* c1, - sunrealtype* c2, sunrealtype** A, - sunrealtype* c3, sunrealtype* c4, - int s); -static sunbooleantype arkode_butcher_order6e(sunrealtype* b, sunrealtype* c1, - sunrealtype* c2, sunrealtype** A1, - sunrealtype** A2, sunrealtype* c3, - int s); -static sunbooleantype arkode_butcher_order6f(sunrealtype* b, sunrealtype** A1, - sunrealtype** A2, sunrealtype* c1, - sunrealtype** A3, sunrealtype* c2, - int s); -static sunbooleantype arkode_butcher_order6g(sunrealtype* b, sunrealtype* c1, - sunrealtype** A, sunrealtype* c2, - sunrealtype* c3, sunrealtype* c4, - int s); -static sunbooleantype arkode_butcher_order6h(sunrealtype* b, sunrealtype* c1, - sunrealtype** A1, sunrealtype* c2, - sunrealtype** A2, sunrealtype* c3, - int s); -static sunbooleantype arkode_butcher_order6i(sunrealtype* b, sunrealtype* c1, - sunrealtype** A1, sunrealtype** A2, - sunrealtype* c2, sunrealtype* c3, - int s); -static sunbooleantype arkode_butcher_order6j(sunrealtype* b, sunrealtype* c1, - sunrealtype** A1, sunrealtype** A2, - sunrealtype** A3, sunrealtype* c2, - int s); -static sunbooleantype arkode_butcher_order6k(sunrealtype* b, sunrealtype** A, - sunrealtype* c1, sunrealtype* c2, - sunrealtype* c3, sunrealtype* c4, - int s); -static sunbooleantype arkode_butcher_order6l(sunrealtype* b, sunrealtype** A1, - sunrealtype* c1, sunrealtype* c2, - sunrealtype** A2, sunrealtype* c3, - int s); -static sunbooleantype arkode_butcher_order6m(sunrealtype* b, sunrealtype** A1, - sunrealtype** A2, sunrealtype* c1, - sunrealtype** A3, sunrealtype* c2, - int s); -static sunbooleantype arkode_butcher_order6n(sunrealtype* b, sunrealtype** A1, - sunrealtype* c1, sunrealtype** A2, - sunrealtype* c2, sunrealtype* c3, - int s); -static sunbooleantype arkode_butcher_order6o(sunrealtype* b, sunrealtype** A1, - sunrealtype* c1, sunrealtype** A2, - sunrealtype** A3, sunrealtype* c2, - int s); -static sunbooleantype arkode_butcher_order6p(sunrealtype* b, sunrealtype** A1, - sunrealtype** A2, sunrealtype* c1, - sunrealtype* c2, sunrealtype* c3, - int s); -static sunbooleantype arkode_butcher_order6q(sunrealtype* b, sunrealtype** A1, - sunrealtype** A2, sunrealtype* c1, - sunrealtype** A3, sunrealtype* c2, - int s); -static sunbooleantype arkode_butcher_order6r(sunrealtype* b, sunrealtype** A1, - sunrealtype** A2, sunrealtype** A3, - sunrealtype* c1, sunrealtype* c2, - int s); -static sunbooleantype arkode_butcher_order6s(sunrealtype* b, sunrealtype** A1, - sunrealtype** A2, sunrealtype** A3, - sunrealtype** A4, sunrealtype* c, - int s); -static int __ButcherSimplifyingAssumptions(sunrealtype** A, sunrealtype* b, - sunrealtype* c, int s); +#define ORDER_CONDITION_TOL (100 * SUN_UNIT_ROUNDOFF) /*--------------------------------------------------------------- Routine to allocate an empty Butcher table structure @@ -369,6 +233,22 @@ void ARKodeButcherTable_Free(ARKodeButcherTable B) } } +static sunbooleantype is_valid_table(const ARKodeButcherTable table) +{ + if (table == NULL || table->stages < 1 || table->A == NULL || + table->b == NULL || table->c == NULL) + { + return SUNFALSE; + } + + for (int i = 0; i < table->stages; i++) + { + if (table->A[i] == NULL) { return SUNFALSE; } + } + + return SUNTRUE; +} + /*--------------------------------------------------------------- Routine to print a Butcher table structure ---------------------------------------------------------------*/ @@ -376,15 +256,7 @@ void ARKodeButcherTable_Write(ARKodeButcherTable B, FILE* outfile) { int i, j; - /* check for valid table */ - if (B == NULL) { return; } - if (B->A == NULL) { return; } - for (i = 0; i < B->stages; i++) - { - if (B->A[i] == NULL) { return; } - } - if (B->c == NULL) { return; } - if (B->b == NULL) { return; } + if (!is_valid_table(B)) { return; } fprintf(outfile, " A = \n"); for (i = 0; i < B->stages; i++) @@ -429,669 +301,406 @@ sunbooleantype ARKodeButcherTable_IsStifflyAccurate(ARKodeButcherTable B) return SUNTRUE; } -/*--------------------------------------------------------------- - Routine to determine the analytical order of accuracy for a - specified Butcher table. We check the analytical [necessary] - order conditions up through order 6. After that, we revert to - the [sufficient] Butcher simplifying assumptions. - - Inputs: - B: Butcher table to check - outfile: file pointer to print results; if NULL then no - outputs are printed +/* Grafts a branch onto a base tree while maintaining a lexicographic ordering + * of the children */ +static void butcher_product(const int* const base, const int branch, + int* const tree) +{ + const int base_children = base[0]; + tree[0] = base_children + 1; + int i; + for (i = 1; i <= base_children && base[i] < branch; i++) + { + tree[i] = base[i]; + } - Outputs: - q: measured order of accuracy for method - p: measured order of accuracy for embedding [0 if not present] + tree[i] = branch; - Return values: - 0 (success): internal {q,p} values match analytical order - 1 (warning): internal {q,p} values are lower than analytical - order, or method achieves maximum order possible with this - routine and internal {q,p} are higher. - -1 (failure): internal p and q values are higher than analytical - order - -2 (failure): NULL-valued B (or critical contents) + for (; i <= base_children; i++) { tree[i + 1] = base[i]; } +} - Note: for embedded methods, if the return flags for p and q would - differ, failure takes precedence over warning, which takes - precedence over success. - ---------------------------------------------------------------*/ -int ARKodeButcherTable_CheckOrder(ARKodeButcherTable B, int* q, int* p, - FILE* outfile) +/* Returns true if the trees are equal and false otherwise */ +static sunbooleantype tree_equal(const int* const tree1, const int* const tree2) { - /* local variables */ - int q_SA, p_SA, i, s; - sunrealtype **A, *b, *c, *d; - sunbooleantype alltrue; - (*q) = (*p) = 0; + const int children1 = tree1[0]; + const int children2 = tree2[0]; - /* verify non-NULL Butcher table structure and contents */ - if (B == NULL) { return (-2); } - if (B->stages < 1) { return (-2); } - if (B->A == NULL) { return (-2); } - for (i = 0; i < B->stages; i++) - { - if (B->A[i] == NULL) { return (-2); } - } - if (B->c == NULL) { return (-2); } - if (B->b == NULL) { return (-2); } + return children1 == children2 && + memcmp(&tree1[1], &tree2[1], children1 * sizeof(*tree1)) == 0; +} - /* set shortcuts for Butcher table components */ - A = B->A; - b = B->b; - c = B->c; - d = B->d; - s = B->stages; +typedef struct +{ + int* list; /* A flattened array of all trees generated so far */ + int* current; /* A memory buffer for constructing the next tree */ + int* order_offset; /* The indices into list at which each order starts */ + int length; /* The number of ints used in list */ + int capacity; /* The number of ints list can store */ + int order; /* The current order */ + int root_order; /* The current order of tree to use as a root */ + int root_offset; /* The index offset for the current root tree for the root_order */ + int branch_offset; /* The index offset for the current branch tree to graft on the root */ +} tree_generator; - /* check method order */ - if (outfile) { fprintf(outfile, "ARKodeButcherTable_CheckOrder:\n"); } +static tree_generator tree_generator_create() +{ + return (tree_generator){.list = NULL, + .current = NULL, + .order_offset = NULL, + .length = 0, + .capacity = 0, + .order = 0, + .root_order = 0, + .root_offset = 0, + .branch_offset = 0}; +} - /* row sum condition */ - if (arkode_butcher_rowsum(A, c, s)) { (*q) = 0; } - else +static void tree_generator_free(tree_generator* const gen) +{ + free(gen->list); + free(gen->current); + free(gen->order_offset); +} + +static int tree_generator_push(tree_generator* const gen) +{ + for (int offset = gen->order_offset[gen->order - 1]; offset < gen->length; + offset += gen->list[offset] + 1) { - (*q) = -1; - if (outfile) { fprintf(outfile, " method fails row sum condition\n"); } + /* Check if current tree has already been generated */ + if (tree_equal(gen->current, &gen->list[offset])) { return ARK_WARNING; } } - /* order 1 condition */ - if ((*q) == 0) + + const int tree_length = gen->current[0] + 1; + const int new_length = gen->length + tree_length; + if (new_length > gen->capacity) { - if (arkode_butcher_order1(b, s)) { (*q) = 1; } - else - { - if (outfile) { fprintf(outfile, " method fails order 1 condition\n"); } - } + gen->capacity = 2 * new_length; + gen->list = realloc(gen->list, gen->capacity * sizeof(*gen->list)); + if (gen->list == NULL) { return ARK_MEM_FAIL; } } - /* order 2 condition */ - if ((*q) == 1) + + memcpy(&gen->list[gen->length], gen->current, tree_length * sizeof(*gen->list)); + gen->length = new_length; + return ARK_SUCCESS; +} + +static void tree_print(const int* const tree, const tree_generator* const gen, + FILE* const outfile) +{ + const int children = tree[0]; + if (children == 0) { fprintf(outfile, "t"); } + else { - if (arkode_butcher_order2(b, c, s)) { (*q) = 2; } - else + fprintf(outfile, "["); + for (int i = 1; i <= children; i++) { - if (outfile) { fprintf(outfile, " method fails order 2 condition\n"); } + tree_print(&gen->list[tree[i]], gen, outfile); } + fprintf(outfile, "]"); } - /* order 3 conditions */ - if ((*q) == 2) +} + +static int generate_tree(tree_generator* const gen) +{ + /* Loop over orders */ + for (;;) { - alltrue = SUNTRUE; - if (!arkode_butcher_order3a(b, c, c, s)) + /* Loop over order of root tree */ + for (; gen->root_order < gen->order; gen->root_order++) { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 3 condition A\n"); } + const int root_min = gen->order_offset[gen->root_order - 1]; + const int root_max = gen->order_offset[gen->root_order]; + + /* Loop over trees of current root order */ + for (;;) + { + const int root = root_min + gen->root_offset; + if (root == root_max) { break; } + + const int branch_order = gen->order - gen->root_order; + const int branch_min = gen->order_offset[branch_order - 1]; + const int branch_max = gen->order_offset[branch_order]; + + /* Loop over branches to graft to the root */ + for (;;) + { + const int branch = branch_min + gen->branch_offset; + if (branch == branch_max) { break; } + + butcher_product(&gen->list[root], branch, gen->current); + gen->branch_offset += gen->list[branch] + 1; + + const int retval = tree_generator_push(gen); + if (retval <= ARK_SUCCESS) { return retval; } + } + + gen->root_offset += gen->list[root] + 1; + gen->branch_offset = 0; + } + + gen->root_offset = 0; } - if (!arkode_butcher_order3b(b, A, c, s)) + + gen->root_order = 1; + gen->order++; + gen->current = realloc(gen->current, gen->order * sizeof(*gen->current)); + if (gen->current == NULL) { return ARK_MEM_FAIL; } + gen->order_offset = realloc(gen->order_offset, + gen->order * sizeof(*gen->order_offset)); + if (gen->order_offset == NULL) { return ARK_MEM_FAIL; } + gen->order_offset[gen->order - 1] = gen->length; + + if (gen->order == 1) { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 3 condition B\n"); } + gen->current[0] = 0; + return tree_generator_push(gen); } - if (alltrue) { (*q) = 3; } } - /* order 4 conditions */ - if ((*q) == 3) +} + +typedef struct +{ + sunrealtype* Phi; + sunrealtype phi; + sunrealtype phi_hat; + int gamma; + int sigma; + int order; +} tree_props; + +static void vec_set(sunrealtype* const vec, const sunrealtype value, + const int stages) +{ + for (int i = 0; i < stages; i++) { vec[i] = value; } +} + +static void vec_times(sunrealtype* const vec1, const sunrealtype* const vec2, + int stages) +{ + for (int i = 0; i < stages; i++) { vec1[i] *= vec2[i]; } +} + +static sunrealtype dot_prod(const sunrealtype* const vec1, + const sunrealtype* const vec2, const int stages) +{ + sunrealtype total = ZERO; + for (int i = 0; i < stages; i++) { total += vec1[i] * vec2[i]; } + return total; +} + +static sunrealtype* mat_vec(sunrealtype* const* const mat, + const sunrealtype* const vec, + sunrealtype* const prod, const int stages) +{ + for (int i = 0; i < stages; i++) { prod[i] = dot_prod(mat[i], vec, stages); } + return prod; +} + +static sunbooleantype rowsum(const ARKodeButcherTable table) +{ + for (int i = 0; i < table->stages; i++) { - alltrue = SUNTRUE; - if (!arkode_butcher_order4a(b, c, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 4 condition A\n"); } - } - if (!arkode_butcher_order4b(b, c, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 4 condition B\n"); } - } - if (!arkode_butcher_order4c(b, A, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 4 condition C\n"); } - } - if (!arkode_butcher_order4d(b, A, A, c, s)) + sunrealtype rsum = SUN_RCONST(0.0); + for (int j = 0; j < table->stages; j++) { rsum += table->A[i][j]; } + if (SUNRabs(rsum - table->c[i]) > ORDER_CONDITION_TOL) { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 4 condition D\n"); } + printf("ROWSUM ERR: %" RSYM "\n", SUNRabs(rsum - table->c[i])); + return SUNFALSE; } - if (alltrue) { (*q) = 4; } } - /* order 5 conditions */ - if ((*q) == 4) + return SUNTRUE; +} + +static tree_props get_tree_props(const int* const tree, + const tree_generator* const gen, int color, + const ARKodeButcherTable* const tables, + sunrealtype* const buf, sunbooleantype root) +{ + tree_props props = {.gamma = 1, .sigma = 1, .order = 1}; + const ARKodeButcherTable table = tables[color & 1]; + const int children = tree[0]; + + if (children == 0 && !root) { - alltrue = SUNTRUE; - if (!arkode_butcher_order5a(b, c, c, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 5 condition A\n"); } - } - if (!arkode_butcher_order5b(b, c, c, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 5 condition B\n"); } - } - if (!arkode_butcher_order5c(b, A, c, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 5 condition C\n"); } - } - if (!arkode_butcher_order5d(b, c, A, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 5 condition D\n"); } - } - if (!arkode_butcher_order5e(b, A, c, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 5 condition E\n"); } - } - if (!arkode_butcher_order5f(b, c, A, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 5 condition F\n"); } - } - if (!arkode_butcher_order5g(b, A, c, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 5 condition G\n"); } - } - if (!arkode_butcher_order5h(b, A, A, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 5 condition H\n"); } - } - if (!arkode_butcher_order5i(b, A, A, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 5 condition I\n"); } - } - if (alltrue) { (*q) = 5; } + props.Phi = table->c; + return props; } - /* order 6 conditions */ - if ((*q) == 5) + + const int s = table->stages; + props.Phi = buf; + vec_set(props.Phi, ONE, s); + + int prev_color = -1; + int num_duplicate = 1; + for (int i = 1; i <= children; i++) { - alltrue = SUNTRUE; - if (!arkode_butcher_order6a(b, c, c, c, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 6 condition A\n"); } - } - if (!arkode_butcher_order6b(b, c, c, c, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 6 condition B\n"); } - } - if (!arkode_butcher_order6c(b, c, A, c, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 6 condition C\n"); } - } - if (!arkode_butcher_order6d(b, c, c, A, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 6 condition D\n"); } - } - if (!arkode_butcher_order6e(b, c, c, A, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 6 condition E\n"); } - } - if (!arkode_butcher_order6f(b, A, A, c, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 6 condition F\n"); } - } - if (!arkode_butcher_order6g(b, c, A, c, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 6 condition G\n"); } - } - if (!arkode_butcher_order6h(b, c, A, c, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 6 condition H\n"); } - } - if (!arkode_butcher_order6i(b, c, A, A, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 6 condition I\n"); } - } - if (!arkode_butcher_order6j(b, c, A, A, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 6 condition J\n"); } - } - if (!arkode_butcher_order6k(b, A, c, c, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 6 condition K\n"); } - } - if (!arkode_butcher_order6l(b, A, c, c, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 6 condition L\n"); } - } - if (!arkode_butcher_order6m(b, A, A, c, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 6 condition M\n"); } - } - if (!arkode_butcher_order6n(b, A, c, A, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 6 condition N\n"); } - } - if (!arkode_butcher_order6o(b, A, c, A, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 6 condition O\n"); } - } - if (!arkode_butcher_order6p(b, A, A, c, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 6 condition P\n"); } - } - if (!arkode_butcher_order6q(b, A, A, c, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 6 condition Q\n"); } - } - if (!arkode_butcher_order6r(b, A, A, A, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 6 condition R\n"); } - } - if (!arkode_butcher_order6s(b, A, A, A, A, c, s)) + const int* const child = &gen->list[tree[i]]; + const int child_color = color >> props.order; + sunrealtype* const child_buf = &buf[props.order * s]; + const tree_props child_props = get_tree_props(child, gen, child_color, + tables, child_buf, SUNFALSE); + props.gamma *= child_props.gamma; + props.sigma *= child_props.sigma; + const int masked_child_color = child_color & ((1 << child_props.order) - 1); + // This check relies on trees being in lexicographic order so duplicate subtrees are consecutive + if (prev_color == masked_child_color && tree[i] == tree[i - 1]) { - alltrue = SUNFALSE; - if (outfile) { fprintf(outfile, " method fails order 6 condition S\n"); } + num_duplicate++; + props.sigma *= num_duplicate; } - if (alltrue) { (*q) = 6; } + else { num_duplicate = 1; } + props.order += child_props.order; + prev_color = masked_child_color; + vec_times(props.Phi, child_props.Phi, s); } - /* higher order conditions (via simplifying assumptions) */ - if ((*q) == 6) + + props.gamma *= props.order; + + if (root) { - if (outfile) - { - fprintf(outfile, - " method order >= 6; reverting to simplifying assumptions\n"); - } - q_SA = __ButcherSimplifyingAssumptions(A, b, c, s); - (*q) = SUNMAX((*q), q_SA); - if (outfile) { fprintf(outfile, " method order = %i\n", (*q)); } + props.phi = dot_prod(table->b, props.Phi, s); + if (table->d != NULL) { props.phi_hat = dot_prod(table->d, props.Phi, s); } } + else { props.Phi = mat_vec(table->A, props.Phi, &buf[s], s); } + return props; +} + +static int compare_orders(const int given, const int computed, const int retval) +{ + if (given > computed || retval == 1) { return 1; } + else if (given < computed || retval == -1) { return -1; } + else { return 0; } +} + +static int check_order(const ARKodeButcherTable* const tables, + const sunbooleantype ark, int* const q, int* const p, + FILE* const outfile) +{ + tree_generator gen = tree_generator_create(); + sunrealtype* buf = NULL; + int retval = ARK_SUCCESS; - /* check embedding order */ - if (d) + while (SUNMIN(*p, *q) < 0) { - if (outfile) { fprintf(outfile, "\n"); } - b = d; + retval = generate_tree(&gen); + if (retval != ARK_SUCCESS) { break; } - /* row sum condition */ - if (arkode_butcher_rowsum(A, c, s)) { (*p) = 0; } - else - { - (*p) = -1; - if (outfile) - { - fprintf(outfile, " embedding fails row sum condition\n"); - } - } - /* order 1 condition */ - if ((*p) == 0) - { - if (arkode_butcher_order1(b, s)) { (*p) = 1; } - else - { - if (outfile) - { - fprintf(outfile, " embedding fails order 1 condition\n"); - } - } - } - /* order 2 condition */ - if ((*p) == 1) - { - if (arkode_butcher_order2(b, c, s)) { (*p) = 2; } - else - { - if (outfile) - { - fprintf(outfile, " embedding fails order 2 condition\n"); - } - } - } - /* order 3 conditions */ - if ((*p) == 2) - { - alltrue = SUNTRUE; - if (!arkode_butcher_order3a(b, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 3 condition A\n"); - } - } - if (!arkode_butcher_order3b(b, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 3 condition B\n"); - } - } - if (alltrue) { (*p) = 3; } - } - /* order 4 conditions */ - if ((*p) == 3) + buf = realloc(buf, tables[0]->stages * gen.order * sizeof(*buf)); + if (buf == NULL) { - alltrue = SUNTRUE; - if (!arkode_butcher_order4a(b, c, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 4 condition A\n"); - } - } - if (!arkode_butcher_order4b(b, c, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 4 condition B\n"); - } - } - if (!arkode_butcher_order4c(b, A, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 4 condition C\n"); - } - } - if (!arkode_butcher_order4d(b, A, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 4 condition D\n"); - } - } - if (alltrue) { (*p) = 4; } + retval = ARK_MEM_FAIL; + break; } - /* order 5 conditions */ - if ((*p) == 4) + + const int max_color = ark ? (1 << gen.order) : 1; + for (int color = 0; color < max_color; color++) { - alltrue = SUNTRUE; - if (!arkode_butcher_order5a(b, c, c, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 5 condition A\n"); - } - } - if (!arkode_butcher_order5b(b, c, c, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 5 condition B\n"); - } - } - if (!arkode_butcher_order5c(b, A, c, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 5 condition C\n"); - } - } - if (!arkode_butcher_order5d(b, c, A, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 5 condition D\n"); - } - } - if (!arkode_butcher_order5e(b, A, c, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 5 condition E\n"); - } - } - if (!arkode_butcher_order5f(b, c, A, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 5 condition F\n"); - } - } - if (!arkode_butcher_order5g(b, A, c, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 5 condition G\n"); - } - } - if (!arkode_butcher_order5h(b, A, A, c, c, s)) + const tree_props props = get_tree_props(gen.current, &gen, color, tables, + buf, SUNTRUE); + + if (*q < 0) { - alltrue = SUNFALSE; - if (outfile) + const sunrealtype residual = SUNRabs(props.phi - ONE / props.gamma) / + props.sigma; + if (residual > ORDER_CONDITION_TOL) { - fprintf(outfile, " embedding fails order 5 condition H\n"); + *q = props.order - 1; + if (outfile != NULL) + { + fprintf(outfile, " method fails order %d condition for tree ", + props.order); + tree_print(gen.current, &gen, outfile); + fprintf(outfile, " with residual %" RSYM "\n", residual); + } } } - if (!arkode_butcher_order5i(b, A, A, A, c, s)) + + if (*p < 0) { - alltrue = SUNFALSE; - if (outfile) + const sunrealtype embedded_residual = + SUNRabs(props.phi_hat - ONE / props.gamma) / props.sigma; + if (embedded_residual > ORDER_CONDITION_TOL) { - fprintf(outfile, " embedding fails order 5 condition I\n"); + *p = props.order - 1; + if (outfile != NULL) + { + fprintf(outfile, " embedding fails order %d condition for tree ", + props.order); + tree_print(gen.current, &gen, outfile); + fprintf(outfile, " with residual %" RSYM "\n", embedded_residual); + } } } - if (alltrue) { (*p) = 5; } - } - /* order 6 conditions */ - if ((*p) == 5) - { - alltrue = SUNTRUE; - if (!arkode_butcher_order6a(b, c, c, c, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 6 condition A\n"); - } - } - if (!arkode_butcher_order6b(b, c, c, c, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 6 condition B\n"); - } - } - if (!arkode_butcher_order6c(b, c, A, c, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 6 condition C\n"); - } - } - if (!arkode_butcher_order6d(b, c, c, A, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 6 condition D\n"); - } - } - if (!arkode_butcher_order6e(b, c, c, A, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 6 condition E\n"); - } - } - if (!arkode_butcher_order6f(b, A, A, c, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 6 condition F\n"); - } - } - if (!arkode_butcher_order6g(b, c, A, c, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 6 condition G\n"); - } - } - if (!arkode_butcher_order6h(b, c, A, c, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 6 condition H\n"); - } - } - if (!arkode_butcher_order6i(b, c, A, A, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 6 condition I\n"); - } - } - if (!arkode_butcher_order6j(b, c, A, A, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 6 condition J\n"); - } - } - if (!arkode_butcher_order6k(b, A, c, c, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 6 condition K\n"); - } - } - if (!arkode_butcher_order6l(b, A, c, c, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 6 condition L\n"); - } - } - if (!arkode_butcher_order6m(b, A, A, c, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 6 condition M\n"); - } - } - if (!arkode_butcher_order6n(b, A, c, A, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 6 condition N\n"); - } - } - if (!arkode_butcher_order6o(b, A, c, A, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 6 condition O\n"); - } - } - if (!arkode_butcher_order6p(b, A, A, c, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 6 condition P\n"); - } - } - if (!arkode_butcher_order6q(b, A, A, c, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 6 condition Q\n"); - } - } - if (!arkode_butcher_order6r(b, A, A, A, c, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 6 condition R\n"); - } - } - if (!arkode_butcher_order6s(b, A, A, A, A, c, s)) - { - alltrue = SUNFALSE; - if (outfile) - { - fprintf(outfile, " embedding fails order 6 condition S\n"); - } - } - if (alltrue) { (*p) = 6; } - } - /* higher order conditions (via simplifying assumptions) */ - if ((*p) == 6) - { - if (outfile) - { - fprintf(outfile, " embedding order >= 6; reverting to simplifying " - "assumptions\n"); - } - p_SA = __ButcherSimplifyingAssumptions(A, b, c, s); - (*p) = SUNMAX((*p), p_SA); - if (outfile) { fprintf(outfile, " embedding order = %i\n", (*p)); } } } - /* compare results against stored values and return */ + tree_generator_free(&gen); + free(buf); + return retval; +} - /* check failure modes first */ - if (((*q) < B->q) && ((*q) < 6)) { return (-1); } - if (d) +static int check_tables(const ARKodeButcherTable* const tables, + const sunbooleantype ark, int* const q, int* const p, + FILE* const outfile) +{ + if (!is_valid_table(tables[0]) || (ark && !is_valid_table(tables[1]))) { - if (((*p) < B->p) && ((*p) < 6)) { return (-1); } + return -2; } - /* check warning modes */ - if ((*q) > B->q) { return (1); } - if (d) + if (outfile) { fprintf(outfile, "Order Conditions Check:\n"); } + + *q = *p = -1; + if (rowsum(tables[0]) && (!ark || rowsum(tables[1]))) { - if ((*p) > B->p) { return (1); } + const int retval = check_order(tables, ark, q, p, outfile); + if (retval != ARK_SUCCESS) { return -2; } } - if (((*q) < B->q) && ((*q) >= 6)) { return (1); } - if (d) + else if (outfile) { fprintf(outfile, " method fails row sum condition\n"); } + + int retval = 0; + for (int i = 0; i < (ark ? 2 : 1); i++) { - if (((*p) < B->p) && ((*p) >= 6)) { return (1); } + retval = compare_orders(tables[i]->q, *q, retval); + retval = compare_orders(tables[i]->p, *p, retval); } - /* return success */ - return (0); + return retval; +} + +/*--------------------------------------------------------------- + Routine to determine the analytical order of accuracy for a + specified Butcher table. We check the analytical [necessary] + order conditions up through order 6. After that, we revert to + the [sufficient] Butcher simplifying assumptions. + + Inputs: + B: Butcher table to check + outfile: file pointer to print results; if NULL then no + outputs are printed + + Outputs: + q: measured order of accuracy for method + p: measured order of accuracy for embedding [0 if not present] + + Return values: + 0 (success): internal {q,p} values match analytical order + 1 (warning): internal {q,p} values are lower than analytical + order, or method achieves maximum order possible with this + routine and internal {q,p} are higher. + -1 (failure): internal p and q values are higher than analytical + order + -2 (failure): NULL-valued B (or critical contents) + + Note: for embedded methods, if the return flags for p and q would + differ, failure takes precedence over warning, which takes + precedence over success. + ---------------------------------------------------------------*/ +int ARKodeButcherTable_CheckOrder(ARKodeButcherTable B, int* q, int* p, + FILE* outfile) +{ + return check_tables(&B, SUNFALSE, q, p, outfile); } /*--------------------------------------------------------------- @@ -1121,3152 +730,6 @@ int ARKodeButcherTable_CheckOrder(ARKodeButcherTable B, int* q, int* p, int ARKodeButcherTable_CheckARKOrder(ARKodeButcherTable B1, ARKodeButcherTable B2, int* q, int* p, FILE* outfile) { - /* local variables */ - int i, j, k, l, m, n, s; - sunbooleantype alltrue; - sunrealtype **A[2], *b[2], *c[2], *d[2]; - (*q) = (*p) = 0; - - /* verify non-NULL Butcher table structure and contents */ - if (B1 == NULL) { return (-1); } - if (B1->stages < 1) { return (-1); } - if (B1->A == NULL) { return (-1); } - for (i = 0; i < B1->stages; i++) - { - if (B1->A[i] == NULL) { return (-1); } - } - if (B1->c == NULL) { return (-1); } - if (B1->b == NULL) { return (-1); } - if (B2 == NULL) { return (-1); } - if (B2->stages < 1) { return (-1); } - if (B2->A == NULL) { return (-1); } - for (i = 0; i < B2->stages; i++) - { - if (B2->A[i] == NULL) { return (-1); } - } - if (B2->c == NULL) { return (-1); } - if (B2->b == NULL) { return (-1); } - if (B1->stages != B2->stages) { return (-1); } - - /* set shortcuts for Butcher table components */ - A[0] = B1->A; - b[0] = B1->b; - c[0] = B1->c; - d[0] = B1->d; - A[1] = B2->A; - b[1] = B2->b; - c[1] = B2->c; - d[1] = B1->d; - s = B1->stages; - - /* check method order */ - if (outfile) { fprintf(outfile, "ARKodeButcherTable_CheckARKOrder:\n"); } - - /* row sum conditions */ - if (arkode_butcher_rowsum(A[0], c[0], s) && arkode_butcher_rowsum(A[1], c[1], s)) - { - (*q) = 0; - } - else - { - (*q) = -1; - if (outfile) { fprintf(outfile, " method fails row sum conditions\n"); } - } - /* order 1 conditions */ - if ((*q) == 0) - { - if (arkode_butcher_order1(b[0], s) && arkode_butcher_order1(b[1], s)) - { - (*q) = 1; - } - else - { - if (outfile) { fprintf(outfile, " method fails order 1 conditions\n"); } - } - } - /* order 2 conditions */ - if ((*q) == 1) - { - alltrue = SUNTRUE; - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - alltrue = (alltrue && arkode_butcher_order2(b[i], c[j], s)); - } - } - if (alltrue) { (*q) = 2; } - else - { - if (outfile) { fprintf(outfile, " method fails order 2 conditions\n"); } - } - } - /* order 3 conditions */ - if ((*q) == 2) - { - alltrue = SUNTRUE; - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - alltrue = (alltrue && arkode_butcher_order3a(b[i], c[j], c[k], s)); - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 3 conditions A\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - alltrue = (alltrue && arkode_butcher_order3b(b[i], A[j], c[k], s)); - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 3 conditions B\n"); - } - if (alltrue) { (*q) = 3; } - } - /* order 4 conditions */ - if ((*q) == 3) - { - alltrue = SUNTRUE; - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - alltrue = (alltrue && - arkode_butcher_order4a(b[i], c[j], c[k], c[l], s)); - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 4 conditions A\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - alltrue = (alltrue && - arkode_butcher_order4b(b[i], c[j], A[k], c[l], s)); - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 4 conditions B\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - alltrue = (alltrue && - arkode_butcher_order4c(b[i], A[j], c[k], c[l], s)); - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 4 conditions C\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - alltrue = (alltrue && - arkode_butcher_order4d(b[i], A[j], A[k], c[l], s)); - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 4 conditions D\n"); - } - if (alltrue) { (*q) = 4; } - } - /* order 5 conditions */ - if ((*q) == 4) - { - alltrue = SUNTRUE; - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - alltrue = (alltrue && arkode_butcher_order5a(b[i], c[j], c[k], - c[l], c[m], s)); - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 5 conditions A\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - alltrue = (alltrue && arkode_butcher_order5b(b[i], c[j], c[k], - A[l], c[m], s)); - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 5 conditions B\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - alltrue = (alltrue && arkode_butcher_order5c(b[i], A[j], c[k], - A[l], c[m], s)); - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 5 conditions C\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - alltrue = (alltrue && arkode_butcher_order5d(b[i], c[j], A[k], - c[l], c[m], s)); - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 5 conditions D\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - alltrue = (alltrue && arkode_butcher_order5e(b[i], A[j], c[k], - c[l], c[m], s)); - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 5 conditions E\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - alltrue = (alltrue && arkode_butcher_order5f(b[i], c[j], A[k], - A[l], c[m], s)); - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 5 conditions F\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - alltrue = (alltrue && arkode_butcher_order5g(b[i], A[j], c[k], - A[l], c[m], s)); - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 5 conditions G\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - alltrue = (alltrue && arkode_butcher_order5h(b[i], A[j], A[k], - c[l], c[m], s)); - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 5 conditions H\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - alltrue = (alltrue && arkode_butcher_order5i(b[i], A[j], A[k], - A[l], c[m], s)); - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 5 conditions I\n"); - } - if (alltrue) { (*q) = 5; } - } - /* order 6 conditions */ - if ((*q) == 5) - { - alltrue = SUNTRUE; - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && arkode_butcher_order6a(b[i], c[j], c[k], - c[l], c[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 6 conditions A\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && arkode_butcher_order6b(b[i], c[j], c[k], - c[l], A[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 6 conditions B\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && arkode_butcher_order6c(b[i], c[j], A[k], - c[l], A[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 6 conditions C\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && arkode_butcher_order6d(b[i], c[j], c[k], - A[l], c[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 6 conditions D\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && arkode_butcher_order6e(b[i], c[j], c[k], - A[l], A[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 6 conditions E\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && arkode_butcher_order6f(b[i], A[j], A[k], - c[l], A[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 6 conditions F\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && arkode_butcher_order6g(b[i], c[j], A[k], - c[l], c[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 6 conditions G\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && arkode_butcher_order6h(b[i], c[j], A[k], - c[l], A[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 6 conditions H\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && arkode_butcher_order6i(b[i], c[j], A[k], - A[l], c[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 6 conditions I\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && arkode_butcher_order6j(b[i], c[j], A[k], - A[l], A[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 6 conditions J\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && arkode_butcher_order6k(b[i], A[j], c[k], - c[l], c[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 6 conditions K\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && arkode_butcher_order6l(b[i], A[j], c[k], - c[l], A[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 6 conditions L\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && arkode_butcher_order6m(b[i], A[j], A[k], - c[l], A[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 6 conditions M\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && arkode_butcher_order6n(b[i], A[j], c[k], - A[l], c[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 6 conditions N\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && arkode_butcher_order6o(b[i], A[j], c[k], - A[l], A[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 6 conditions O\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && arkode_butcher_order6p(b[i], A[j], A[k], - c[l], c[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 6 conditions P\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && arkode_butcher_order6q(b[i], A[j], A[k], - c[l], A[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 6 conditions Q\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && arkode_butcher_order6r(b[i], A[j], A[k], - A[l], c[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 6 conditions R\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && arkode_butcher_order6s(b[i], A[j], A[k], - A[l], A[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " method fails order 6 conditions S\n"); - } - if (alltrue) { (*q) = 6; } - } - - /* check embedding order */ - if (d[0] && d[1]) - { - if (outfile) { fprintf(outfile, "\n"); } - - /* row sum conditions */ - if (arkode_butcher_rowsum(A[0], c[0], s) && - arkode_butcher_rowsum(A[1], c[1], s)) - { - (*p) = 0; - } - else - { - (*p) = -1; - if (outfile) - { - fprintf(outfile, " embedding fails row sum conditions\n"); - } - } - /* order 1 conditions */ - if ((*p) == 0) - { - if (arkode_butcher_order1(d[0], s) && arkode_butcher_order1(d[1], s)) - { - (*p) = 1; - } - else - { - if (outfile) - { - fprintf(outfile, " embedding fails order 1 conditions\n"); - } - } - } - /* order 2 conditions */ - if ((*p) == 1) - { - alltrue = SUNTRUE; - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - alltrue = (alltrue && arkode_butcher_order2(d[i], c[j], s)); - } - } - if (alltrue) { (*p) = 2; } - else - { - if (outfile) - { - fprintf(outfile, " embedding fails order 2 conditions\n"); - } - } - } - /* order 3 conditions */ - if ((*p) == 2) - { - alltrue = SUNTRUE; - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - alltrue = (alltrue && arkode_butcher_order3a(d[i], c[j], c[k], s)); - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 3 conditions A\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - alltrue = (alltrue && arkode_butcher_order3b(d[i], A[j], c[k], s)); - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 3 conditions B\n"); - } - if (alltrue) { (*p) = 3; } - } - /* order 4 conditions */ - if ((*p) == 3) - { - alltrue = SUNTRUE; - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - alltrue = (alltrue && - arkode_butcher_order4a(d[i], c[j], c[k], c[l], s)); - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 4 conditions A\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - alltrue = (alltrue && - arkode_butcher_order4b(d[i], c[j], A[k], c[l], s)); - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 4 conditions B\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - alltrue = (alltrue && - arkode_butcher_order4c(d[i], A[j], c[k], c[l], s)); - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 4 conditions C\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - alltrue = (alltrue && - arkode_butcher_order4d(d[i], A[j], A[k], c[l], s)); - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 4 conditions D\n"); - } - if (alltrue) { (*p) = 4; } - } - /* order 5 conditions */ - if ((*p) == 4) - { - alltrue = SUNTRUE; - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - alltrue = (alltrue && arkode_butcher_order5a(d[i], c[j], c[k], - c[l], c[m], s)); - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 5 conditions A\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - alltrue = (alltrue && arkode_butcher_order5b(d[i], c[j], c[k], - A[l], c[m], s)); - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 5 conditions B\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - alltrue = (alltrue && arkode_butcher_order5c(d[i], A[j], c[k], - A[l], c[m], s)); - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 5 conditions C\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - alltrue = (alltrue && arkode_butcher_order5d(d[i], c[j], A[k], - c[l], c[m], s)); - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 5 conditions D\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - alltrue = (alltrue && arkode_butcher_order5e(d[i], A[j], c[k], - c[l], c[m], s)); - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 5 conditions E\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - alltrue = (alltrue && arkode_butcher_order5f(d[i], c[j], A[k], - A[l], c[m], s)); - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 5 conditions F\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - alltrue = (alltrue && arkode_butcher_order5g(d[i], A[j], c[k], - A[l], c[m], s)); - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 5 conditions G\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - alltrue = (alltrue && arkode_butcher_order5h(d[i], A[j], A[k], - c[l], c[m], s)); - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 5 conditions H\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - alltrue = (alltrue && arkode_butcher_order5i(d[i], A[j], A[k], - A[l], c[m], s)); - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 5 conditions I\n"); - } - if (alltrue) { (*p) = 5; } - } - /* order 6 conditions */ - if ((*p) == 5) - { - alltrue = SUNTRUE; - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && - arkode_butcher_order6a(d[i], c[j], c[k], c[l], - c[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 6 conditions A\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && - arkode_butcher_order6b(d[i], c[j], c[k], c[l], - A[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 6 conditions B\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && - arkode_butcher_order6c(d[i], c[j], A[k], c[l], - A[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 6 conditions C\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && - arkode_butcher_order6d(d[i], c[j], c[k], A[l], - c[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 6 conditions D\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && - arkode_butcher_order6e(d[i], c[j], c[k], A[l], - A[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 6 conditions E\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && - arkode_butcher_order6f(d[i], A[j], A[k], c[l], - A[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 6 conditions F\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && - arkode_butcher_order6g(d[i], c[j], A[k], c[l], - c[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 6 conditions G\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && - arkode_butcher_order6h(d[i], c[j], A[k], c[l], - A[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 6 conditions H\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && - arkode_butcher_order6i(d[i], c[j], A[k], A[l], - c[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 6 conditions I\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && - arkode_butcher_order6j(d[i], c[j], A[k], A[l], - A[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 6 conditions J\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && - arkode_butcher_order6k(d[i], A[j], c[k], c[l], - c[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 6 conditions K\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && - arkode_butcher_order6l(d[i], A[j], c[k], c[l], - A[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 6 conditions L\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && - arkode_butcher_order6m(d[i], A[j], A[k], c[l], - A[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 6 conditions M\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && - arkode_butcher_order6n(d[i], A[j], c[k], A[l], - c[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 6 conditions N\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && - arkode_butcher_order6o(d[i], A[j], c[k], A[l], - A[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 6 conditions O\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && - arkode_butcher_order6p(d[i], A[j], A[k], c[l], - c[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 6 conditions P\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && - arkode_butcher_order6q(d[i], A[j], A[k], c[l], - A[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 6 conditions Q\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && - arkode_butcher_order6r(d[i], A[j], A[k], A[l], - c[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 6 conditions R\n"); - } - for (i = 0; i < 2; i++) - { - for (j = 0; j < 2; j++) - { - for (k = 0; k < 2; k++) - { - for (l = 0; l < 2; l++) - { - for (m = 0; m < 2; m++) - { - for (n = 0; n < 2; n++) - { - alltrue = (alltrue && - arkode_butcher_order6s(d[i], A[j], A[k], A[l], - A[m], c[n], s)); - } - } - } - } - } - } - if ((!alltrue) && outfile) - { - fprintf(outfile, " embedding fails order 6 conditions S\n"); - } - if (alltrue) { (*p) = 6; } - } - } - - /* compare results against stored values and return */ - - /* check warning modes */ - if ((*q) > B1->q) { return (1); } - if ((*q) > B2->q) { return (1); } - if (d[0] && d[1]) - { - if ((*p) > B1->p) { return (1); } - if ((*p) > B2->p) { return (1); } - } - if (((*q) < B1->q) && ((*q) == 6)) { return (1); } - if (((*q) < B2->q) && ((*q) == 6)) { return (1); } - if (d[0] && d[1]) - { - if (((*p) < B1->p) && ((*p) == 6)) { return (1); } - if (((*p) < B2->p) && ((*p) == 6)) { return (1); } - } - - /* return success */ - return (0); -} - -/*--------------------------------------------------------------- - Private utility routines for checking method order - ---------------------------------------------------------------*/ - -/*--------------------------------------------------------------- - Utility routine to compute small dense matrix-vector product - b = A*x - Here A is (s x s), x and b are (s x 1). Returns 0 on success, - nonzero on failure. - ---------------------------------------------------------------*/ -static int arkode_butcher_mv(sunrealtype** A, sunrealtype* x, int s, - sunrealtype* b) -{ - int i, j; - if ((A == NULL) || (x == NULL) || (b == NULL) || (s < 1)) { return (1); } - for (i = 0; i < s; i++) { b[i] = SUN_RCONST(0.0); } - for (i = 0; i < s; i++) - { - for (j = 0; j < s; j++) { b[i] += A[i][j] * x[j]; } - } - return (0); -} - -/*--------------------------------------------------------------- - Utility routine to compute small vector .* vector product - z = x.*y [Matlab notation] - Here all vectors are (s x 1). Returns 0 on success, - nonzero on failure. - ---------------------------------------------------------------*/ -static int arkode_butcher_vv(sunrealtype* x, sunrealtype* y, int s, sunrealtype* z) -{ - int i; - if ((x == NULL) || (y == NULL) || (z == NULL) || (s < 1)) { return (1); } - for (i = 0; i < s; i++) { z[i] = x[i] * y[i]; } - return (0); -} - -/*--------------------------------------------------------------- - Utility routine to compute small vector .^ int - z = x.^l [Matlab notation] - Here all vectors are (s x 1). Returns 0 on success, - nonzero on failure. - ---------------------------------------------------------------*/ -static int arkode_butcher_vp(sunrealtype* x, int l, int s, sunrealtype* z) -{ - int i; - if ((x == NULL) || (z == NULL) || (s < 1) || (s < 0)) { return (1); } - for (i = 0; i < s; i++) { z[i] = SUNRpowerI(x[i], l); } - return (0); -} - -/*--------------------------------------------------------------- - Utility routine to compute small vector dot product: - d = dot(x,y) - Here x and y are (s x 1), and d is scalar. Returns 0 on success, - nonzero on failure. - ---------------------------------------------------------------*/ -static int arkode_butcher_dot(sunrealtype* x, sunrealtype* y, int s, - sunrealtype* d) -{ - int i; - if ((x == NULL) || (y == NULL) || (d == NULL) || (s < 1)) { return (1); } - (*d) = SUN_RCONST(0.0); - for (i = 0; i < s; i++) { (*d) += x[i] * y[i]; } - return (0); -} - -/*--------------------------------------------------------------- - Utility routines to check specific order conditions. Each - returns SUNTRUE on success, SUNFALSE on failure. - Order 0: arkode_butcher_rowsum - Order 1: arkode_butcher_order1 - Order 2: arkode_butcher_order2 - Order 3: arkode_butcher_order3a and arkode_butcher_order3b - Order 4: arkode_butcher_order4a through arkode_butcher_order4d - Order 5: arkode_butcher_order5a through arkode_butcher_order5i - Order 6: arkode_butcher_order6a through arkode_butcher_order6s - ---------------------------------------------------------------*/ - -/* c(i) = sum(A(i,:)) */ -static sunbooleantype arkode_butcher_rowsum(sunrealtype** A, sunrealtype* c, int s) -{ - int i, j; - sunrealtype rsum; - for (i = 0; i < s; i++) - { - rsum = SUN_RCONST(0.0); - for (j = 0; j < s; j++) { rsum += A[i][j]; } - if (SUNRabs(rsum - c[i]) > TOL) { return (SUNFALSE); } - } - return (SUNTRUE); -} - -/* b'*e = 1 */ -static sunbooleantype arkode_butcher_order1(sunrealtype* b, int s) -{ - int i; - sunrealtype err = SUN_RCONST(1.0); - for (i = 0; i < s; i++) { err -= b[i]; } - return (SUNRabs(err) > TOL) ? SUNFALSE : SUNTRUE; -} - -/* b'*c = 1/2 */ -static sunbooleantype arkode_butcher_order2(sunrealtype* b, sunrealtype* c, int s) -{ - sunrealtype bc; - if (arkode_butcher_dot(b, c, s, &bc)) { return (SUNFALSE); } - return (SUNRabs(bc - SUN_RCONST(0.5)) > TOL) ? SUNFALSE : SUNTRUE; -} - -/* b'*(c1.*c2) = 1/3 */ -static sunbooleantype arkode_butcher_order3a(sunrealtype* b, sunrealtype* c1, - sunrealtype* c2, int s) -{ - sunrealtype bcc; - sunrealtype* tmp = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_vv(c1, c2, s, tmp)) - { - free(tmp); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp, s, &bcc)) { return (SUNFALSE); } - free(tmp); - return (SUNRabs(bcc - SUN_RCONST(1.0) / SUN_RCONST(3.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*(A*c) = 1/6 */ -static sunbooleantype arkode_butcher_order3b(sunrealtype* b, sunrealtype** A, - sunrealtype* c, int s) -{ - sunrealtype bAc; - sunrealtype* tmp = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_mv(A, c, s, tmp)) - { - free(tmp); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp, s, &bAc)) { return (SUNFALSE); } - free(tmp); - return (SUNRabs(bAc - SUN_RCONST(1.0) / SUN_RCONST(6.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*(c1.*c2.*c3) = 1/4 */ -static sunbooleantype arkode_butcher_order4a(sunrealtype* b, sunrealtype* c1, - sunrealtype* c2, sunrealtype* c3, - int s) -{ - sunrealtype bccc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_vv(c1, c2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c3, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp2, s, &bccc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bccc - SUN_RCONST(0.25)) > TOL) ? SUNFALSE : SUNTRUE; -} - -/* (b.*c1)'*(A*c2) = 1/8 */ -static sunbooleantype arkode_butcher_order4b(sunrealtype* b, sunrealtype* c1, - sunrealtype** A, sunrealtype* c2, - int s) -{ - sunrealtype bcAc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_vv(b, c1, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A, c2, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(tmp1, tmp2, s, &bcAc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bcAc - SUN_RCONST(0.125)) > TOL) ? SUNFALSE : SUNTRUE; -} - -/* b'*A*(c1.*c2) = 1/12 */ -static sunbooleantype arkode_butcher_order4c(sunrealtype* b, sunrealtype** A, - sunrealtype* c1, sunrealtype* c2, - int s) -{ - sunrealtype bAcc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_vv(c1, c2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp2, s, &bAcc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bAcc - SUN_RCONST(1.0) / SUN_RCONST(12.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*A1*A2*c = 1/24 */ -static sunbooleantype arkode_butcher_order4d(sunrealtype* b, sunrealtype** A1, - sunrealtype** A2, sunrealtype* c, - int s) -{ - sunrealtype bAAc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_mv(A2, c, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A1, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp2, s, &bAAc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bAAc - SUN_RCONST(1.0) / SUN_RCONST(24.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*(c1.*c2.*c3.*c4) = 1/5 */ -static sunbooleantype arkode_butcher_order5a(sunrealtype* b, sunrealtype* c1, - sunrealtype* c2, sunrealtype* c3, - sunrealtype* c4, int s) -{ - sunrealtype bcccc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_vv(c1, c2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c3, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c4, tmp2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp1, s, &bcccc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bcccc - SUN_RCONST(0.2)) > TOL) ? SUNFALSE : SUNTRUE; -} - -/* (b.*c1.*c2)'*(A*c3) = 1/10 */ -static sunbooleantype arkode_butcher_order5b(sunrealtype* b, sunrealtype* c1, - sunrealtype* c2, sunrealtype** A, - sunrealtype* c3, int s) -{ - sunrealtype bccAc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_vv(c1, c2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(b, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A, c3, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(tmp1, tmp2, s, &bccAc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bccAc - SUN_RCONST(0.1)) > TOL) ? SUNFALSE : SUNTRUE; -} - -/* b'*((A1*c1).*(A2*c2)) = 1/20 */ -static sunbooleantype arkode_butcher_order5c(sunrealtype* b, sunrealtype** A1, - sunrealtype* c1, sunrealtype** A2, - sunrealtype* c2, int s) -{ - sunrealtype bAcAc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp3 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_mv(A1, c1, s, tmp1)) - { - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNFALSE); - } - if (arkode_butcher_mv(A2, c2, s, tmp2)) - { - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNFALSE); - } - if (arkode_butcher_vv(tmp1, tmp2, s, tmp3)) - { - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp3, s, &bAcAc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNRabs(bAcAc - SUN_RCONST(0.05)) > TOL) ? SUNFALSE : SUNTRUE; -} - -/* (b.*c1)'*A*(c2.*c3) = 1/15 */ -static sunbooleantype arkode_butcher_order5d(sunrealtype* b, sunrealtype* c1, - sunrealtype** A, sunrealtype* c2, - sunrealtype* c3, int s) -{ - sunrealtype bcAcc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_vv(c2, c3, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(b, c1, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(tmp1, tmp2, s, &bcAcc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bcAcc - SUN_RCONST(1.0) / SUN_RCONST(15.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*A*(c1.*c2.*c3) = 1/20 */ -static sunbooleantype arkode_butcher_order5e(sunrealtype* b, sunrealtype** A, - sunrealtype* c1, sunrealtype* c2, - sunrealtype* c3, int s) -{ - sunrealtype bAccc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_vv(c1, c2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c3, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A, tmp2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp1, s, &bAccc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bAccc - SUN_RCONST(0.05)) > TOL) ? SUNFALSE : SUNTRUE; -} - -/* (b.*c1)'*A1*A2*c2 = 1/30 */ -static sunbooleantype arkode_butcher_order5f(sunrealtype* b, sunrealtype* c1, - sunrealtype** A1, sunrealtype** A2, - sunrealtype* c2, int s) -{ - sunrealtype bcAAc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_mv(A2, c2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A1, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(b, c1, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(tmp1, tmp2, s, &bcAAc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bcAAc - SUN_RCONST(1.0) / SUN_RCONST(30.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*A1*(c1.*(A2*c2)) = 1/40 */ -static sunbooleantype arkode_butcher_order5g(sunrealtype* b, sunrealtype** A1, - sunrealtype* c1, sunrealtype** A2, - sunrealtype* c2, int s) -{ - sunrealtype bAcAc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_mv(A2, c2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c1, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A1, tmp2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp1, s, &bAcAc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bAcAc - SUN_RCONST(1.0) / SUN_RCONST(40.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*A1*A2*(c1.*c2) = 1/60 */ -static sunbooleantype arkode_butcher_order5h(sunrealtype* b, sunrealtype** A1, - sunrealtype** A2, sunrealtype* c1, - sunrealtype* c2, int s) -{ - sunrealtype bAAcc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_vv(c1, c2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A2, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A1, tmp2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp1, s, &bAAcc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bAAcc - SUN_RCONST(1.0) / SUN_RCONST(60.0)) > TOL) ? SUNFALSE - : SUNTRUE; + const ARKodeButcherTable tables[] = {B1, B2}; + return check_tables(tables, SUNTRUE, q, p, outfile); } - -/* b'*A1*A2*A3*c = 1/120 */ -static sunbooleantype arkode_butcher_order5i(sunrealtype* b, sunrealtype** A1, - sunrealtype** A2, sunrealtype** A3, - sunrealtype* c, int s) -{ - sunrealtype bAAAc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_mv(A3, c, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A2, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A1, tmp2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp1, s, &bAAAc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bAAAc - SUN_RCONST(1.0) / SUN_RCONST(120.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*(c1.*c2.*c3.*c4.*c5) = 1/6 */ -static sunbooleantype arkode_butcher_order6a(sunrealtype* b, sunrealtype* c1, - sunrealtype* c2, sunrealtype* c3, - sunrealtype* c4, sunrealtype* c5, - int s) -{ - sunrealtype bccccc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_vv(c1, c2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c3, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c4, tmp2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c5, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp2, s, &bccccc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bccccc - SUN_RCONST(1.0) / SUN_RCONST(6.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* (b.*c1.*c2.*c3)'*(A*c4) = 1/12 */ -static sunbooleantype arkode_butcher_order6b(sunrealtype* b, sunrealtype* c1, - sunrealtype* c2, sunrealtype* c3, - sunrealtype** A, sunrealtype* c4, - int s) -{ - sunrealtype bcccAc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_vv(b, c1, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c2, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c3, tmp2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A, c4, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(tmp1, tmp2, s, &bcccAc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bcccAc - SUN_RCONST(1.0) / SUN_RCONST(12.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*(c1.*(A1*c2).*(A2*c3)) = 1/24 */ -static sunbooleantype arkode_butcher_order6c(sunrealtype* b, sunrealtype* c1, - sunrealtype** A1, sunrealtype* c2, - sunrealtype** A2, sunrealtype* c3, - int s) -{ - sunrealtype bcAc2; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp3 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_mv(A2, c3, s, tmp1)) - { - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNFALSE); - } - if (arkode_butcher_mv(A1, c2, s, tmp2)) - { - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNFALSE); - } - if (arkode_butcher_vv(tmp1, tmp2, s, tmp3)) - { - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNFALSE); - } - if (arkode_butcher_vv(c1, tmp3, s, tmp1)) - { - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp1, s, &bcAc2)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNRabs(bcAc2 - SUN_RCONST(1.0) / SUN_RCONST(24.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* (b.*c1.*c2)'*A*(c3.*c4) = 1/18 */ -static sunbooleantype arkode_butcher_order6d(sunrealtype* b, sunrealtype* c1, - sunrealtype* c2, sunrealtype** A, - sunrealtype* c3, sunrealtype* c4, - int s) -{ - sunrealtype bccAcc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp3 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_vv(c3, c4, s, tmp1)) - { - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNFALSE); - } - if (arkode_butcher_mv(A, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNFALSE); - } - if (arkode_butcher_vv(c1, c2, s, tmp1)) - { - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNFALSE); - } - if (arkode_butcher_vv(b, tmp1, s, tmp3)) - { - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNFALSE); - } - if (arkode_butcher_dot(tmp2, tmp3, s, &bccAcc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNRabs(bccAcc - SUN_RCONST(1.0) / SUN_RCONST(18.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* (b.*(c1.*c2))'*A1*A2*c3 = 1/36 */ -static sunbooleantype arkode_butcher_order6e(sunrealtype* b, sunrealtype* c1, - sunrealtype* c2, sunrealtype** A1, - sunrealtype** A2, sunrealtype* c3, - int s) -{ - sunrealtype bccAAc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp3 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_vv(c1, c2, s, tmp1)) - { - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNFALSE); - } - if (arkode_butcher_vv(b, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNFALSE); - } - if (arkode_butcher_mv(A2, c3, s, tmp1)) - { - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNFALSE); - } - if (arkode_butcher_mv(A1, tmp1, s, tmp3)) - { - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNFALSE); - } - if (arkode_butcher_dot(tmp2, tmp3, s, &bccAAc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNRabs(bccAAc - SUN_RCONST(1.0) / SUN_RCONST(36.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*((A1*A2*c1).*(A3*c2)) = 1/72 */ -static sunbooleantype arkode_butcher_order6f(sunrealtype* b, sunrealtype** A1, - sunrealtype** A2, sunrealtype* c1, - sunrealtype** A3, sunrealtype* c2, - int s) -{ - sunrealtype bAAcAc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp3 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_mv(A2, c1, s, tmp1)) - { - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNFALSE); - } - if (arkode_butcher_mv(A1, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNFALSE); - } - if (arkode_butcher_mv(A3, c2, s, tmp1)) - { - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNFALSE); - } - if (arkode_butcher_vv(tmp1, tmp2, s, tmp3)) - { - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp3, s, &bAAcAc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNRabs(bAAcAc - SUN_RCONST(1.0) / SUN_RCONST(72.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*(c1.*(A*(c2.*c3.*c4))) = 1/24 */ -static sunbooleantype arkode_butcher_order6g(sunrealtype* b, sunrealtype* c1, - sunrealtype** A, sunrealtype* c2, - sunrealtype* c3, sunrealtype* c4, - int s) -{ - sunrealtype bcAccc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_vv(c2, c3, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c4, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A, tmp2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c1, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp2, s, &bcAccc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bcAccc - SUN_RCONST(1.0) / SUN_RCONST(24.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*(c1.*(A1*(c2.*(A2*c3)))) = 1/48 */ -static sunbooleantype arkode_butcher_order6h(sunrealtype* b, sunrealtype* c1, - sunrealtype** A1, sunrealtype* c2, - sunrealtype** A2, sunrealtype* c3, - int s) -{ - sunrealtype bcAcAc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_mv(A2, c3, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c2, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A1, tmp2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c1, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp2, s, &bcAcAc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bcAcAc - SUN_RCONST(1.0) / SUN_RCONST(48.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*(c1.*(A1*A2*(c2.*c3))) = 1/72 */ -static sunbooleantype arkode_butcher_order6i(sunrealtype* b, sunrealtype* c1, - sunrealtype** A1, sunrealtype** A2, - sunrealtype* c2, sunrealtype* c3, - int s) -{ - sunrealtype bcAAcc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_vv(c2, c3, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A2, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A1, tmp2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c1, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp2, s, &bcAAcc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bcAAcc - SUN_RCONST(1.0) / SUN_RCONST(72.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*(c1.*(A1*A2*A3*c2)) = 1/144 */ -static sunbooleantype arkode_butcher_order6j(sunrealtype* b, sunrealtype* c1, - sunrealtype** A1, sunrealtype** A2, - sunrealtype** A3, sunrealtype* c2, - int s) -{ - sunrealtype bcAAAc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_mv(A3, c2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A2, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A1, tmp2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c1, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp2, s, &bcAAAc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bcAAAc - SUN_RCONST(1.0) / SUN_RCONST(144.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*A*(c1.*c2.*c3.*c4) = 1/30 */ -static sunbooleantype arkode_butcher_order6k(sunrealtype* b, sunrealtype** A, - sunrealtype* c1, sunrealtype* c2, - sunrealtype* c3, sunrealtype* c4, - int s) -{ - sunrealtype bAcccc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_vv(c1, c2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c3, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c4, tmp2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp2, s, &bAcccc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bAcccc - SUN_RCONST(1.0) / SUN_RCONST(30.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*A1*(c1.*c2.*(A2*c3)) = 1/60 */ -static sunbooleantype arkode_butcher_order6l(sunrealtype* b, sunrealtype** A1, - sunrealtype* c1, sunrealtype* c2, - sunrealtype** A2, sunrealtype* c3, - int s) -{ - sunrealtype bAccAc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_mv(A2, c3, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c2, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c1, tmp2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A1, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp2, s, &bAccAc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bAccAc - SUN_RCONST(1.0) / SUN_RCONST(60.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*A1*((A2*c1).*(A3*c2)) = 1/120 */ -static sunbooleantype arkode_butcher_order6m(sunrealtype* b, sunrealtype** A1, - sunrealtype** A2, sunrealtype* c1, - sunrealtype** A3, sunrealtype* c2, - int s) -{ - sunrealtype bAAcAc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp3 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_mv(A3, c2, s, tmp1)) - { - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNFALSE); - } - if (arkode_butcher_mv(A2, c1, s, tmp2)) - { - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNFALSE); - } - if (arkode_butcher_vv(tmp1, tmp2, s, tmp3)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A1, tmp3, s, tmp1)) - { - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp1, s, &bAAcAc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - free(tmp3); - return (SUNRabs(bAAcAc - SUN_RCONST(1.0) / SUN_RCONST(120.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*A1*(c1.*(A2*(c2.*c3))) = 1/90 */ -static sunbooleantype arkode_butcher_order6n(sunrealtype* b, sunrealtype** A1, - sunrealtype* c1, sunrealtype** A2, - sunrealtype* c2, sunrealtype* c3, - int s) -{ - sunrealtype bAcAcc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_vv(c2, c3, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A2, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c1, tmp2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A1, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp2, s, &bAcAcc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bAcAcc - SUN_RCONST(1.0) / SUN_RCONST(90.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*A1*(c1.*(A2*A3*c2)) = 1/180 */ -static sunbooleantype arkode_butcher_order6o(sunrealtype* b, sunrealtype** A1, - sunrealtype* c1, sunrealtype** A2, - sunrealtype** A3, sunrealtype* c2, - int s) -{ - sunrealtype bAcAAc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_mv(A3, c2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A2, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c1, tmp2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A1, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp2, s, &bAcAAc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bAcAAc - SUN_RCONST(1.0) / SUN_RCONST(180.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*A1*A2*(c1.*c2.*c3) = 1/120 */ -static sunbooleantype arkode_butcher_order6p(sunrealtype* b, sunrealtype** A1, - sunrealtype** A2, sunrealtype* c1, - sunrealtype* c2, sunrealtype* c3, - int s) -{ - sunrealtype bAAccc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_vv(c1, c2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c3, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A2, tmp2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A1, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp2, s, &bAAccc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bAAccc - SUN_RCONST(1.0) / SUN_RCONST(120.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*A1*A2*(c1.*(A3*c2)) = 1/240 */ -static sunbooleantype arkode_butcher_order6q(sunrealtype* b, sunrealtype** A1, - sunrealtype** A2, sunrealtype* c1, - sunrealtype** A3, sunrealtype* c2, - int s) -{ - sunrealtype bAAcAc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_mv(A3, c2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_vv(c1, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A2, tmp2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A1, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp2, s, &bAAcAc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bAAcAc - SUN_RCONST(1.0) / SUN_RCONST(240.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*A1*A2*A3*(c1.*c2) = 1/360 */ -static sunbooleantype arkode_butcher_order6r(sunrealtype* b, sunrealtype** A1, - sunrealtype** A2, sunrealtype** A3, - sunrealtype* c1, sunrealtype* c2, - int s) -{ - sunrealtype bAAAcc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_vv(c1, c2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A3, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A2, tmp2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A1, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp2, s, &bAAAcc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bAAAcc - SUN_RCONST(1.0) / SUN_RCONST(360.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/* b'*A1*A2*A3*A4*c = 1/720 */ -static sunbooleantype arkode_butcher_order6s(sunrealtype* b, sunrealtype** A1, - sunrealtype** A2, sunrealtype** A3, - sunrealtype** A4, sunrealtype* c, - int s) -{ - sunrealtype bAAAAc; - sunrealtype* tmp1 = calloc(s, sizeof(sunrealtype)); - sunrealtype* tmp2 = calloc(s, sizeof(sunrealtype)); - if (arkode_butcher_mv(A4, c, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A3, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A2, tmp2, s, tmp1)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_mv(A1, tmp1, s, tmp2)) - { - free(tmp1); - free(tmp2); - return (SUNFALSE); - } - if (arkode_butcher_dot(b, tmp2, s, &bAAAAc)) { return (SUNFALSE); } - free(tmp1); - free(tmp2); - return (SUNRabs(bAAAAc - SUN_RCONST(1.0) / SUN_RCONST(720.0)) > TOL) ? SUNFALSE - : SUNTRUE; -} - -/*--------------------------------------------------------------- - Utility routine to check Butcher's simplifying assumptions. - Returns the maximum predicted order. - ---------------------------------------------------------------*/ -static int __ButcherSimplifyingAssumptions(sunrealtype** A, sunrealtype* b, - sunrealtype* c, int s) -{ - int P, Q, R, i, j, k, q; - sunrealtype RHS, LHS; - sunbooleantype alltrue; - sunrealtype* tmp = calloc(s, sizeof(sunrealtype)); - - /* B(P) */ - P = 0; - for (i = 1; i < 1000; i++) - { - if (arkode_butcher_vp(c, i - 1, s, tmp)) - { - free(tmp); - return (0); - } - if (arkode_butcher_dot(b, tmp, s, &LHS)) - { - free(tmp); - return (0); - } - RHS = SUN_RCONST(1.0) / i; - if (SUNRabs(RHS - LHS) > TOL) { break; } - P++; - } - - /* C(Q) */ - Q = 0; - for (k = 1; k < 1000; k++) - { - alltrue = SUNTRUE; - for (i = 0; i < s; i++) - { - if (arkode_butcher_vp(c, k - 1, s, tmp)) - { - free(tmp); - return (0); - } - if (arkode_butcher_dot(A[i], tmp, s, &LHS)) - { - free(tmp); - return (0); - } - RHS = SUNRpowerI(c[i], k) / k; - if (SUNRabs(RHS - LHS) > TOL) - { - alltrue = SUNFALSE; - break; - } - } - if (alltrue) { Q++; } - else { break; } - } - - /* D(R) */ - R = 0; - for (k = 1; k < 1000; k++) - { - alltrue = SUNTRUE; - for (j = 0; j < s; j++) - { - LHS = SUN_RCONST(0.0); - for (i = 0; i < s; i++) - { - LHS += A[i][j] * b[i] * SUNRpowerI(c[i], k - 1); - } - RHS = b[j] / k * (SUN_RCONST(1.0) - SUNRpowerI(c[j], k)); - if (SUNRabs(RHS - LHS) > TOL) - { - alltrue = SUNFALSE; - break; - } - } - if (alltrue) { R++; } - else { break; } - } - - /* determine q, clean up and return */ - q = 0; - for (i = 1; i <= P; i++) - { - if ((q > Q + R + 1) || (q > 2 * Q + 2)) { break; } - q++; - } - free(tmp); - return (q); -} - -/*--------------------------------------------------------------- - EOF - ---------------------------------------------------------------*/ From 5473f16f062b699d148fa5080f1ae57b7bc6ff97 Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Mon, 21 Oct 2024 10:53:26 -0700 Subject: [PATCH 13/89] Feature: Extending Precision for Some DIRK Methods (#593) The Billington, Cash, and Kvaerno DIRK method coefficients only had ~10-14 digits of accuracy which can be insufficient for double and extended precision. This PR extends the coefficients to 40 digits. --- CHANGELOG.md | 8 + doc/arkode/guide/source/Butcher.rst | 10 +- doc/shared/RecentChanges.rst | 14 ++ src/arkode/arkode_butcher_dirk.def | 306 ++++++++++++++-------------- 4 files changed, 180 insertions(+), 158 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2aff004841..7a2184439e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,14 @@ ### New Features and Enhancements +The following DIRK schemes now have coefficients accurate to quad precision: +* `ARKODE_BILLINGTON_3_3_2` +* `ARKODE_KVAERNO_4_2_3` +* `ARKODE_CASH_5_2_4` +* `ARKODE_CASH_5_3_4` +* `ARKODE_KVAERNO_5_3_4` +* `ARKODE_KVAERNO_7_4_5` + The default value of `CMAKE_CUDA_ARCHITECTURES` is no longer set to `70` and is now determined automatically by CMake. The previous default was only valid for Volta GPUs while the automatically selected value will vary across compilers and diff --git a/doc/arkode/guide/source/Butcher.rst b/doc/arkode/guide/source/Butcher.rst index 0b7e401a56..4e6aec608a 100644 --- a/doc/arkode/guide/source/Butcher.rst +++ b/doc/arkode/guide/source/Butcher.rst @@ -1407,12 +1407,12 @@ Here, the higher-order embedding is less stable than the lower-order method \renewcommand{\arraystretch}{1.5} \begin{array}{r|ccc} - 0.292893218813 & 0.292893218813 & 0 & 0 \\ - 1.091883092037 & 0.798989873223 & 0.292893218813 & 0 \\ - 1.292893218813 & 0.740789228841 & 0.259210771159 & 0.292893218813 \\ + 1 - \frac{1}{\sqrt{2}} & 1 - \frac{1}{\sqrt{2}} & 0 & 0 \\ + \frac{27}{\sqrt{2}} - 18 & 14 \sqrt{2} - 19 & 1 - \frac{1}{\sqrt{2}} & 0 \\ + 2 - \frac{1}{\sqrt{2}} & \frac{53 - 5 \sqrt{2}}{62} & \frac{9 + 5 \sqrt{2}}{62} & 1 - \frac{1}{\sqrt{2}} \\ \hline - 2 & 0.740789228840 & 0.259210771159 & 0 \\ - 3 & 0.691665115992 & 0.503597029883 & -0.195262145876 + 2 & \frac{53 - 5 \sqrt{2}}{62} & \frac{9 + 5 \sqrt{2}}{62} & 0 \\ + 3 & \frac{263 - 95 \sqrt{2}}{186} & \frac{47 + 33 \sqrt{2}}{186} & \frac{\sqrt{2} - 2}{3} \end{array} .. figure:: /figs/arkode/stab_region_12.png diff --git a/doc/shared/RecentChanges.rst b/doc/shared/RecentChanges.rst index 875d45c9b7..2be479f59c 100644 --- a/doc/shared/RecentChanges.rst +++ b/doc/shared/RecentChanges.rst @@ -2,6 +2,20 @@ **New Features and Enhancements** +The following DIRK schemes now have coefficients accurate to quad precision: + +* ``ARKODE_BILLINGTON_3_3_2`` + +* ``ARKODE_KVAERNO_4_2_3`` + +* ``ARKODE_CASH_5_2_4`` + +* ``ARKODE_CASH_5_3_4`` + +* ``ARKODE_KVAERNO_5_3_4`` + +* ``ARKODE_KVAERNO_7_4_5`` + The default value of :cmakeop:`CMAKE_CUDA_ARCHITECTURES` is no longer set to ``70`` and is now determined automatically by CMake. The previous default was only valid for Volta GPUs while the automatically selected value will vary diff --git a/src/arkode/arkode_butcher_dirk.def b/src/arkode/arkode_butcher_dirk.def index 40d13e60bd..06fdfb82bd 100644 --- a/src/arkode/arkode_butcher_dirk.def +++ b/src/arkode/arkode_butcher_dirk.def @@ -39,24 +39,24 @@ ARKODE_ARK2_DIRK_3_1_2 ESDIRK Y Y Y ARKODE_IMPLICIT_MIDPOINT_1_2 SDIRK Y N Y ARKODE_IMPLICIT_TRAPEZOIDAL_2_2 ESDIRK Y N Y - ARKODE_BILLINGTON_3_3_2 SDIRK N N N + ARKODE_BILLINGTON_3_3_2 SDIRK N N Y ARKODE_TRBDF2_3_3_2 ESDIRK N N Y - ARKODE_KVAERNO_4_2_3 ESDIRK Y Y N + ARKODE_KVAERNO_4_2_3 ESDIRK Y Y Y ARKODE_ARK324L2SA_DIRK_4_2_3* ESDIRK Y Y N ARKODE_ESDIRK324L2SA_4_2_3 ESDIRK Y Y Y ARKODE_ESDIRK325L2SA_5_2_3 ESDIRK Y Y Y ARKODE_ESDIRK32I5L2SA_5_2_3 ESDIRK Y Y Y - ARKODE_CASH_5_2_4 SDIRK Y Y N - ARKODE_CASH_5_3_4 SDIRK Y Y N + ARKODE_CASH_5_2_4 SDIRK Y Y Y + ARKODE_CASH_5_3_4 SDIRK Y Y Y ARKODE_SDIRK_5_3_4 SDIRK Y Y Y - ARKODE_KVAERNO_5_3_4 ESDIRK Y N N + ARKODE_KVAERNO_5_3_4 ESDIRK Y N Y ARKODE_ARK436L2SA_DIRK_6_3_4* ESDIRK Y Y N ARKODE_ARK437L2SA_DIRK_7_3_4* ESDIRK Y Y N ARKODE_ESDIRK436L2SA_6_3_4 ESDIRK Y Y N ARKODE_ESDIRK43I6L2SA_6_3_4 ESDIRK Y Y N ARKODE_QESDIRK436L2SA_6_3_4 ESDIRK Y Y N ARKODE_ESDIRK437L2SA_7_3_4 ESDIRK Y Y N - ARKODE_KVAERNO_7_4_5 ESDIRK Y Y N + ARKODE_KVAERNO_7_4_5 ESDIRK Y Y Y ARKODE_ARK548L2SA_DIRK_8_4_5* ESDIRK Y Y N ARKODE_ARK548L2SAb_DIRK_8_4_5* ESDIRK Y Y N ARKODE_ESDIRK547L2SA_7_4_5 ESDIRK Y Y N @@ -169,23 +169,23 @@ ARK_BUTCHER_TABLE(ARKODE_BILLINGTON_3_3_2, { /* Billington-SDIRK */ B->q = 2; B->p = 3; - B->A[0][0] = SUN_RCONST(0.292893218813); - B->A[1][0] = SUN_RCONST(0.798989873223); - B->A[1][1] = SUN_RCONST(0.292893218813); - B->A[2][0] = SUN_RCONST(0.740789228841); - B->A[2][1] = SUN_RCONST(0.259210771159); - B->A[2][2] = SUN_RCONST(0.292893218813); + B->A[0][0] = SUN_RCONST(0.2928932188134524755991556378951509607152); + B->A[1][0] = SUN_RCONST(0.7989898732233306832236421389357730999754); + B->A[1][1] = SUN_RCONST(0.2928932188134524755991556378951509607152); + B->A[2][0] = SUN_RCONST(0.7407892288408794315482509093379275743089); + B->A[2][1] = SUN_RCONST(0.2592107711591205684517490906620724256911); + B->A[2][2] = SUN_RCONST(0.2928932188134524755991556378951509607152); - B->d[0] = SUN_RCONST(0.691665115992); - B->d[1] = SUN_RCONST(0.503597029883); - B->d[2] = SUN_RCONST(-0.195262145876); + B->d[0] = SUN_RCONST(0.6916651159922363998055890924735413039564); + B->d[1] = SUN_RCONST(0.5035970298833985839271813327898926698538); + B->d[2] = SUN_RCONST(-0.1952621458756349837327704252634339738101); - B->b[0] = SUN_RCONST(0.740789228840); - B->b[1] = SUN_RCONST(0.259210771159); + B->b[0] = SUN_RCONST(0.7407892288408794315482509093379275743089); + B->b[1] = SUN_RCONST(0.2592107711591205684517490906620724256911); - B->c[0] = SUN_RCONST(0.292893218813); - B->c[1] = SUN_RCONST(1.091883092037); - B->c[2] = SUN_RCONST(1.292893218813); + B->c[0] = SUN_RCONST(0.2928932188134524755991556378951509607152); + B->c[1] = SUN_RCONST(1.091883092036783158822797776830924060691); + B->c[2] = SUN_RCONST(1.292893218813452475599155637895150960715); return B; }) @@ -217,26 +217,26 @@ ARK_BUTCHER_TABLE(ARKODE_KVAERNO_4_2_3, { /* Kvaerno(4,2,3)-ESDIRK */ ARKodeButcherTable B = ARKodeButcherTable_Alloc(4, SUNTRUE); B->q = 3; B->p = 2; - B->A[1][0] = SUN_RCONST(0.4358665215); - B->A[1][1] = SUN_RCONST(0.4358665215); - B->A[2][0] = SUN_RCONST(0.490563388419108); - B->A[2][1] = SUN_RCONST(0.073570090080892); - B->A[2][2] = SUN_RCONST(0.4358665215); - B->A[3][0] = SUN_RCONST(0.308809969973036); - B->A[3][1] = SUN_RCONST(1.490563388254106); - B->A[3][2] = SUN_RCONST(-1.235239879727145); - B->A[3][3] = SUN_RCONST(0.4358665215); - - B->b[0] = SUN_RCONST(0.308809969973036); - B->b[1] = SUN_RCONST(1.490563388254106); - B->b[2] = SUN_RCONST(-1.235239879727145); - B->b[3] = SUN_RCONST(0.4358665215); - - B->d[0] = SUN_RCONST(0.490563388419108); - B->d[1] = SUN_RCONST(0.073570090080892); - B->d[2] = SUN_RCONST(0.4358665215); - - B->c[1] = SUN_RCONST(0.871733043); + B->A[1][0] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[1][1] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[2][0] = SUN_RCONST(0.4905633884217805706284679584665446902307); + B->A[2][1] = SUN_RCONST(0.07357009006976042995551259033989846723997); + B->A[2][2] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[3][0] = SUN_RCONST(0.3088099699767465233481624698867005109200); + B->A[3][1] = SUN_RCONST(1.490563388421780570628467958466544690231); + B->A[3][2] = SUN_RCONST(-1.235239879906986093392649879546802043680); + B->A[3][3] = SUN_RCONST(0.4358665215084589994160194511935568425293); + + B->b[0] = SUN_RCONST(0.3088099699767465233481624698867005109200); + B->b[1] = SUN_RCONST(1.490563388421780570628467958466544690231); + B->b[2] = SUN_RCONST(-1.235239879906986093392649879546802043680); + B->b[3] = SUN_RCONST(0.4358665215084589994160194511935568425293); + + B->d[0] = SUN_RCONST(0.4905633884217805706284679584665446902307); + B->d[1] = SUN_RCONST(0.07357009006976042995551259033989846723997); + B->d[2] = SUN_RCONST(0.4358665215084589994160194511935568425293); + + B->c[1] = SUN_RCONST(0.8717330430169179988320389023871136850586); B->c[2] = SUN_RCONST(1.0); B->c[3] = SUN_RCONST(1.0); return B; @@ -276,35 +276,35 @@ ARK_BUTCHER_TABLE(ARKODE_CASH_5_2_4, { /* Cash(5,2,4)-SDIRK */ ARKodeButcherTable B = ARKodeButcherTable_Alloc(5, SUNTRUE); B->q = 4; B->p = 2; - B->A[0][0] = SUN_RCONST(0.435866521508); - B->A[1][0] = SUN_RCONST(-1.13586652150); - B->A[1][1] = SUN_RCONST(0.435866521508); - B->A[2][0] = SUN_RCONST(1.08543330679); - B->A[2][1] = SUN_RCONST(-0.721299828287); - B->A[2][2] = SUN_RCONST(0.435866521508); - B->A[3][0] = SUN_RCONST(0.416349501547); - B->A[3][1] = SUN_RCONST(0.190984004184); - B->A[3][2] = SUN_RCONST(-0.118643265417); - B->A[3][3] = SUN_RCONST(0.435866521508); - B->A[4][0] = SUN_RCONST(0.896869652944); - B->A[4][1] = SUN_RCONST(0.0182725272734); - B->A[4][2] = SUN_RCONST(-0.0845900310706); - B->A[4][3] = SUN_RCONST(-0.266418670647); - B->A[4][4] = SUN_RCONST(0.435866521508); - - B->b[0] = SUN_RCONST(0.896869652944); - B->b[1] = SUN_RCONST(0.0182725272734); - B->b[2] = SUN_RCONST(-0.0845900310706); - B->b[3] = SUN_RCONST(-0.266418670647); - B->b[4] = SUN_RCONST(0.435866521508); - - B->d[0] = (SUN_RCONST(-0.7)-SUN_RCONST(0.5))/(SUN_RCONST(-0.7)-SUN_RCONST(0.435866521508)); - B->d[1] = (SUN_RCONST(0.5)-SUN_RCONST(0.435866521508))/(SUN_RCONST(-0.7)-SUN_RCONST(0.435866521508)); - - B->c[0] = SUN_RCONST(0.435866521508); + B->A[0][0] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[1][0] = SUN_RCONST(-1.135866521508458999416019451193556842529); + B->A[1][1] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[2][0] = SUN_RCONST(1.085433306501187798233740932177548948256); + B->A[2][1] = SUN_RCONST(-0.7212998280096467976497603833711057907848); + B->A[2][2] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[3][0] = SUN_RCONST(0.4163495015787799872439975203112232915822); + B->A[3][1] = SUN_RCONST(0.1909840041795561340637290424182710083545); + B->A[3][2] = SUN_RCONST(-0.1186432654601150605249854908172545332519); + B->A[3][3] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[4][0] = SUN_RCONST(0.8968696529704295827357809984030487598656); + B->A[4][1] = SUN_RCONST(0.01827252727396890379954420931708867645445); + B->A[4][2] = SUN_RCONST(-0.08459003110197203803096641412326485130547); + B->A[4][3] = SUN_RCONST(-0.2664186706508854479203782447904294275438); + B->A[4][4] = SUN_RCONST(0.4358665215084589994160194511935568425293); + + B->b[0] = SUN_RCONST(0.8968696529704295827357809984030487598656); + B->b[1] = SUN_RCONST(0.01827252727396890379954420931708867645445); + B->b[2] = SUN_RCONST(-0.08459003110197203803096641412326485130547); + B->b[3] = SUN_RCONST(-0.2664186706508854479203782447904294275438); + B->b[4] = SUN_RCONST(0.4358665215084589994160194511935568425293); + + B->d[0] = SUN_RCONST(1.056462161070096639164359247420837614501); + B->d[1] = SUN_RCONST(-0.05646216107009663916435924742083761450128); + + B->c[0] = SUN_RCONST(0.4358665215084589994160194511935568425293); B->c[1] = SUN_RCONST(-0.7); B->c[2] = SUN_RCONST(0.8); - B->c[3] = SUN_RCONST(0.924556761814); + B->c[3] = SUN_RCONST(0.9245567618066800601987605231057966092142); B->c[4] = SUN_RCONST(1.0); return B; }) @@ -313,37 +313,37 @@ ARK_BUTCHER_TABLE(ARKODE_CASH_5_3_4, { /* Cash(5,3,4)-SDIRK */ ARKodeButcherTable B = ARKodeButcherTable_Alloc(5, SUNTRUE); B->q = 4; B->p = 3; - B->A[0][0] = SUN_RCONST(0.435866521508); - B->A[1][0] = SUN_RCONST(-1.13586652150); - B->A[1][1] = SUN_RCONST(0.435866521508); - B->A[2][0] = SUN_RCONST(1.08543330679); - B->A[2][1] = SUN_RCONST(-0.721299828287); - B->A[2][2] = SUN_RCONST(0.435866521508); - B->A[3][0] = SUN_RCONST(0.416349501547); - B->A[3][1] = SUN_RCONST(0.190984004184); - B->A[3][2] = SUN_RCONST(-0.118643265417); - B->A[3][3] = SUN_RCONST(0.435866521508); - B->A[4][0] = SUN_RCONST(0.896869652944); - B->A[4][1] = SUN_RCONST(0.0182725272734); - B->A[4][2] = SUN_RCONST(-0.0845900310706); - B->A[4][3] = SUN_RCONST(-0.266418670647); - B->A[4][4] = SUN_RCONST(0.435866521508); - - B->b[0] = SUN_RCONST(0.896869652944); - B->b[1] = SUN_RCONST(0.0182725272734); - B->b[2] = SUN_RCONST(-0.0845900310706); - B->b[3] = SUN_RCONST(-0.266418670647); - B->b[4] = SUN_RCONST(0.435866521508); - - B->d[0] = SUN_RCONST(0.776691932910); - B->d[1] = SUN_RCONST(0.0297472791484); - B->d[2] = SUN_RCONST(-0.0267440239074); - B->d[3] = SUN_RCONST(0.220304811849); - - B->c[0] = SUN_RCONST(0.435866521508); + B->A[0][0] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[1][0] = SUN_RCONST(-1.135866521508458999416019451193556842529); + B->A[1][1] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[2][0] = SUN_RCONST(1.085433306501187798233740932177548948256); + B->A[2][1] = SUN_RCONST(-0.7212998280096467976497603833711057907848); + B->A[2][2] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[3][0] = SUN_RCONST(0.4163495015787799872439975203112232915822); + B->A[3][1] = SUN_RCONST(0.1909840041795561340637290424182710083545); + B->A[3][2] = SUN_RCONST(-0.1186432654601150605249854908172545332519); + B->A[3][3] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[4][0] = SUN_RCONST(0.8968696529704295827357809984030487598656); + B->A[4][1] = SUN_RCONST(0.01827252727396890379954420931708867645445); + B->A[4][2] = SUN_RCONST(-0.08459003110197203803096641412326485130547); + B->A[4][3] = SUN_RCONST(-0.2664186706508854479203782447904294275438); + B->A[4][4] = SUN_RCONST(0.4358665215084589994160194511935568425293); + + B->b[0] = SUN_RCONST(0.8968696529704295827357809984030487598656); + B->b[1] = SUN_RCONST(0.01827252727396890379954420931708867645445); + B->b[2] = SUN_RCONST(-0.08459003110197203803096641412326485130547); + B->b[3] = SUN_RCONST(-0.2664186706508854479203782447904294275438); + B->b[4] = SUN_RCONST(0.4358665215084589994160194511935568425293); + + B->d[0] = SUN_RCONST(0.7766919329157524221967851040635650689914); + B->d[1] = SUN_RCONST(0.02974727915032039108861503804581544141749); + B->d[2] = SUN_RCONST(-0.02674402391564096382835552392654800827276); + B->d[3] = SUN_RCONST(0.2203048118495681505429553818171674978639); + + B->c[0] = SUN_RCONST(0.4358665215084589994160194511935568425293); B->c[1] = SUN_RCONST(-0.7); B->c[2] = SUN_RCONST(0.8); - B->c[3] = SUN_RCONST(0.924556761814); + B->c[3] = SUN_RCONST(0.9245567618066800601987605231057966092142); B->c[4] = SUN_RCONST(1.0); return B; }) @@ -391,34 +391,34 @@ ARK_BUTCHER_TABLE(ARKODE_KVAERNO_5_3_4, { /* Kvaerno(5,3,4)-ESDIRK */ ARKodeButcherTable B = ARKodeButcherTable_Alloc(5, SUNTRUE); B->q = 4; B->p = 3; - B->A[1][0] = SUN_RCONST(0.4358665215); - B->A[1][1] = SUN_RCONST(0.4358665215); - B->A[2][0] = SUN_RCONST(0.140737774731968); - B->A[2][1] = SUN_RCONST(-0.108365551378832); - B->A[2][2] = SUN_RCONST(0.4358665215); - B->A[3][0] = SUN_RCONST(0.102399400616089); - B->A[3][1] = SUN_RCONST(-0.376878452267324); - B->A[3][2] = SUN_RCONST(0.838612530151233); - B->A[3][3] = SUN_RCONST(0.4358665215); - B->A[4][0] = SUN_RCONST(0.157024897860995); - B->A[4][1] = SUN_RCONST(0.117330441357768); - B->A[4][2] = SUN_RCONST(0.61667803039168); - B->A[4][3] = SUN_RCONST(-0.326899891110444); - B->A[4][4] = SUN_RCONST(0.4358665215); - - B->b[0] = SUN_RCONST(0.157024897860995); - B->b[1] = SUN_RCONST(0.117330441357768); - B->b[2] = SUN_RCONST(0.61667803039168); - B->b[3] = SUN_RCONST(-0.326899891110444); - B->b[4] = SUN_RCONST(0.4358665215); - - B->d[0] = SUN_RCONST(0.102399400616089); - B->d[1] = SUN_RCONST(-0.376878452267324); - B->d[2] = SUN_RCONST(0.838612530151233); - B->d[3] = SUN_RCONST(0.4358665215); - - B->c[1] = SUN_RCONST(0.871733043); - B->c[2] = SUN_RCONST(0.468238744853136); + B->A[1][0] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[1][1] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[2][0] = SUN_RCONST(0.1407377747247061961864132309262694299296); + B->A[2][1] = SUN_RCONST(-0.1083655513813207999782253192353360264820); + B->A[2][2] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[3][0] = SUN_RCONST(0.1023994006199109976822794150595997362069); + B->A[3][1] = SUN_RCONST(-0.3768784522555561060886970749014278247138); + B->A[3][2] = SUN_RCONST(0.8386125301271861089903982086482712459776); + B->A[3][3] = SUN_RCONST(0.4358665215084589994160194511935568425293); + B->A[4][0] = SUN_RCONST(0.1570248978603249371007885739812418750001); + B->A[4][1] = SUN_RCONST(0.1173304413704388486968184370770592278731); + B->A[4][2] = SUN_RCONST(0.6166780303921214643483881261433096864945); + B->A[4][3] = SUN_RCONST(-0.3268998911313442495620145883951676318970); + B->A[4][4] = SUN_RCONST(0.4358665215084589994160194511935568425293); + + B->b[0] = SUN_RCONST(0.1570248978603249371007885739812418750001); + B->b[1] = SUN_RCONST(0.1173304413704388486968184370770592278731); + B->b[2] = SUN_RCONST(0.6166780303921214643483881261433096864945); + B->b[3] = SUN_RCONST(-0.3268998911313442495620145883951676318970); + B->b[4] = SUN_RCONST(0.4358665215084589994160194511935568425293); + + B->d[0] = SUN_RCONST(0.1023994006199109976822794150595997362069); + B->d[1] = SUN_RCONST(-0.3768784522555561060886970749014278247138); + B->d[2] = SUN_RCONST(0.8386125301271861089903982086482712459776); + B->d[3] = SUN_RCONST(0.4358665215084589994160194511935568425293); + + B->c[1] = SUN_RCONST(0.8717330430169179988320389023871136850586); + B->c[2] = SUN_RCONST(0.4682387448518443956242073628844902459769); B->c[3] = SUN_RCONST(1.0); B->c[4] = SUN_RCONST(1.0); return B; @@ -527,46 +527,46 @@ ARK_BUTCHER_TABLE(ARKODE_KVAERNO_7_4_5, { /* Kvaerno(7,4,5)-ESDIRK */ B->A[1][0] = SUN_RCONST(0.26); B->A[1][1] = SUN_RCONST(0.26); B->A[2][0] = SUN_RCONST(0.13); - B->A[2][1] = SUN_RCONST(0.84033320996790809); + B->A[2][1] = SUN_RCONST(0.8403332099679080963171360487915268154051); B->A[2][2] = SUN_RCONST(0.26); - B->A[3][0] = SUN_RCONST(0.22371961478320505); - B->A[3][1] = SUN_RCONST(0.47675532319799699); - B->A[3][2] = SUN_RCONST(-0.06470895363112615); + B->A[3][0] = SUN_RCONST(0.2237196147832050559163143898290529441991); + B->A[3][1] = SUN_RCONST(0.4767553231979969983278927937270874162429); + B->A[3][2] = SUN_RCONST(-0.06470895363112615133816161180658488282681); B->A[3][3] = SUN_RCONST(0.26); - B->A[4][0] = SUN_RCONST(0.16648564323248321); - B->A[4][1] = SUN_RCONST(0.10450018841591720); - B->A[4][2] = SUN_RCONST(0.03631482272098715); - B->A[4][3] = SUN_RCONST(-0.13090704451073998); + B->A[4][0] = SUN_RCONST(0.1664856432324832152535151725360430044452); + B->A[4][1] = SUN_RCONST(0.1045001884159172041151167240328967362455); + B->A[4][2] = SUN_RCONST(0.03631482272098715161651993758285203251909); + B->A[4][3] = SUN_RCONST(-0.1309070445107399857071749645700052401819); B->A[4][4] = SUN_RCONST(0.26); - B->A[5][0] = SUN_RCONST(0.13855640231268224); - B->A[5][2] = SUN_RCONST(-0.04245337201752043); - B->A[5][3] = SUN_RCONST(0.02446657898003141); - B->A[5][4] = SUN_RCONST(0.61943039072480676); + B->A[5][0] = SUN_RCONST(0.1385564023126822495054973091161581456582); + B->A[5][2] = SUN_RCONST(-0.04245337201752043098884399725982168512523); + B->A[5][3] = SUN_RCONST(0.02446657898003141965963581513879101305561); + B->A[5][4] = SUN_RCONST(0.6194303907248067618237108730048725264114); B->A[5][5] = SUN_RCONST(0.26); - B->A[6][0] = SUN_RCONST(0.13659751177640291); - B->A[6][2] = SUN_RCONST(-0.05496908796538376); - B->A[6][3] = SUN_RCONST(-0.04118626728321046); - B->A[6][4] = SUN_RCONST(0.62993304899016403); - B->A[6][5] = SUN_RCONST(0.06962479448202728); + B->A[6][0] = SUN_RCONST(0.1365975117764029144062783844146127033921); + B->A[6][2] = SUN_RCONST(-0.05496908796538376712487773114648630009105); + B->A[6][3] = SUN_RCONST(-0.04118626728321046868299776958296295741592); + B->A[6][4] = SUN_RCONST(0.6299330489901640319161060392667246534806); + B->A[6][5] = SUN_RCONST(0.06962479448202728948549107704811190063421); B->A[6][6] = SUN_RCONST(0.26); - B->b[0] = SUN_RCONST(0.13659751177640291); - B->b[2] = SUN_RCONST(-0.05496908796538376); - B->b[3] = SUN_RCONST(-0.04118626728321046); - B->b[4] = SUN_RCONST(0.62993304899016403); - B->b[5] = SUN_RCONST(0.06962479448202728); + B->b[0] = SUN_RCONST(0.1365975117764029144062783844146127033921); + B->b[2] = SUN_RCONST(-0.05496908796538376712487773114648630009105); + B->b[3] = SUN_RCONST(-0.04118626728321046868299776958296295741592); + B->b[4] = SUN_RCONST(0.6299330489901640319161060392667246534806); + B->b[5] = SUN_RCONST(0.06962479448202728948549107704811190063421); B->b[6] = SUN_RCONST(0.26); - B->d[0] = SUN_RCONST(0.13855640231268224); - B->d[2] = SUN_RCONST(-0.04245337201752043); - B->d[3] = SUN_RCONST(0.02446657898003141); - B->d[4] = SUN_RCONST(0.61943039072480676); + B->d[0] = SUN_RCONST(0.1385564023126822495054973091161581456582); + B->d[2] = SUN_RCONST(-0.04245337201752043098884399725982168512523); + B->d[3] = SUN_RCONST(0.02446657898003141965963581513879101305561); + B->d[4] = SUN_RCONST(0.6194303907248067618237108730048725264114); B->d[5] = SUN_RCONST(0.26); B->c[1] = SUN_RCONST(0.52); - B->c[2] = SUN_RCONST(1.230333209967908); - B->c[3] = SUN_RCONST(0.895765984350076); - B->c[4] = SUN_RCONST(0.436393609858648); + B->c[2] = SUN_RCONST(1.230333209967908096317136048791526815405); + B->c[3] = SUN_RCONST(0.8957659843500759029060455717495554776153); + B->c[4] = SUN_RCONST(0.4363936098586475852779768695817865330279); B->c[5] = SUN_RCONST(1.0); B->c[6] = SUN_RCONST(1.0); return B; From 166cd2275e1eba689191ea4df92b3fd8d4b5da62 Mon Sep 17 00:00:00 2001 From: Cody Balos Date: Wed, 30 Oct 2024 11:46:08 -0700 Subject: [PATCH 14/89] CI: Enable GitLab CI on Tioga and Dane (#595) --- .gitlab-ci.yml | 203 ++++++++-------- .gitlab/build_and_test.sh | 62 ++--- .gitlab/corona-jobs.yml | 48 ---- .gitlab/corona-templates.yml | 35 --- .gitlab/custom-jobs-and-variables.yml | 84 +++++++ .gitlab/jobs/dane.yml | 66 +++++ .gitlab/jobs/tioga.yml | 92 +++++++ .gitlab/lassen-jobs.yml | 45 ---- .gitlab/lassen-templates.yml | 56 ----- .gitlab/quartz-jobs.yml | 85 ------- .gitlab/quartz-templates.yml | 35 --- .gitlab/radiuss-spack-configs | 2 +- .../netlib-lapack/ibm-xl-3.9.1.patch | 108 --------- .../spack_packages/netlib-lapack/ibm-xl.patch | 53 ---- .../spack_packages/netlib-lapack/package.py | 223 ----------------- .../netlib-lapack/testing.patch | 13 - .../undefined_declarations.patch | 26 -- .gitlab/subscribed-pipelines.yml | 77 ++++++ .gitlab/uberenv | 2 +- .gitmodules | 2 +- .uberenv_config.json | 5 +- cmake/macros/SundialsAddTest.cmake | 46 +++- doc/shared/sundials/Install.rst | 17 ++ .../developers/style_guide/Documentation.rst | 12 + .../source/developers/testing/CI.rst | 226 +++++++++--------- examples/nvector/petsc/CMakeLists.txt | 5 +- examples/sunnonlinsol/petsc/CMakeLists.txt | 7 +- .../petsc/test_sunnonlinsol_petscsnes.c | 1 + ...missing-README-to-examples-cvode-hip.patch | 0 .../sundials/5.5.0-xsdk-patches.patch | 0 .../sundials/FindPackageMultipass.cmake.patch | 0 .../packages}/sundials/nvector-pic.patch | 0 .../spack/packages}/sundials/package.py | 26 +- .../remove-links-to-OpenMP-vector.patch | 0 .../packages}/sundials/sundials-v5.8.0.patch | 0 .../sundials/test_nvector_parhyp.patch | 0 scripts/spack/repo.yaml | 2 + 37 files changed, 642 insertions(+), 1022 deletions(-) delete mode 100644 .gitlab/corona-jobs.yml delete mode 100644 .gitlab/corona-templates.yml create mode 100644 .gitlab/custom-jobs-and-variables.yml create mode 100644 .gitlab/jobs/dane.yml create mode 100644 .gitlab/jobs/tioga.yml delete mode 100644 .gitlab/lassen-jobs.yml delete mode 100644 .gitlab/lassen-templates.yml delete mode 100644 .gitlab/quartz-jobs.yml delete mode 100644 .gitlab/quartz-templates.yml delete mode 100644 .gitlab/spack_packages/netlib-lapack/ibm-xl-3.9.1.patch delete mode 100644 .gitlab/spack_packages/netlib-lapack/ibm-xl.patch delete mode 100644 .gitlab/spack_packages/netlib-lapack/package.py delete mode 100644 .gitlab/spack_packages/netlib-lapack/testing.patch delete mode 100644 .gitlab/spack_packages/netlib-lapack/undefined_declarations.patch create mode 100644 .gitlab/subscribed-pipelines.yml rename {.gitlab/spack_packages => scripts/spack/packages}/sundials/0001-add-missing-README-to-examples-cvode-hip.patch (100%) rename {.gitlab/spack_packages => scripts/spack/packages}/sundials/5.5.0-xsdk-patches.patch (100%) rename {.gitlab/spack_packages => scripts/spack/packages}/sundials/FindPackageMultipass.cmake.patch (100%) rename {.gitlab/spack_packages => scripts/spack/packages}/sundials/nvector-pic.patch (100%) rename {.gitlab/spack_packages => scripts/spack/packages}/sundials/package.py (98%) rename {.gitlab/spack_packages => scripts/spack/packages}/sundials/remove-links-to-OpenMP-vector.patch (100%) rename {.gitlab/spack_packages => scripts/spack/packages}/sundials/sundials-v5.8.0.patch (100%) rename {.gitlab/spack_packages => scripts/spack/packages}/sundials/test_nvector_parhyp.patch (100%) create mode 100644 scripts/spack/repo.yaml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c02b239373..b748728bc2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,6 +1,23 @@ -# --------------------------------------------------------------- +############################################################################### +# Copyright (c) 2022-23, Lawrence Livermore National Security, LLC and RADIUSS +# project contributors. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# SPDX-License-Identifier: (MIT) +############################################################################### +# Modifications to this file have been made under the folllowing copyright. +# ----------------------------------------------------------------------------- # SUNDIALS Copyright Start -# Copyright (c) 2002-2021, Lawrence Livermore National Security +# Copyright (c) 2002-2024, Lawrence Livermore National Security # and Southern Methodist University. # All rights reserved. # @@ -8,129 +25,97 @@ # # SPDX-License-Identifier: BSD-3-Clause # SUNDIALS Copyright End -# --------------------------------------------------------------- +# ----------------------------------------------------------------------------- +# DESCRIPTION: ############################################################################### # General GitLab pipelines configurations for supercomputers and Linux clusters # at Lawrence Livermore National Laboratory (LLNL). -############################################################################### - -# We define the following GitLab pipeline variables (all of which can be -# set from the GitLab CI "run pipeline" UI): -# -# GIT_SUBMODULE_STRATEGY: -# Tells Gitlab to recursively update the submodules when cloning. -# -# ALLOC_NAME: -# Allocation unique name. -# -# BUILD_ROOT: -# The path to the shared resources between all jobs. The BUILD_ROOT is unique to -# the pipeline, preventing any form of concurrency with other pipelines. This -# also means that the BUILD_ROOT directory will never be cleaned. -# -# DEFAULT_TIME: -# Default time to let the jobs run will be 30 minutes. -# -# BUILD_JOBS: -# Number of threads to use for builds. -# -# NCPU: -# Number of CPUs to alloc. +# This entire pipeline is LLNL-specific # -# VERBOSE_BUILD: -# Sets CMAKE_VERBOSE_MAKEFILE to TRUE when "ON". +# Important note: This file is a template provided by llnl/radiuss-shared-ci. +# Remains to set variable values, change the reference to the radiuss-shared-ci +# repo, opt-in and out optional features. The project can then extend it with +# additional stages. # -# VERBOSE_TEST: -# Passes --verbose to CTest when "ON". +# In addition, each project should copy over and complete: +# - .gitlab/custom-jobs-and-variables.yml +# - .gitlab/subscribed-pipelines.yml # -# ON_LASSEN: -# Should the Lassen pipeline run? Set to "ON" or "OFF" to enable/disable. -# -# ON_QUARTZ: -# Should the Quartz pipeline run? Set to "ON" or "OFF" to enable/disable. -# -# SPACK_PREFIX: prefix used for shared spack installation. -# Usually this a spack version number that matches the version set in the uberenv_config.json file. -# Spack installs go in /usr/workspace/sundials/spack_installs/${SPACK_PREFIX}/$(hostname). -# -# SHARED_SPACK: -# If "ON", then a shared spack install that has been pre-configured is utilized. -# If "OFF", then a new spack instance is created for every build (meaning all TPLs have to be installed). -# If "UPSTREAM" (the default), then the shared spack is used as an upstream for a build specific spack. -# -# BENCHMARK: -# If "ON", then the SUNDIALS benchmark problems are run and generate profiles. -# -# BENCHMARK_NNODES: -# Number of nodes to use for benchmarks. Default is 4. -# -# BENCHMARK_QUEUE: -# What queue to submit the benchmarks too. Default is pbatch (for Livermore). +# The jobs should be specified in a file local to the project, +# - .gitlab/jobs/${CI_MACHINE}.yml +# or generated (see LLNL/Umpire for an example). +############################################################################### +# We define the following GitLab pipeline variables: variables: +##### LC GITLAB CONFIGURATION +# Use an LLNL service user to run CI. This prevents from running pipelines as +# an actual user. + LLNL_SERVICE_USER: "" +# Use the service user workspace. Solves permission issues, stores everything +# at the same location whoever triggers a pipeline. + CUSTOM_CI_BUILDS_DIR: "/usr/workspace/sundials/ci/.builds/" +# Tells Gitlab to recursively update the submodules when cloning the project. GIT_SUBMODULE_STRATEGY: recursive - ALLOC_NAME: ${CI_PROJECT_NAME}_ci_${CI_PIPELINE_ID} - BUILD_ROOT: ${CI_PROJECT_DIR} - DEFAULT_TIME: 30 - BUILD_JOBS: 32 - NCPUS: 12 - VERBOSE_BUILD: "OFF" - VERBOSE_TEST: "OFF" - ON_LASSEN: "ON" - ON_QUARTZ: "ON" - ON_CORONA: "ON" - SPACK_PREFIX: "v0.19.1" - SHARED_SPACK: "UPSTREAM" - BENCHMARK: "OFF" - BENCHMARK_NNODES: 4 - BENCHMARK_QUEUE: "pbatch" - -# Normally, stages are blocking in Gitlab. However, using the keyword "needs" we -# can express dependencies between job that break the ordering of stages, in -# favor of a DAG. -# In practice q_*, l_* and c_* stages are independently run and start immediately. -stages: - - q_build_and_test - - l_build_and_test - - l_build_and_bench - - c_build_and_test +##### PROJECT VARIABLES +# We build the projects in the CI clone directory. +# Used in script/gitlab/build_and_test.sh script. +# TODO: add a clean-up mechanism. + BUILD_ROOT: ${CI_PROJECT_DIR} + SPACK_REF: "594a376c521cc746978571b1181a47bbcff30a21" # v0.22.2 -# These are also templates (.name) that define project specific build commands. -# If an allocation exist with the name defined in this pipeline, the job will -# use it (slurm specific). -.build_toss_3_x86_64_ib_script: - script: - - echo ${ALLOC_NAME} - - srun -p pdebug -N 1 -n ${NCPUS} --interactive -t ${DEFAULT_TIME} - --job-name=${ALLOC_NAME} .gitlab/build_and_test.sh +##### SHARED_CI CONFIGURATION +# Required information about GitHub repository + GITHUB_PROJECT_NAME: "sundials" + GITHUB_PROJECT_ORG: "LLNL" +# Set the build-and-test command. +# Nested variables are allowed and useful to customize the job command. We +# prevent variable expansion so that you can define them at job level. + JOB_CMD: + value: ".gitlab/build_and_test.sh" + expand: false +# Override the pattern describing branches that will skip the "draft PR filter +# test". Add protected branches here. See default value in +# preliminary-ignore-draft-pr.yml. +# ALWAYS_RUN_PATTERN: "" -# Corona -.build_toss_4_x86_64_ib_corona_script: - script: - - echo ${ALLOC_NAME} - - flux alloc -N 1 -t ${DEFAULT_TIME} .gitlab/build_and_test.sh +# We organize the build-and-test stage with sub-pipelines. Each sub-pipeline +# corresponds to a test batch on a given machine. -# CORAL systems use spectrum LSF instead of SLURM -.build_blueos_3_ppc64le_ib_script: - script: - - echo ${ALLOC_NAME} - - bsub -q pdebug -J ${ALLOC_NAME} -nnodes 1 -W ${DEFAULT_TIME} -Is .gitlab/build_and_test.sh +# High level stages +stages: + - prerequisites + - build-and-test -# Benchmark job for CORAL systems -.build_blueos_3_ppc64le_ib_bench: - script: - - echo ${ALLOC_NAME} - - bsub -q ${BENCHMARK_QUEUE} -J ${ALLOC_NAME} -nnodes ${BENCHMARK_NNODES} -W ${DEFAULT_TIME} -Is .gitlab/build_and_bench.sh +# Template for jobs triggering a build-and-test sub-pipeline: +.build-and-test: + stage: build-and-test + trigger: + include: + - local: '.gitlab/custom-jobs-and-variables.yml' + - project: 'sundials/radiuss-shared-ci' # https://lc.llnl.gov/gitlab/sundials/radiuss-shared-ci + ref: 'ae1f3786591beed83abc6a0de2229f6e9532e2d4' + file: 'pipelines/${CI_MACHINE}.yml' + # Add your jobs + # you can use a local file + - local: '.gitlab/jobs/${CI_MACHINE}.yml' + # or a file generated in the previous steps + # - artifact: '${CI_MACHINE}-jobs.yml' + # job: 'generate-job-file' + # (See Umpire CI setup for an example). + strategy: depend + forward: + pipeline_variables: true -# This is where jobs are included. include: + # Sets ID tokens for every job using `default:` - project: 'lc-templates/id_tokens' file: 'id_tokens.yml' - - local: .gitlab/quartz-templates.yml - - local: .gitlab/quartz-jobs.yml - - local: .gitlab/lassen-templates.yml - - local: .gitlab/lassen-jobs.yml - - local: .gitlab/corona-templates.yml - - local: .gitlab/corona-jobs.yml + # # [Optional] checks preliminary to running the actual CI test + # - project: 'radiuss/radiuss-shared-ci' + # ref: 'v2024.04.0' + # file: 'utilities/preliminary-ignore-draft-pr.yml' + # pipelines subscribed by the project + - local: '.gitlab/subscribed-pipelines.yml' diff --git a/.gitlab/build_and_test.sh b/.gitlab/build_and_test.sh index cf7ab193fa..04abb537ea 100755 --- a/.gitlab/build_and_test.sh +++ b/.gitlab/build_and_test.sh @@ -20,9 +20,6 @@ job_unique_id=${CI_JOB_ID:-""} sys_type=${SYS_TYPE:-""} py_env_path=${PYTHON_ENVIRONMENT_PATH:-""} -spack_prefix=${SHARED_SPACK_PREFIX:-"v0.19.1"} -shared_spack=${SHARED_SPACK:-"UPSTREAM"} - # Dependencies date @@ -38,7 +35,6 @@ echo "spec = ${spec}" echo "job_unique_id = ${job_unique_id}" echo "sys_type = ${sys_type}" echo "py_env_path = ${py_env_path}" -echo "shared_spack = ${shared_spack}" # remove tailing number from hostname hostname=${hostname%%[0-9]*} @@ -46,19 +42,6 @@ hostname=${hostname%%[0-9]*} # number of parallel build jobs BUILD_JOBS=${BUILD_JOBS:-"1"} -# load newer python to try the clingo concretizer -# machine specific loads -if [[ "${hostname}" == "lassen" ]]; then - echo "module load python/3.8.2" - module load python/3.8.2 -elif [[ "${hostname}" == "corona" ]]; then - echo "module load python/3.9.12" - module load python/3.9.12 -else - echo "module load python" - module load python -fi - if [[ "${option}" != "--build-only" && "${option}" != "--test-only" ]] then echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" @@ -97,35 +80,29 @@ then mkdir -p ${spack_user_cache} fi - if [[ -d /usr/workspace/sundials ]] - then - upstream="/usr/workspace/sundials/spack_installs/${spack_prefix}/${hostname}" - mkdir -p "${upstream}" - upstream_opt="--upstream=${upstream}" - fi + mirror_opt="" + buildcache="/usr/workspace/sundials/ci/spack_stuff/build_caches/${SPACK_REF}" - if [[ "${shared_spack}" == "UPSTREAM" ]] + if [[ ! -d "${buildcache}" ]] then - python3 .gitlab/uberenv/uberenv.py --spec="${spec}" "${prefix_opt}" "${upstream_opt}" - elif [[ "${shared_spack}" == "ON" ]] - then - python3 .gitlab/uberenv/uberenv.py --spec="${spec}" --prefix="${upstream}" - else - python3 .gitlab/uberenv/uberenv.py --spec="${spec}" "${prefix_opt}" + mkdir "${buildcache}" fi - # Ensure correct CUDA module is loaded, only works for module naming - # convention on Lassen. Only needed for CUDA 11 (unclear why). - if [[ -n "${CUDA_SPEC}" ]]; then - cuda_version="${CUDA_SPEC##*@}" - echo "module load cuda/${cuda_version}" - module load cuda/"${cuda_version}" - fi + mirror_opt=("--mirror=${buildcache}" "--mirror-autopush") - module load cmake/3.23 + key_path=/usr/workspace/sundials/ci/spack_stuff/gpg_backup + python3 .gitlab/uberenv/uberenv.py \ + --trust-key ${key_path}/pubring.gpg --trust-key ${key_path}/secring.gpg \ + --spec="${spec}" "${mirror_opt[@]}" "${prefix_opt}" \ + --spack-commit="${SPACK_REF}" fi + date +# Reload the spack environment created by uberenv +. ${prefix}/spack/share/spack/setup-env.sh +spack load + # Host config file if [[ -z ${hostconfig} ]] then @@ -173,6 +150,9 @@ then echo "~ Host-config: ${hostconfig_path}" echo "~ Build Dir: ${build_dir}" echo "~ Project Dir: ${project_dir}" + echo "~ MPIEXEC_EXECUTABLE: ${MPIEXEC_EXECUTABLE}" + echo "~ MPIEXEC_PREFLAGS: ${MPIEXEC_PREFLAGS}" + echo "~ MPIEXEC_POSTFLAGS: ${MPIEXEC_POSTFLAGS}" echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" @@ -195,6 +175,9 @@ then $cmake_exe \ -C "${hostconfig_path}" \ -DCMAKE_INSTALL_PREFIX=${install_dir} \ + -DMPIEXEC_EXECUTABLE=$(which $MPIEXEC_EXECUTABLE) \ + -DMPIEXEC_PREFLAGS=${MPIEXEC_PREFLAGS} \ + -DMPIEXEC_POSTFLAGS=${MPIEXEC_POSTFLAGS} \ -DSUNDIALS_CALIPER_OUTPUT_DIR="${CALIPER_DIR}/Release/${hostname}/${sundials_version}" \ "${project_dir}" @@ -202,6 +185,9 @@ then $cmake_exe \ -C "${hostconfig_path}" \ -DCMAKE_INSTALL_PREFIX=${install_dir} \ + -DMPIEXEC_EXECUTABLE=$(which $MPIEXEC_EXECUTABLE) \ + -DMPIEXEC_PREFLAGS=${MPIEXEC_PREFLAGS} \ + -DMPIEXEC_POSTFLAGS=${MPIEXEC_POSTFLAGS} \ "${project_dir}" fi diff --git a/.gitlab/corona-jobs.yml b/.gitlab/corona-jobs.yml deleted file mode 100644 index f694611c39..0000000000 --- a/.gitlab/corona-jobs.yml +++ /dev/null @@ -1,48 +0,0 @@ -# ------------------------------------------------------------------------------ -# SUNDIALS Copyright Start -# Copyright (c) 2002-2021, Lawrence Livermore National Security -# and Southern Methodist University. -# All rights reserved. -# -# See the top-level LICENSE and NOTICE files for details. -# -# SPDX-License-Identifier: BSD-3-Clause -# SUNDIALS Copyright End -# ------------------------------------------------------------------------------ - -# ------------------------------------------------------------------------------ -# HIP -# ------------------------------------------------------------------------------ - -# Builds with HIP -corona_rocmcc_550: - parallel: - matrix: - - COMPILER_SPEC: rocmcc@5.5.0 - AMDGPU_TARGET: [gfx906] - variables: - SPEC: "%${COMPILER_SPEC} cstd=99 cxxstd=14 precision=double amdgpu_target=${AMDGPU_TARGET} scheduler=flux +rocm+mpi" - extends: .corona_build_and_test - -# ------------------------------------------------------------------------------ -# HIP + TPLs -# ------------------------------------------------------------------------------ -corona_rocmcc_550_tpls: - parallel: - matrix: - - COMPILER_SPEC: rocmcc@5.5.0 - AMDGPU_TARGET: [gfx906] - ROCM_VERSION: 5.5.0 - variables: - SPEC: "%${COMPILER_SPEC} cstd=99 cxxstd=14 precision=double ~int64 amdgpu_target=${AMDGPU_TARGET} scheduler=flux +rocm+mpi+magma+raja+kokkos+kokkos-kernels~ginkgo ^magma+rocm amdgpu_target=${AMDGPU_TARGET} ^raja+rocm~openmp~examples~exercises amdgpu_target=${AMDGPU_TARGET} ^kokkos+rocm~profiling amdgpu_target=${AMDGPU_TARGET} ^hipblas@${ROCM_VERSION} ^hipsparse@${ROCM_VERSION} ^hip@${ROCM_VERSION} ^hsa-rocr-dev@${ROCM_VERSION} ^llvm-amdgpu@${ROCM_VERSION}" - extends: .corona_build_and_test - -corona_rocmcc_523_tpls: - parallel: - matrix: - - COMPILER_SPEC: rocmcc@5.2.3 - AMDGPU_TARGET: [gfx906] - ROCM_VERSION: 5.2.3 - variables: - SPEC: "%${COMPILER_SPEC} cstd=99 cxxstd=14 precision=double ~int64 amdgpu_target=${AMDGPU_TARGET} scheduler=flux +rocm+mpi+magma+raja+kokkos+kokkos-kernels+ginkgo ^magma+rocm amdgpu_target=${AMDGPU_TARGET} ^raja+rocm~openmp~examples~exercises amdgpu_target=${AMDGPU_TARGET} ^kokkos+rocm~profiling amdgpu_target=${AMDGPU_TARGET} ^ginkgo+rocm amdgpu_target=${AMDGPU_TARGET} ^hipblas@${ROCM_VERSION} ^hipsparse@${ROCM_VERSION} ^rocrand@${ROCM_VERSION} ^rocthrust@${ROCM_VERSION} ^hip@${ROCM_VERSION} ^hsa-rocr-dev@${ROCM_VERSION} ^llvm-amdgpu@${ROCM_VERSION} ^rocprim@${ROCM_VERSION}" - extends: .corona_build_and_test diff --git a/.gitlab/corona-templates.yml b/.gitlab/corona-templates.yml deleted file mode 100644 index a901f4fa48..0000000000 --- a/.gitlab/corona-templates.yml +++ /dev/null @@ -1,35 +0,0 @@ -# ------------------------------------------------------------------------------ -# SUNDIALS Copyright Start -# Copyright (c) 2002-2021, Lawrence Livermore National Security -# and Southern Methodist University. -# All rights reserved. -# -# See the top-level LICENSE and NOTICE files for details. -# -# SPDX-License-Identifier: BSD-3-Clause -# SUNDIALS Copyright End -# ------------------------------------------------------------------------------ - -# ------------------------------------------------------------------------------ -# Tags and rules to run tests on Corona -# ------------------------------------------------------------------------------ - -# Generic Corona build job, extending build script for Toss 4 x86_64 Systems -.corona_build_and_test: - tags: - - shell - - corona - extends: [.build_toss_4_x86_64_ib_corona_script] - stage: c_build_and_test - needs: [] - artifacts: - paths: - - spack-*.txt - - build_*/* - when: always - rules: - # Don't run if... - - if: '$CI_COMMIT_BRANCH =~ /_cnone/ || $ON_CORONA == "OFF" || $BENCHMARK == "ON"' - when: never - # Default is to run if previous stage succeeded - - when: on_success diff --git a/.gitlab/custom-jobs-and-variables.yml b/.gitlab/custom-jobs-and-variables.yml new file mode 100644 index 0000000000..1b830e2e3c --- /dev/null +++ b/.gitlab/custom-jobs-and-variables.yml @@ -0,0 +1,84 @@ +############################################################################### +# Copyright (c) 2022-23, Lawrence Livermore National Security, LLC and RADIUSS +# project contributors. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# SPDX-License-Identifier: (MIT) +############################################################################### +# Modifications to this file have been made under the folllowing copyright. +# ----------------------------------------------------------------------------- +# SUNDIALS Copyright Start +# Copyright (c) 2002-2024, Lawrence Livermore National Security +# and Southern Methodist University. +# All rights reserved. +# +# See the top-level LICENSE and NOTICE files for details. +# +# SPDX-License-Identifier: BSD-3-Clause +# SUNDIALS Copyright End +# ----------------------------------------------------------------------------- + +# We define the following GitLab pipeline variables: +variables: +# In some pipelines we create only one allocation shared among jobs in +# order to save time and resources. This allocation has to be uniquely +# named so that we are sure to retrieve it and avoid collisions. + ALLOC_NAME: ${CI_PROJECT_NAME}_ci_${CI_PIPELINE_ID} + +# Dane +# Arguments for top level allocation + DANE_SHARED_ALLOC: "--exclusive --reservation=ci --time=60 --nodes=1" +# Arguments for job level allocation + DANE_JOB_ALLOC: "--time=55 --nodes=1 --overlap" +# Add variables that should apply to all the jobs on a machine: +# DANE_MY_VAR: "..." + +# Tioga +# Arguments for top level allocation + TIOGA_SHARED_ALLOC: "--exclusive --queue pci --time-limit=60m --nodes=1" +# Arguments for job level allocation + TIOGA_JOB_ALLOC: "--time-limit=55m --nodes=1" +# Add variables that should apply to all the jobs on a machine: +# TIOGA_MY_VAR: "..." + +# Number of threads to use for builds. + BUILD_JOBS: 32 + +# Sets CMAKE_VERBOSE_MAKEFILE to TRUE when "ON". + VERBOSE_BUILD: "ON" + +# Passes --verbose to CTest when "ON". + VERBOSE_TEST: "ON" + +# Should the Dane pipeline run? Set to "ON" or "OFF" to enable/disable. + ON_DANE: "ON" + +# Should the Tioga pipeline run? Set to "ON" or "OFF" to enable/disable. + ON_TIOGA: "ON" + +# If "ON", then the SUNDIALS benchmark problems are run and generate profiles. + BENCHMARK: "OFF" + +# Number of nodes to use for benchmarks. Default is 4. + BENCHMARK_NNODES: 4 + +# What queue to submit the benchmarks too. Default is pbatch (for Livermore). + BENCHMARK_QUEUE: "pbatch" + +# Configuration shared by build and test jobs specific to this project. +# Not all configuration can be shared. Here projects can fine tune the +# CI behavior. +# See Umpire for an example (export junit test reports). +.custom_job: + variables: + SPACK_DISABLE_LOCAL_CONFIG: "true" + SPACK_USER_CACHE_PATH: /tmp/spack diff --git a/.gitlab/jobs/dane.yml b/.gitlab/jobs/dane.yml new file mode 100644 index 0000000000..bcb31c8bc8 --- /dev/null +++ b/.gitlab/jobs/dane.yml @@ -0,0 +1,66 @@ +############################################################################## +# Copyright (c) 2022-24, Lawrence Livermore National Security, LLC and RADIUSS +# project contributors. See the COPYRIGHT file for details. +# +# SPDX-License-Identifier: (MIT) +############################################################################## +# ------------------------------------------------------------------------------ +# SUNDIALS Copyright Start +# Copyright (c) 2002-2024, Lawrence Livermore National Security +# and Southern Methodist University. +# All rights reserved. +# +# See the top-level LICENSE and NOTICE files for details. +# +# SPDX-License-Identifier: BSD-3-Clause +# SUNDIALS Copyright End +# ------------------------------------------------------------------------------ + +########################################## +# Overridden shared radiuss-shared-ci jobs +########################################## + +# We duplicate the shared jobs description and add necessary changes for this +# project. We keep ${PROJECT__VARIANTS} and ${PROJECT__DEPS} +# So that the comparison with the original job is easier. + +# No overridden jobs so far. + +######################## +# Extra jobs +######################## + +.sundials_job_on_dane: + variables: + MPIEXEC_EXECUTABLE: "srun" + extends: [.custom_job, .job_on_dane] + +dane_clang_tpls: + parallel: + matrix: + - COMPILER_SPEC: clang@14.0.6 + INDEX_SPEC: [~int64] + PRECISION_SPEC: [double] + variables: + SPEC: "%${COMPILER_SPEC} cstd=99 cxxstd=14 ${INDEX_SPEC} precision=${PRECISION_SPEC} +f2003+mpi+openmp+hypre+superlu-dist+lapack+klu+petsc+ginkgo+kokkos+kokkos-kernels~trilinos ^openblas" + extends: .sundials_job_on_dane + +dane_gcc_tpls: + parallel: + matrix: + - COMPILER_SPEC: gcc@10.3.1 + INDEX_SPEC: [~int64] + PRECISION_SPEC: [double] + variables: + SPEC: "%${COMPILER_SPEC} cstd=99 cxxstd=14 ${INDEX_SPEC} precision=${PRECISION_SPEC} +f2003+mpi+openmp+hypre+superlu-dist+lapack+klu+petsc+ginkgo+kokkos+kokkos-kernels~trilinos ^netlib-lapack" + extends: .sundials_job_on_dane + +dane_intel_tpls: + parallel: + matrix: + - COMPILER_SPEC: intel@2023.2.1 + INDEX_SPEC: [~int64] + PRECISION_SPEC: [double] + variables: + SPEC: "%${COMPILER_SPEC} cstd=99 cxxstd=14 ${INDEX_SPEC} precision=${PRECISION_SPEC} ~f2003+mpi+openmp+hypre+superlu-dist+lapack~klu+petsc+ginkgo+kokkos+kokkos-kernels~trilinos ^intel-oneapi-mkl" + extends: .sundials_job_on_dane diff --git a/.gitlab/jobs/tioga.yml b/.gitlab/jobs/tioga.yml new file mode 100644 index 0000000000..3a38476cca --- /dev/null +++ b/.gitlab/jobs/tioga.yml @@ -0,0 +1,92 @@ +############################################################################## +# Copyright (c) 2022-24, Lawrence Livermore National Security, LLC and RADIUSS +# project contributors. See the COPYRIGHT file for details. +# +# SPDX-License-Identifier: (MIT) +############################################################################## +# ------------------------------------------------------------------------------ +# SUNDIALS Copyright Start +# Copyright (c) 2002-2024, Lawrence Livermore National Security +# and Southern Methodist University. +# All rights reserved. +# +# See the top-level LICENSE and NOTICE files for details. +# +# SPDX-License-Identifier: BSD-3-Clause +# SUNDIALS Copyright End +# ------------------------------------------------------------------------------ + +########################################## +# Overridden shared radiuss-shared-ci jobs +########################################## + +# We duplicate the shared jobs description and add necessary changes for this +# project. We keep ${PROJECT__VARIANTS} and ${PROJECT__DEPS} +# So that the comparison with the original job is easier. + +# No overridden jobs so far. + +######################## +# Extra jobs +######################## + +.sundials_job_on_tioga: + variables: + MPIEXEC_EXECUTABLE: "flux" + MPIEXEC_PREFLAGS: "run" + extends: [.custom_job, .job_on_tioga] + +# --- Builds with HIP + +# Builds fine but non-mpi tests fail to execute due to a missing so: +# error while loading shared libraries: libpgmath.so: cannot open shared object file: No such file or directory +# This seems like it might be an LC environment issue, so disabling the job for now. +tioga_rocmcc_571_tpls: + parallel: + matrix: + - COMPILER_SPEC: rocmcc@5.7.1 + AMDGPU_TARGET: [gfx90a] + variables: + ON_TIOGA: "OFF" # disable until we can figure out libpgmath.so error + # have to use ginkgo@master because our spack version does not have ginkgo@1.8.0: yet (which seems to be needed) + SPEC: "%${COMPILER_SPEC} cstd=99 cxxstd=14 precision=double amdgpu_target=${AMDGPU_TARGET} +rocm+mpi+magma+ginkgo+kokkos ^magma+rocm amdgpu_target=${AMDGPU_TARGET} ^ginkgo@master+rocm amdgpu_target=${AMDGPU_TARGET} ^kokkos+rocm amdgpu_target=${AMDGPU_TARGET}" + before_script: + - module load rocmcc/5.7.1-magic + extends: [.sundials_job_on_tioga] + +tioga_rocmcc_620_tpls: + parallel: + matrix: + - COMPILER_SPEC: rocmcc@6.2.0 + AMDGPU_TARGET: [gfx90a] + variables: + # have to use ginkgo@master because our spack version does not have ginkgo@1.8.0: yet (which seems to be needed) + # similarly, we need a newer magma than available to compile with 'rocm@6:' so we turn it off + SPEC: "%${COMPILER_SPEC} cstd=99 cxxstd=14 precision=double amdgpu_target=${AMDGPU_TARGET} +rocm+mpi~magma+ginkgo+kokkos ^ginkgo@master+rocm amdgpu_target=${AMDGPU_TARGET} ^kokkos+rocm amdgpu_target=${AMDGPU_TARGET}" + before_script: + - module load rocmcc/6.2.0-magic + extends: [.sundials_job_on_tioga] + +# --- Builds without HIP + +tioga_cce_1800_mpi_only: + parallel: + matrix: + - COMPILER_SPEC: cce@18.0.0 + variables: + SPEC: "%${COMPILER_SPEC} cstd=99 cxxstd=14 precision=double +mpi" + extends: [.sundials_job_on_tioga] + + +# --- Benchmark jobs + +tioga_rocmcc_620_benchmark: + parallel: + matrix: + - COMPILER_SPEC: rocmcc@6.2.0 + AMDGPU_TARGET: [gfx90a] + CALIPER_DIR: /usr/workspace/sundials/ci/performance/califiles + variables: + ON_TIOGA: "OFF" # disable until we re-baseline on Tioga + SPEC: "%${COMPILER_SPEC} cstd=99 cxxstd=14 build_type=Release precision=double scheduler=flux caliper-dir=${CALIPER_DIR} ~int64 +benchmarks+profiling+caliper+adiak+mpi+openmp+rocm+raja amdgpu_target=${AMDGPU_TARGET} ^raja+rocm~openmp~examples~exercises amdgpu_target=${AMDGPU_TARGET} ^caliper+adiak+rocm amdgpu_target=${AMDGPU_TARGET}" + extends: [.sundials_job_on_tioga] diff --git a/.gitlab/lassen-jobs.yml b/.gitlab/lassen-jobs.yml deleted file mode 100644 index 1ffca71d46..0000000000 --- a/.gitlab/lassen-jobs.yml +++ /dev/null @@ -1,45 +0,0 @@ -# ------------------------------------------------------------------------------ -# SUNDIALS Copyright Start -# Copyright (c) 2002-2021, Lawrence Livermore National Security -# and Southern Methodist University. -# All rights reserved. -# -# See the top-level LICENSE and NOTICE files for details. -# -# SPDX-License-Identifier: BSD-3-Clause -# SUNDIALS Copyright End -# ------------------------------------------------------------------------------ - -# Builds with CUDA, RAJA and other TPLs -lassen_cuda_no_tpls: - parallel: - matrix: - - COMPILER_SPEC: [xl@16.1.1.14] - CUDA_SPEC: [cuda@10.1.243] - variables: - SPEC: "%${COMPILER_SPEC} cstd=99 cxxstd=14 precision=double ~int64 +mpi+openmp+cuda~raja~magma~superlu-dist~petsc~hypre~ginkgo cuda_arch=70 ^${CUDA_SPEC}+allow-unsupported-compilers" - extends: .lassen_build_and_test - -lassen_gcc_cuda_tpls: - parallel: - matrix: - - COMPILER_SPEC: gcc@8.3.1 - CUDA_SPEC: [cuda@11.8.0] - variables: - SPEC: "%${COMPILER_SPEC} cstd=99 cxxstd=14 precision=double ~int64 +mpi+openmp+cuda+raja+magma+superlu-dist+petsc+hypre+ginkgo cuda_arch=70 ^ginkgo+cuda cuda_arch=70 ^hypre~cuda ^petsc~cuda ^superlu-dist+cuda cuda_arch=70 ^magma+cuda cuda_arch=70 ^raja+cuda~openmp~examples~exercises cuda_arch=70 ^${CUDA_SPEC}+allow-unsupported-compilers" - extends: .lassen_build_and_test - -# ------------------------------------------------------------------------------ -# Benchmark jobs -# ------------------------------------------------------------------------------ - -lassen_gcc_cuda_bench: - parallel: - matrix: - - COMPILER_SPEC: gcc@8.3.1 - CUDA_SPEC: [cuda@11.8.0] - CALIPER_DIR: /usr/workspace/sundials/califiles - variables: - SPEC: "%${COMPILER_SPEC} cstd=99 cxxstd=14 build_type=Release precision=double scheduler=lsf caliper-dir=${CALIPER_DIR} ~int64 +benchmarks+profiling+caliper+adiak+mpi+openmp+cuda+raja cuda_arch=70 ^raja+cuda~openmp~examples~exercises cuda_arch=70 ^caliper+adiak+cuda cuda_arch=70 ^${CUDA_SPEC}+allow-unsupported-compilers" - extends: .lassen_build_and_bench - diff --git a/.gitlab/lassen-templates.yml b/.gitlab/lassen-templates.yml deleted file mode 100644 index 450a3134c2..0000000000 --- a/.gitlab/lassen-templates.yml +++ /dev/null @@ -1,56 +0,0 @@ -# ------------------------------------------------------------------------------ -# SUNDIALS Copyright Start -# Copyright (c) 2002-2021, Lawrence Livermore National Security -# and Southern Methodist University. -# All rights reserved. -# -# See the top-level LICENSE and NOTICE files for details. -# -# SPDX-License-Identifier: BSD-3-Clause -# SUNDIALS Copyright End -# ------------------------------------------------------------------------------ - -# ------------------------------------------------------------------------------ -# Tags and rules to run tests on Lassen -# ------------------------------------------------------------------------------ - -# Generic lassen build job, extending build script for IBM P9 systems -.lassen_build_and_test: - tags: - - shell - - lassen - extends: [.build_blueos_3_ppc64le_ib_script] - stage: l_build_and_test - needs: [] - artifacts: - paths: - - spack-*.txt - - build_*/* - when: always - rules: - # Don't run if... - - if: '$CI_COMMIT_BRANCH =~ /_lnone/ || $ON_LASSEN == "OFF" || $BENCHMARK == "ON"' - when: never - # Default is to run if previous stage succeeded - - when: on_success - -.lassen_build_and_bench: - tags: - - shell - - lassen - extends: [.build_blueos_3_ppc64le_ib_bench] - stage: l_build_and_bench - needs: [] - artifacts: - paths: - - spack-*.txt - - build_*/* - - '*.cali' - when: always - expire_in: never - rules: - # Don't run if... - - if: '$CI_COMMIT_BRANCH =~ /_lnone/ || $ON_LASSEN == "OFF" || $BENCHMARK == "OFF"' - when: never - # Default is to run if previous stage succeeded - - when: on_success diff --git a/.gitlab/quartz-jobs.yml b/.gitlab/quartz-jobs.yml deleted file mode 100644 index a0c96755a6..0000000000 --- a/.gitlab/quartz-jobs.yml +++ /dev/null @@ -1,85 +0,0 @@ -# --------------------------------------------------------------- -# SUNDIALS Copyright Start -# Copyright (c) 2002-2021, Lawrence Livermore National Security -# and Southern Methodist University. -# All rights reserved. -# -# See the top-level LICENSE and NOTICE files for details. -# -# SPDX-License-Identifier: BSD-3-Clause -# SUNDIALS Copyright End -# --------------------------------------------------------------- - -# ------------------------------------------------------------------------------ -# Basic builds w/o TPLs -# ------------------------------------------------------------------------------ -### Builds without TPLs -# How to easily add +f2003 when int64 and double? - -# quartz_clang: -# parallel: -# matrix: -# - COMPILER_SPEC: clang@12.0.0 -# INDEX_SPEC: [~int64, +int64] -# PRECISION_SPEC: [double] -# variables: -# SPEC: "%${COMPILER_SPEC} ${INDEX_SPEC} precision=${PRECISION_SPEC}" -# extends: .quartz_build_and_test - -# quartz_gcc: -# parallel: -# matrix: -# - COMPILER_SPEC: gcc@10.3.1 -# INDEX_SPEC: [~int64, +int64] -# PRECISION_SPEC: [double] -# variables: -# SPEC: "%${COMPILER_SPEC} ${INDEX_SPEC} precision=${PRECISION_SPEC}" -# extends: .quartz_build_and_test - -# quartz_intel: -# parallel: -# matrix: -# - COMPILER_SPEC: intel@19.1.2 -# INDEX_SPEC: [~int64, +int64] -# PRECISION_SPEC: [double] -# variables: -# SPEC: "%${COMPILER_SPEC} ${INDEX_SPEC} precision=${PRECISION_SPEC}" -# extends: .quartz_build_and_test - -# ------------------------------------------------------------------------------ -# Builds with TPLs -# ------------------------------------------------------------------------------ -# +petsc ~hypre ~superlu-dist ~int64 ~hdf5 -# +superlu-dist == segfaults - -quartz_clang_tpls: - parallel: - matrix: - - COMPILER_SPEC: clang@14.0.6 - INDEX_SPEC: [~int64] - PRECISION_SPEC: [double] - variables: - SPEC: "%${COMPILER_SPEC} cstd=99 cxxstd=14 ${INDEX_SPEC} precision=${PRECISION_SPEC} +mpi +openmp +hypre +superlu-dist +lapack +klu +petsc ^suite-sparse@5.13.0 ^openblas" - extends: .quartz_build_and_test - -quartz_gcc_tpls: - parallel: - matrix: - - COMPILER_SPEC: gcc@10.3.1 - INDEX_SPEC: [~int64] - PRECISION_SPEC: [double] - variables: - # For some reason nvhpc gets picked up for lapack w/o ^openblas - SPEC: "%${COMPILER_SPEC} cstd=99 cxxstd=14 ${INDEX_SPEC} precision=${PRECISION_SPEC} +mpi +openmp +hypre +superlu-dist +lapack +klu +petsc ^suite-sparse@5.13.0 ^openblas" - extends: .quartz_build_and_test - -quartz_intel_tpls: - parallel: - matrix: - - COMPILER_SPEC: intel@19.1.2 - INDEX_SPEC: [~int64] - PRECISION_SPEC: [double] - variables: - # perl@5.32.0 needed until spack v0.20.0: https://github.com/spack/spack/pull/35666 - SPEC: "%${COMPILER_SPEC} cstd=99 cxxstd=14 ${INDEX_SPEC} precision=${PRECISION_SPEC} +mpi +openmp +hypre ~superlu-dist +lapack +klu ^suite-sparse@5.13.0 ^perl@5.32.0" - extends: .quartz_build_and_test diff --git a/.gitlab/quartz-templates.yml b/.gitlab/quartz-templates.yml deleted file mode 100644 index bfc33a3fd5..0000000000 --- a/.gitlab/quartz-templates.yml +++ /dev/null @@ -1,35 +0,0 @@ -# ------------------------------------------------------------------------------ -# SUNDIALS Copyright Start -# Copyright (c) 2002-2021, Lawrence Livermore National Security -# and Southern Methodist University. -# All rights reserved. -# -# See the top-level LICENSE and NOTICE files for details. -# -# SPDX-License-Identifier: BSD-3-Clause -# SUNDIALS Copyright End -# ------------------------------------------------------------------------------ - -# ------------------------------------------------------------------------------ -# Tags and rules to run tests on Quartz -# ------------------------------------------------------------------------------ - -# Generic quartz build job, extending build script -.quartz_build_and_test: - tags: - - shell - - quartz - extends: [.build_toss_3_x86_64_ib_script] - stage: q_build_and_test - needs: [] - artifacts: - paths: - - spack-*.txt - - build_*/* - when: always - rules: - # Don't run if... - - if: '$CI_COMMIT_BRANCH =~ /_lnone/ || $ON_QUARTZ == "OFF" || $BENCHMARK == "ON"' - when: never - # Default is to run if previous stage succeeded - - when: on_success diff --git a/.gitlab/radiuss-spack-configs b/.gitlab/radiuss-spack-configs index 1264a6db12..89c2074e46 160000 --- a/.gitlab/radiuss-spack-configs +++ b/.gitlab/radiuss-spack-configs @@ -1 +1 @@ -Subproject commit 1264a6db12f451153a5cb22a32a1b7ba2faa5fc2 +Subproject commit 89c2074e466d454c77ec17249cbdf8555d183388 diff --git a/.gitlab/spack_packages/netlib-lapack/ibm-xl-3.9.1.patch b/.gitlab/spack_packages/netlib-lapack/ibm-xl-3.9.1.patch deleted file mode 100644 index c9e1707857..0000000000 --- a/.gitlab/spack_packages/netlib-lapack/ibm-xl-3.9.1.patch +++ /dev/null @@ -1,108 +0,0 @@ -Fixes for IBM XL and Cray CCE builds: - -* Correct path to the fallback configuration used to handle mangling for - C++/Fortran compatibility (CCE, XL) - -* Change logic for detecting recursive fortran flags to (a) Include XL -(qrecur), and (b) Be explicit, since not every compiler will correctly reject -an incorrect option (ALL) - -NOTE: This patch has been accepted upstream -(see https://github.com/Reference-LAPACK/lapack/pull/621) - -############################################################################## - -diff -Naur a/CBLAS/CMakeLists.txt b/CBLAS/CMakeLists.txt ---- a/CBLAS/CMakeLists.txt 2021-03-25 12:25:15.000000000 -0600 -+++ b/CBLAS/CMakeLists.txt 2021-09-01 16:27:23.561355382 -0600 -@@ -11,9 +11,7 @@ - MACRO_NAMESPACE "F77_" - SYMBOL_NAMESPACE "F77_") - if(NOT FortranCInterface_GLOBAL_FOUND OR NOT FortranCInterface_MODULE_FOUND) -- message(WARNING "Reverting to pre-defined include/lapacke_mangling.h") -- configure_file(include/lapacke_mangling_with_flags.h.in -- ${LAPACK_BINARY_DIR}/include/lapacke_mangling.h) -+ message(WARNING "Reverting to pre-defined include/cblas_mangling.h") - configure_file(include/cblas_mangling_with_flags.h.in - ${LAPACK_BINARY_DIR}/include/cblas_mangling.h) - endif() -diff -Naur a/CMakeLists.txt b/CMakeLists.txt ---- a/CMakeLists.txt 2021-03-25 12:25:15.000000000 -0600 -+++ b/CMakeLists.txt 2021-09-02 09:49:18.070436958 -0600 -@@ -94,16 +94,22 @@ - - # Check if recursive flag exists - include(CheckFortranCompilerFlag) --check_fortran_compiler_flag("-recursive" _recursiveFlag) --check_fortran_compiler_flag("-frecursive" _frecursiveFlag) --check_fortran_compiler_flag("-Mrecursive" _MrecursiveFlag) -+if(CMAKE_Fortran_COMPILER_ID STREQUAL Flang) -+ check_fortran_compiler_flag("-Mrecursive" _MrecursiveFlag) -+elseif(CMAKE_Fortran_COMPILER_ID STREQUAL GNU) -+ check_fortran_compiler_flag("-frecursive" _frecursiveFlag) -+elseif(CMAKE_Fortran_COMPILER_ID STREQUAL Intel) -+ check_fortran_compiler_flag("-recursive" _recursiveFlag) -+elseif(CMAKE_Fortran_COMPILER_ID STREQUAL XL) -+ check_fortran_compiler_flag("-qrecur" _qrecurFlag) -+endif() - - # Add recursive flag --if(_recursiveFlag) -- string(REGEX MATCH "-recursive" output_test "${CMAKE_Fortran_FLAGS}") -+if(_MrecursiveFlag) -+ string(REGEX MATCH "-Mrecursive" output_test "${CMAKE_Fortran_FLAGS}") - if(NOT output_test) -- set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -recursive" -- CACHE STRING "Recursive flag must be set" FORCE) -+ set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -Mrecursive" -+ CACHE STRING "Recursive flag must be set" FORCE) - endif() - elseif(_frecursiveFlag) - string(REGEX MATCH "-frecursive" output_test "${CMAKE_Fortran_FLAGS}") -@@ -111,11 +117,17 @@ - set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -frecursive" - CACHE STRING "Recursive flag must be set" FORCE) - endif() --elseif(_MrecursiveFlag) -- string(REGEX MATCH "-Mrecursive" output_test "${CMAKE_Fortran_FLAGS}") -+elseif(_recursiveFlag) -+ string(REGEX MATCH "-recursive" output_test "${CMAKE_Fortran_FLAGS}") - if(NOT output_test) -- set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -Mrecursive" -- CACHE STRING "Recursive flag must be set" FORCE) -+ set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -recursive" -+ CACHE STRING "Recursive flag must be set" FORCE) -+ endif() -+elseif(_qrecurFlag) -+ string(REGEX MATCH "-qrecur" output_test "${CMAKE_Fortran_FLAGS}") -+ if(NOT output_test) -+ set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -qrecur" -+ CACHE STRING "Recursive flag must be set" FORCE) - endif() - endif() - -@@ -124,7 +136,7 @@ - set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fp-model strict") - endif() - if(CMAKE_Fortran_COMPILER_ID STREQUAL XL) -- set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -qnosave -qstrict=none") -+ set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -qnosave -qstrict") - endif() - # Delete libmtsk in linking sequence for Sun/Oracle Fortran Compiler. - # This library is not present in the Sun package SolarisStudio12.3-linux-x86-bin -diff -Naur a/INSTALL/make.inc.XLF b/INSTALL/make.inc.XLF ---- a/INSTALL/make.inc.XLF 2021-03-25 12:25:15.000000000 -0600 -+++ b/INSTALL/make.inc.XLF 2021-09-02 09:50:02.664646455 -0600 -@@ -14,10 +14,10 @@ - # the compiler options desired when NO OPTIMIZATION is selected. - # - FC = xlf --FFLAGS = -O3 -qfixed -qnosave -+FFLAGS = -O3 -qfixed -qnosave -qrecur - # For -O2, add -qstrict=none - FFLAGS_DRV = $(FFLAGS) --FFLAGS_NOOPT = -O0 -qfixed -qnosave -+FFLAGS_NOOPT = -O0 -qfixed -qnosave -qrecur - - # Define LDFLAGS to the desired linker options for your machine. - # diff --git a/.gitlab/spack_packages/netlib-lapack/ibm-xl.patch b/.gitlab/spack_packages/netlib-lapack/ibm-xl.patch deleted file mode 100644 index 52b5f19719..0000000000 --- a/.gitlab/spack_packages/netlib-lapack/ibm-xl.patch +++ /dev/null @@ -1,53 +0,0 @@ -Fixes for IBM XL and Cray CCE builds: - -* Avoid optimizations that would alter program semantics by changing the - qstrict activation threshold from O3 to O2 (XL) - -* Don't assume Fortran code is all in fixed source form; disable qfixed (XL) - -* Correct path to the fallback configuration used to handle mangling for - C++/Fortran compatibility (CCE, XL) -############################################################################## - ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -62,7 +62,7 @@ - set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fp-model strict") - endif() - if("${CMAKE_Fortran_COMPILER}" MATCHES "xlf") -- set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -qnosave -qstrict=none") -+ set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -qnosave -qstrict") - endif() - # Delete libmtsk in linking sequence for Sun/Oracle Fortran Compiler. - # This library is not present in the Sun package SolarisStudio12.3-linux-x86-bin - ---- a/CMAKE/CheckLAPACKCompilerFlags.cmake -+++ b/CMAKE/CheckLAPACKCompilerFlags.cmake -@@ -43,12 +43,6 @@ - if( "${CMAKE_Fortran_FLAGS}" MATCHES "-qflttrap=[a-zA-Z:]:enable" ) - set( FPE_EXIT TRUE ) - endif() -- -- if( NOT ("${CMAKE_Fortran_FLAGS}" MATCHES "-qfixed") ) -- message( STATUS "Enabling fixed format F90/F95 with -qfixed" ) -- set( CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -qfixed" -- CACHE STRING "Flags for Fortran compiler." FORCE ) -- endif() - - # HP Fortran - elseif( CMAKE_Fortran_COMPILER_ID STREQUAL "HP" ) - ---- a/CBLAS/CMakeLists.txt -+++ b/CBLAS/CMakeLists.txt -@@ -12,8 +12,8 @@ - SYMBOL_NAMESPACE "F77_") - if(NOT FortranCInterface_GLOBAL_FOUND OR NOT FortranCInterface_MODULE_FOUND) - message(WARNING "Reverting to pre-defined include/lapacke_mangling.h") -- configure_file(include/lapacke_mangling_with_flags.h.in -- ${LAPACK_BINARY_DIR}/include/lapacke_mangling.h) -+ configure_file(include/cblas_mangling_with_flags.h.in -+ ${LAPACK_BINARY_DIR}/include/cblas_mangling.h) - endif() - - include_directories(include ${LAPACK_BINARY_DIR}/include) - diff --git a/.gitlab/spack_packages/netlib-lapack/package.py b/.gitlab/spack_packages/netlib-lapack/package.py deleted file mode 100644 index cb1832d061..0000000000 --- a/.gitlab/spack_packages/netlib-lapack/package.py +++ /dev/null @@ -1,223 +0,0 @@ -# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other -# Spack Project Developers. See the top-level COPYRIGHT file for details. -# -# SPDX-License-Identifier: (Apache-2.0 OR MIT) -import spack.build_systems.cmake -from spack.package import * - - -class NetlibLapack(CMakePackage): - """LAPACK version 3.X is a comprehensive FORTRAN library that does - linear algebra operations including matrix inversions, least squared - solutions to linear sets of equations, eigenvector analysis, singular - value decomposition, etc. It is a very comprehensive and reputable - package that has found extensive use in the scientific community. - - """ - - homepage = "https://www.netlib.org/lapack/" - url = "https://www.netlib.org/lapack/lapack-3.5.0.tgz" - tags = ["windows"] - - version( - "3.10.1", - sha256="cd005cd021f144d7d5f7f33c943942db9f03a28d110d6a3b80d718a295f7f714", - url="https://github.com/Reference-LAPACK/lapack/archive/refs/tags/v3.10.1.tar.gz", - ) - version( - "3.10.0", - sha256="328c1bea493a32cac5257d84157dc686cc3ab0b004e2bea22044e0a59f6f8a19", - url="https://github.com/Reference-LAPACK/lapack/archive/refs/tags/v3.10.0.tar.gz", - ) - version( - "3.9.1", - sha256="d0085d2caf997ff39299c05d4bacb6f3d27001d25a4cc613d48c1f352b73e7e0", - url="https://github.com/Reference-LAPACK/lapack/archive/refs/tags/v3.9.1.tar.gz", - ) - version( - "3.9.0", - sha256="106087f1bb5f46afdfba7f569d0cbe23dacb9a07cd24733765a0e89dbe1ad573", - url="https://github.com/Reference-LAPACK/lapack/archive/v3.9.0.tar.gz", - ) - version( - "3.8.0", - sha256="deb22cc4a6120bff72621155a9917f485f96ef8319ac074a7afbc68aab88bcf6", - url="https://www.netlib.org/lapack/lapack-3.8.0.tar.gz", - ) - version("3.7.1", sha256="f6c53fd9f56932f3ddb3d5e24c1c07e4cd9b3b08e7f89de9c867125eecc9a1c8") - version("3.7.0", sha256="ed967e4307e986474ab02eb810eed1d1adc73f5e1e3bc78fb009f6fe766db3be") - version("3.6.1", sha256="888a50d787a9d828074db581c80b2d22bdb91435a673b1bf6cd6eb51aa50d1de") - version("3.6.0", sha256="a9a0082c918fe14e377bbd570057616768dca76cbdc713457d8199aaa233ffc3") - version("3.5.0", sha256="9ad8f0d3f3fb5521db49f2dd716463b8fb2b6bc9dc386a9956b8c6144f726352") - version("3.4.2", sha256="60a65daaf16ec315034675942618a2230521ea7adf85eea788ee54841072faf0") - version("3.4.1", sha256="93b910f94f6091a2e71b59809c4db4a14655db527cfc5821ade2e8c8ab75380f") - version("3.4.0", sha256="a7139ef97004d0e3c4c30f1c52d508fd7ae84b5fbaf0dd8e792c167dc306c3e9") - version("3.3.1", sha256="56821ab51c29369a34e5085728f92c549a9aa926f26acf7eeac87b61eed329e4") - - # netlib-lapack is the reference implementation of LAPACK - for ver in [ - "3.10.1", - "3.10.0", - "3.9.1", - "3.9.0", - "3.8.0", - "3.7.1", - "3.7.0", - "3.6.1", - "3.6.0", - "3.5.0", - "3.4.2", - "3.4.1", - "3.4.0", - "3.3.1", - ]: - provides("lapack@" + ver, when="@" + ver) - - variant("shared", default=True, description="Build shared library version") - variant("external-blas", default=False, description="Build lapack with an external blas") - - variant("lapacke", default=True, description="Activates the build of the LAPACKE C interface") - variant("xblas", default=False, description="Builds extended precision routines using XBLAS") - - # Fixes for IBM XL and Cray CCE builds: - # Avoid optimizations that alter program semantics - # Don't assume fixed source form for Fortran - # Correct path to mangling config - patch("ibm-xl.patch", when="@3.7:3.8 %xl") - patch("ibm-xl.patch", when="@3.7:3.8 %xl_r") - patch("ibm-xl.patch", when="@3.7:3.8 %cce@9:") - - # https://github.com/Reference-LAPACK/lapack/pull/621 - # Fixes for IBM XL and Cray CCE builds: - # Correct path to mangling config - # Fix logic for detecting recursive Fortran flags - patch("ibm-xl-3.9.1.patch", when="@3.9.1 %xl") - patch("ibm-xl-3.9.1.patch", when="@3.9.1 %xl_r") - patch("ibm-xl-3.9.1.patch", when="@3.9.1 %cce@13:") - - # https://github.com/Reference-LAPACK/lapack/issues/228 - patch("undefined_declarations.patch", when="@3.8.0:3.8") - - # https://github.com/Reference-LAPACK/lapack/pull/268 - patch("testing.patch", when="@3.7.0:3.8") - - # virtual dependency - provides("blas", when="~external-blas") - provides("lapack") - - depends_on("blas", when="+external-blas") - depends_on("netlib-xblas+fortran+plain_blas", when="+xblas") - depends_on("python@2.7:", type="test") - - # We need to run every phase twice in order to get static and shared - # versions of the libraries. When ~shared, we run the default - # implementations of the CMakePackage's phases and get only one building - # directory 'spack-build-static' with -DBUILD_SHARED_LIBS:BOOL=OFF (see - # implementations of self.build_directory and self.cmake_args() below). - # When +shared, we run the overridden methods for the phases, each - # running the default implementation twice with different values for - # self._building_shared. As a result, we get two building directories: - # 'spack-build-static' with -DBUILD_SHARED_LIBS:BOOL=OFF and - # 'spack-build-shared' with -DBUILD_SHARED_LIBS:BOOL=ON. - _building_shared = False - - def patch(self): - # Fix cblas CMakeLists.txt -- has wrong case for subdirectory name. - if self.spec.satisfies("@3.6.0:"): - filter_file( - "${CMAKE_CURRENT_SOURCE_DIR}/CMAKE/", - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/", - "CBLAS/CMakeLists.txt", - string=True, - ) - - # Remove duplicate header file that gets generated during CMake shared - # builds: https://github.com/Reference-LAPACK/lapack/issues/583 - if self.spec.satisfies("platform=windows @0:3.9.1"): - force_remove("LAPACKE/include/lapacke_mangling.h") - - @property - def blas_libs(self): - shared = True if "+shared" in self.spec else False - query_parameters = self.spec.last_query.extra_parameters - query2libraries = { - tuple(): ["libblas"], - ("c", "fortran"): ["libcblas", "libblas"], - ("c",): ["libcblas"], - ("fortran",): ["libblas"], - } - key = tuple(sorted(query_parameters)) - libraries = query2libraries[key] - return find_libraries(libraries, root=self.prefix, shared=shared, recursive=True) - - @property - def lapack_libs(self): - shared = True if "+shared" in self.spec else False - query_parameters = self.spec.last_query.extra_parameters - query2libraries = { - tuple(): ["liblapack"], - ("c", "fortran"): ["liblapacke", "liblapack"], - ("c",): ["liblapacke"], - ("fortran",): ["liblapack"], - } - key = tuple(sorted(query_parameters)) - libraries = query2libraries[key] - return find_libraries(libraries, root=self.prefix, shared=shared, recursive=True) - - @property - def headers(self): - include_dir = self.spec.prefix.include - cblas_h = join_path(include_dir, "cblas.h") - lapacke_h = join_path(include_dir, "lapacke.h") - return HeaderList([cblas_h, lapacke_h]) - - -class CMakeBuilder(spack.build_systems.cmake.CMakeBuilder): - def cmake_args(self): - args = [ - self.define_from_variant("BUILD_SHARED_LIBS", "shared"), - self.define_from_variant("LAPACKE", "lapacke"), - self.define_from_variant("LAPACKE_WITH_TMG", "lapacke"), - self.define("CBLAS", self.spec.satisfies("@3.6.0:")), - ] - - if self.spec.satisfies("%intel"): - # Intel compiler finds serious syntax issues when trying to - # build CBLAS and LapackE - args.extend([self.define("CBLAS", False), self.define("LAPACKE", False)]) - - if self.spec.satisfies("%xl") or self.spec.satisfies("%xl_r"): - # use F77 compiler if IBM XL - args.extend( - [ - self.define("CMAKE_Fortran_COMPILER", self.pkg.compiler.f77), - self.define( - "CMAKE_Fortran_FLAGS", - " ".join(self.spec.compiler_flags["fflags"]) + " -O3 -qnohot", - ), - ] - ) - - # deprecated routines are commonly needed by, for example, suitesparse - # Note that OpenBLAS spack is built with deprecated routines - args.append(self.define("BUILD_DEPRECATED", True)) - - if self.spec.satisfies("+external-blas"): - args.extend( - [ - self.define("USE_OPTIMIZED_BLAS", True), - self.define("BLAS_LIBRARIES:PATH", self.spec["blas"].libs.joined(";")), - ] - ) - - if self.spec.satisfies("+xblas"): - args.extend( - [ - self.define("XBLAS_INCLUDE_DIR", self.spec["netlib-xblas"].prefix.include), - self.define("XBLAS_LIBRARY", self.spec["netlib-xblas"].libs.joined(";")), - ] - ) - - args.append(self.define("BUILD_TESTING", self.pkg.run_tests)) - - return args diff --git a/.gitlab/spack_packages/netlib-lapack/testing.patch b/.gitlab/spack_packages/netlib-lapack/testing.patch deleted file mode 100644 index fce18548c4..0000000000 --- a/.gitlab/spack_packages/netlib-lapack/testing.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/TESTING/LIN/alahd.f b/TESTING/LIN/alahd.f -index 8f4cd58d..6a4946e0 100644 ---- a/TESTING/LIN/alahd.f -+++ b/TESTING/LIN/alahd.f -@@ -1036,7 +1036,7 @@ - 9929 FORMAT( ' Test ratios (1-3: ', A1, 'TZRZF):' ) - 9920 FORMAT( 3X, ' 7-10: same as 3-6', 3X, ' 11-14: same as 3-6' ) - 9921 FORMAT( ' Test ratios:', / ' (1-2: ', A1, 'GELS, 3-6: ', A1, -- $ 'GELSY, 7-10: ', A1, 'GELSS, 11-14: ', A1, 'GELSD, 15-16: ' -+ $ 'GELSY, 7-10: ', A1, 'GELSS, 11-14: ', A1, 'GELSD, 15-16: ', - $ A1, 'GETSLS)') - 9928 FORMAT( 7X, 'where ALPHA = ( 1 + SQRT( 17 ) ) / 8' ) - 9927 FORMAT( 3X, I2, ': ABS( Largest element in L )', / 12X, diff --git a/.gitlab/spack_packages/netlib-lapack/undefined_declarations.patch b/.gitlab/spack_packages/netlib-lapack/undefined_declarations.patch deleted file mode 100644 index 9dac2562f7..0000000000 --- a/.gitlab/spack_packages/netlib-lapack/undefined_declarations.patch +++ /dev/null @@ -1,26 +0,0 @@ -diff --git a/SRC/dsytrf_aa_2stage.f b/SRC/dsytrf_aa_2stage.f -index 2991305..f5f06cc 100644 ---- a/SRC/dsytrf_aa_2stage.f -+++ b/SRC/dsytrf_aa_2stage.f -@@ -191,7 +191,7 @@ - EXTERNAL LSAME, ILAENV - * .. - * .. External Subroutines .. -- EXTERNAL XERBLA, DCOPY, DLACGV, DLACPY, -+ EXTERNAL XERBLA, DCOPY, DLACPY, - $ DLASET, DGBTRF, DGEMM, DGETRF, - $ DSYGST, DSWAP, DTRSM - * .. -diff --git a/SRC/ssytrf_aa_2stage.f b/SRC/ssytrf_aa_2stage.f -index be6809d..a929749 100644 ---- a/SRC/ssytrf_aa_2stage.f -+++ b/SRC/ssytrf_aa_2stage.f -@@ -191,7 +191,7 @@ - EXTERNAL LSAME, ILAENV - * .. - * .. External Subroutines .. -- EXTERNAL XERBLA, SCOPY, SLACGV, SLACPY, -+ EXTERNAL XERBLA, SCOPY, SLACPY, - $ SLASET, SGBTRF, SGEMM, SGETRF, - $ SSYGST, SSWAP, STRSM - * .. diff --git a/.gitlab/subscribed-pipelines.yml b/.gitlab/subscribed-pipelines.yml new file mode 100644 index 0000000000..879dcc7be6 --- /dev/null +++ b/.gitlab/subscribed-pipelines.yml @@ -0,0 +1,77 @@ +############################################################################### +# Copyright (c) 2022-23, Lawrence Livermore National Security, LLC and RADIUSS +# project contributors. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# SPDX-License-Identifier: (MIT) +############################################################################### +# Modifications to this file have been made under the folllowing copyright. +# ----------------------------------------------------------------------------- +# SUNDIALS Copyright Start +# Copyright (c) 2002-2024, Lawrence Livermore National Security +# and Southern Methodist University. +# All rights reserved. +# +# See the top-level LICENSE and NOTICE files for details. +# +# SPDX-License-Identifier: BSD-3-Clause +# SUNDIALS Copyright End +# ----------------------------------------------------------------------------- + +# The template job to test whether a machine is up. +# Expects CI_MACHINE defined to machine name. +.machine-check: + stage: prerequisites + tags: [shell, oslic] + variables: + GIT_STRATEGY: none + script: + - | + if [[ $(jq '.[env.CI_MACHINE].total_nodes_up' /usr/global/tools/lorenz/data/loginnodeStatus) == 0 ]] + then + echo -e "\e[31mNo node available on ${CI_MACHINE}\e[0m" + curl --url "https://api.github.com/repos/${GITHUB_PROJECT_ORG}/${GITHUB_PROJECT_NAME}/statuses/${CI_COMMIT_SHA}" \ + --header 'Content-Type: application/json' \ + --header "authorization: Bearer ${GITHUB_TOKEN}" \ + --data "{ \"state\": \"failure\", \"target_url\": \"${CI_PIPELINE_URL}\", \"description\": \"GitLab ${CI_MACHINE} down\", \"context\": \"ci/gitlab/${CI_MACHINE}\" }" + exit 1 + fi + +### +# Trigger a build-and-test pipeline for a machine. +# Comment the jobs for machines you don’t need. +### + +# DANE +dane-up-check: + variables: + CI_MACHINE: "dane" + extends: [.machine-check] + +dane-build-and-test: + variables: + CI_MACHINE: "dane" + needs: [dane-up-check] + extends: [.build-and-test] + +# TIOGA +tioga-up-check: + variables: + CI_MACHINE: "tioga" + extends: [.machine-check] + +tioga-build-and-test: + variables: + CI_MACHINE: "tioga" + needs: [tioga-up-check] + extends: [.build-and-test] + diff --git a/.gitlab/uberenv b/.gitlab/uberenv index 0d00dc8e19..ec6fd144c8 160000 --- a/.gitlab/uberenv +++ b/.gitlab/uberenv @@ -1 +1 @@ -Subproject commit 0d00dc8e19a889ba07ae433590b87533c4b5b3da +Subproject commit ec6fd144c814ce30a6487db9fb8294def606afda diff --git a/.gitmodules b/.gitmodules index 659855b75f..e915f32aa6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -3,7 +3,7 @@ url = https://github.com/sundials-codes/radiuss-spack-configs.git [submodule "uberenv"] path = .gitlab/uberenv - url = https://github.com/LLNL/uberenv.git + url = https://github.com/sundials-codes/uberenv.git [submodule "test/answers"] path = test/answers url = https://github.com/sundials-codes/answers.git diff --git a/.uberenv_config.json b/.uberenv_config.json index 67618cca2f..3264fe5b05 100644 --- a/.uberenv_config.json +++ b/.uberenv_config.json @@ -4,8 +4,7 @@ "package_final_phase": "initconfig", "package_source_dir": "../..", "spack_url": "https://github.com/spack/spack", - "spack_commit": "5e0d2107348eed6cbe6deca43a30f5b06c5e40af", "spack_activate": {}, "spack_configs_path": ".gitlab/radiuss-spack-configs", - "spack_packages_path": ".gitlab/spack_packages" -} + "spack_packages_path": "scripts/spack/packages" +} \ No newline at end of file diff --git a/cmake/macros/SundialsAddTest.cmake b/cmake/macros/SundialsAddTest.cmake index a1b491dc49..4b4733820e 100644 --- a/cmake/macros/SundialsAddTest.cmake +++ b/cmake/macros/SundialsAddTest.cmake @@ -185,13 +185,25 @@ macro(SUNDIALS_ADD_TEST NAME EXECUTABLE) if((SUNDIALS_ADD_TEST_MPI_NPROCS) AND ((MPIEXEC_EXECUTABLE) OR (SUNDIALS_TEST_MPIRUN_COMMAND))) if(SUNDIALS_TEST_MPIRUN_COMMAND) - set(RUN_COMMAND - "${SUNDIALS_TEST_MPIRUN_COMMAND} ${MPIEXEC_NUMPROC_FLAG} ${SUNDIALS_ADD_TEST_MPI_NPROCS} ${MPIEXEC_PREFLAGS}" - ) + if(MPIEXEC_PREFLAGS) + set(RUN_COMMAND + "${SUNDIALS_TEST_MPIRUN_COMMAND} ${MPIEXEC_PREFLAGS} ${MPIEXEC_NUMPROC_FLAG} ${SUNDIALS_ADD_TEST_MPI_NPROCS}" + ) + else() + set(RUN_COMMAND + "${SUNDIALS_TEST_MPIRUN_COMMAND} ${MPIEXEC_NUMPROC_FLAG} ${SUNDIALS_ADD_TEST_MPI_NPROCS}" + ) + endif() elseif(MPIEXEC_EXECUTABLE) - set(RUN_COMMAND - "${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG} ${SUNDIALS_ADD_TEST_MPI_NPROCS} ${MPIEXEC_PREFLAGS}" - ) + if(MPIEXEC_PREFLAGS) + set(RUN_COMMAND + "${MPIEXEC_EXECUTABLE} ${MPIEXEC_PREFLAGS} ${MPIEXEC_NUMPROC_FLAG} ${SUNDIALS_ADD_TEST_MPI_NPROCS}" + ) + else() + set(RUN_COMMAND + "${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG} ${SUNDIALS_ADD_TEST_MPI_NPROCS}" + ) + endif() endif() # remove trailing white space (empty MPIEXEC_PREFLAGS) as it can cause @@ -211,7 +223,12 @@ macro(SUNDIALS_ADD_TEST NAME EXECUTABLE) set(_run_args "${_run_args} ${_extra_args}") unset(_extra_args) endif() - if(_have_test_args OR _have_extra_test_args) + if(MPIEXEC_POSTFLAGS) + set(_run_args "${MPIEXEC_POSTFLAGS} ${_run_args}") + endif() + if(_have_test_args + OR _have_extra_test_args + OR MPIEXEC_POSTFLAGS) string(STRIP "${_run_args}" _run_args) list(APPEND TEST_ARGS "--runargs=\"${_run_args}\"") unset(_run_args) @@ -239,22 +256,25 @@ macro(SUNDIALS_ADD_TEST NAME EXECUTABLE) if(MPIEXEC_PREFLAGS) string(REPLACE " " ";" PREFLAGS "${MPIEXEC_PREFLAGS}") endif() + if(MPIEXEC_POSTFLAGS) + string(REPLACE " " ";" POSTLAGS "${MPIEXEC_POSTFLAGS}") + endif() if(SUNDIALS_TEST_MPIRUN_COMMAND) string(REPLACE " " ";" MPI_EXEC_ARGS "${SUNDIALS_TEST_MPIRUN_COMMAND}") add_test( NAME ${NAME} COMMAND - ${MPI_EXEC_ARGS} ${MPIEXEC_NUMPROC_FLAG} - ${SUNDIALS_ADD_TEST_MPI_NPROCS} ${PREFLAGS} - $ ${TEST_ARGS}) + ${MPI_EXEC_ARGS} ${PREFLAGS} ${MPIEXEC_NUMPROC_FLAG} + ${SUNDIALS_ADD_TEST_MPI_NPROCS} $ + ${POSTFLAGS} ${TEST_ARGS}) else() add_test( NAME ${NAME} COMMAND - ${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG} - ${SUNDIALS_ADD_TEST_MPI_NPROCS} ${PREFLAGS} - $ ${TEST_ARGS}) + ${MPIEXEC_EXECUTABLE} ${PREFLAGS} ${MPIEXEC_NUMPROC_FLAG} + ${SUNDIALS_ADD_TEST_MPI_NPROCS} ${POSTFLAGS} + $ ${POSTFLAGS} ${TEST_ARGS}) endif() else() add_test(NAME ${NAME} COMMAND $ ${TEST_ARGS}) diff --git a/doc/shared/sundials/Install.rst b/doc/shared/sundials/Install.rst index 2a5068e5c9..0b778bb07c 100644 --- a/doc/shared/sundials/Install.rst +++ b/doc/shared/sundials/Install.rst @@ -868,6 +868,23 @@ illustration only. .. note:: This option is triggered only if MPI is enabled (``ENABLE_MPI`` is ``ON``). +.. cmakeoption:: MPIEXEC_PREFLAGS + + Specifies flags that come directly after ``MPIEXEC_EXECUTABLE`` and before + ``MPIEXEC_NUMPROC_FLAG`` and ``MPIEXEC_MAX_NUMPROCS``. + + Default: none + + .. note:: This option is triggered only if MPI is enabled (``ENABLE_MPI`` is ``ON``). + +.. cmakeoption:: MPIEXEC_POSTFLAGS + + Specifies flags that come after the executable to run but before any other program arguments. + + Default: none + + .. note:: This option is triggered only if MPI is enabled (``ENABLE_MPI`` is ``ON``). + .. cmakeoption:: ENABLE_ONEMKL Enable oneMKL support. diff --git a/doc/superbuild/source/developers/style_guide/Documentation.rst b/doc/superbuild/source/developers/style_guide/Documentation.rst index 92b6d02e86..c21f600714 100644 --- a/doc/superbuild/source/developers/style_guide/Documentation.rst +++ b/doc/superbuild/source/developers/style_guide/Documentation.rst @@ -126,6 +126,18 @@ References All citations go into `doc/shared/sundials.bib`. TODO: add citation and reference key style. +Links +===== + +Links to websites should typically use the anonymous link syntax. + +.. code-block:: rst + + `SUNDIALS documentation `__ + +Pay special attention to the two trailing underscores - two underscores +indicates an anonymous link. + User-Callable Functions ======================= diff --git a/doc/superbuild/source/developers/testing/CI.rst b/doc/superbuild/source/developers/testing/CI.rst index a71b4e5930..e891ed3e74 100644 --- a/doc/superbuild/source/developers/testing/CI.rst +++ b/doc/superbuild/source/developers/testing/CI.rst @@ -13,7 +13,7 @@ .. _CI: -GitHub CI Testing +GitHub CI Testing ================= There are two categories of CI testing that we run on GitHub via `GitHub actions `_: @@ -111,6 +111,11 @@ For information specific to the LLNL GitLab CI see: * `LLNL GitLab Runner Tags `_ +SUNDIALS utilizes the GitLab CI pipeline code repository shared by LLNL RADIUSS +projects. The `docs `__ for +the shared project should be reviewed before reading the docs below. + + CI Pipelines and Jobs --------------------- @@ -123,124 +128,120 @@ the jobs in a stage succeed, the pipeline moves on to the next stage. If any job in a stage fails, the next stage is usually (see below) not executed and the pipeline ends early. +Some pipelines are run automatically on new commits (after they are mirrored +from GitHub to LC GitLab). Other pipelines, such as the benchmarking pipeline, +are run on a schedule that is configured through the +`GitLab UI `__. + +Structure +^^^^^^^^^ + +As previously stated, most of our code for the LC GitLab CI pipelines is sourced from +the templates provided in the +`radiuss-shared-ci `__ repo. +Here we briefly outline the relevant files: + +The ``.gitlab-ci.yml`` file in the root of the repository is the starting point for +defining the SUNDIALS GitLab CI pipelines. The only thing that is typically changed +in this file is the ``SPACK_REF`` variable in the ``variables`` section (this +is done when we update the version of Spack we use for installing dependencies). +Currently, we also override the `.build-and-test` job defined in this file so +that we can pull in some files from our fork of `radiuss-shared-ci` +(maintained `here `__) +instead of the upstream repository. + +The ``.gitlab/subscribed-pipelines.yml`` defines which machines we will test on. +This file may be modified if you need to add a new machine to test on. + +The ``.gitlab/custom-jobs-and-variables.yml`` defines variables available in all +pipelines and jobs. This file may be modified if you need to add a new variable +that needs to be accessible to all pipelines and jobs. + +The ``.gitlab/jobs/.yaml`` files define the jobs for a specific machine. +A "hidden" job of the form `.sundials_job_on_` is defined first in these +files and typically defines variables specific to that machine, such as what command +to use for executing MPI programs. The rest of the jobs in the file extend the +`.sundials_job_on_` and define the Spack spec that we will build and test. +Take for example, this Tioga job: -CI Pipeline -^^^^^^^^^^^ - -The YAML file ``.gitlab-ci.yml`` at the top-level of the repository defines the -GitLab CI pipeline. The SUNDIALS CI configuration file is organized as follows: - -* The ``variables:`` keyword defines environment variables shared by all stages - and jobs. Variables can be used to alter the CI pipeline behavior when - launching a job from the GitLab "Run pipeline" UI or from the GitLab pipeline - scheduling UI. See the ``.gitlab-ci.yml`` file for details about all of the - available variables and what they do. - - .. code-block:: YAML +.. code-block:: YAML + tioga_rocmcc_620_tpls: + parallel: + matrix: + - COMPILER_SPEC: rocmcc@6.2.0 + AMDGPU_TARGET: [gfx90a] variables: - GIT_SUBMODULE_STRATEGY: recursive - ALLOC_NAME: ${CI_PROJECT_NAME}_ci_${CI_PIPELINE_ID} - BUILD_ROOT: ${CI_PROJECT_DIR} - # ... - -* The ``stages:`` keyword defines independent CI stages targeting a specific - test machine following the prefix naming convention: + # have to use ginkgo@master because our spack version does not have ginkgo@1.8.0: yet (which seems to be needed) + # similarly, we need a newer magma than available to compile with 'rocm@6:' so we turn it off + SPEC: "%${COMPILER_SPEC} cstd=99 cxxstd=14 precision=double amdgpu_target=${AMDGPU_TARGET} +rocm+mpi~magma+ginkgo+kokkos ^ginkgo@master+rocm amdgpu_target=${AMDGPU_TARGET} ^kokkos+rocm amdgpu_target=${AMDGPU_TARGET}" + before_script: + - module load rocmcc/6.2.0-magic + extends: [.sundials_job_on_tioga] - * ``q_`` jobs run on Quartz - * ``l_`` jobs run on Lassen +The ``parallel:`` and ``matrix:`` keywords could be used to enable creating multiple jobs +with different variable values for each instance of the job, e.g., one job using +``rocmcc@6.2.0`` and another using ``rocmcc@6.2.1``. However, right now they only create +a single job (hence why ``COMPILER_SPEC`` and ``AMDGPU_TARGET`` only have one value). These +variables values are then used to create an environment variable ``SPEC`` which is the Spack spec +used by ``build_and_test.sh`` (discussed below) to configure and build SUNDIALS and the +necessary dependencies. - .. code-block:: YAML +Disabling a Job +^^^^^^^^^^^^^^^ - stages: - - q_build_and_test - - l_build_and_test - # ... +A job can be disabled by adding the variable ``.ON_: "OFF"`` to the ``variables:`` +section of the job, e.g., -* Several hidden job templates (job names start with ``.``) are defined for - specific architectures and batch queue systems. These jobs provide the batch - system command to run the ``build_and_test.sh`` script that configures, - builds, and tests SUNDIALS. - .. code-block:: YAML - - .build_toss_3_x86_64_ib_script: - script: - - echo ${ALLOC_NAME} - - srun -p pdebug -N 1 -n ${NCPUS} --interactive -t ${DEFAULT_TIME} - --job-name=${ALLOC_NAME} .gitlab/build_and_test.sh - - # ... - -* The ``include:`` keyword loads YAML files defining the jobs for specific - machines. - - .. code-block:: YAML - - include: - - local: .gitlab/quartz-jobs.yml - - local: .gitlab/lassen-jobs.yml - # ... - - -CI Jobs -^^^^^^^ +.. code-block:: YAML -As noted above, each stage in the CI pipeline corresponds to testing on a -specific machine. For example, jobs run on Lassen are associated with the -``l_build_and_test`` stage. The actual jobs to run are defined in the YAML -file ``.gitlab/lassen-jobs.yml``. + tioga_rocmcc_620_tpls: + parallel: + matrix: + - COMPILER_SPEC: rocmcc@6.2.0 + AMDGPU_TARGET: [gfx90a] + variables: + ON_TIOGA: "OFF" # disable this job + SPEC: "%${COMPILER_SPEC} cstd=99 cxxstd=14 precision=double amdgpu_target=${AMDGPU_TARGET} +rocm+mpi~magma+ginkgo+kokkos ^ginkgo@master+rocm amdgpu_target=${AMDGPU_TARGET} ^kokkos+rocm amdgpu_target=${AMDGPU_TARGET}" + before_script: + - module load rocmcc/6.2.0-magic + extends: [.sundials_job_on_tioga] -The Lassen build and test jobs inherit from three job templates: +These variables can also be set when manually or scheduling a pipeline in the GitLab UI. -* ``.build_blueos_3_ppc64le_ib_script`` executes the LSF command to run the - testing script. +Updating Spack +^^^^^^^^^^^^^^ -* ``.on_lassen`` defines the tags (``tags:`` keyword) to select a shell runner - on Lassen and the rules (``rules:`` keyword) for when a job should run. +To update the spack commit used for the CI simply replace the commit hash in the +``SPACK_REF`` variable inside the ``.gitlab-ci.yml`` file with the new commit hash. +The first time a pipeline runs with a new ``SPACK_REF`` the pipeline will take longer than +normal as a new Spack build cache must be created and populated (so all packages will be +built from source). -* ``.lassen_build_and_test`` inherits from the prior two job templates using the - ``extends:`` keyword and acts as the base jobs that all other Lassen jobs - inherit from. The base template includes: - * The ``stage:`` keyword defines which stage the jobs run in. +Benchmark Jobs +^^^^^^^^^^^^^^ - * The ``needs:`` keyword lists the job dependencies. Normally, GitLab stages - are blocking however, by providing the dependencies we can break the - ordering of stages, in favor of using a DAG. This allows jobs to be run - out-of-order rather than waiting on the jobs in other stages to complete. +See :ref:`SUNDIALS Continuous Performance Testing (CPT)` for more details. - * The ``artifacts:`` keyword defines ``files:`` and directories (``paths:``) - created by the job that should be retained and ``when:`` they should be - attached to the job. -The Lassen tests are defined by jobs that extend the ``.lassen_build_and_test`` -template and use the naming convention ``lassen__``. -For example, tests using GCC, CUDA, and third-party libraries enabled are -defined by the job: +Directories and Permissions +^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. code-block:: YAML +* ``/usr/workspace/sundials`` is the workspace directory associated with the ``sundials`` LC group. + Users must be added to this group through the LC IDM application. - lassen_gcc_cuda_tpls: - parallel: - matrix: - - COMPILER_SPEC: gcc@7.3.1 - CUDA_SPEC: [cuda@10.1.243, cuda@11.2.0] - variables: - SPEC: "%${COMPILER_SPEC} precision=double ~int64 +openmp +cuda +raja cuda_arch=70 \ - ^raja+cuda~examples~exercises cuda_arch=70 ^${CUDA_SPEC}" - extends: .lassen_build_and_test +* ``/usr/workspace/sundials/ci`` is where all GitLab CI related files are stored. + The correct permissions for this directory are ``drwxrws---``. -The ``parallel:`` and ``matrix:`` keywords enable creating multiple jobs with -different variable values for each instance of the job i.e., one job using -``cuda@10.1.243`` and another using ``cuda@11.2.0``. These variables values are -then used to create an environment variable ``SPEC`` with a Spack spec used by -``build_and_test.sh`` when configuring SUNDIALS. +* ``/usr/workspace/sundials/ci/.builds`` is where GitLab CI pipelines are run. The permissions + for this directory are ``drwxrwx---``, but directories within it must be ``drwx------``. + Files within it should be ``-rw-rw----`` (can add ``x`` for group and owner as appropriate). -Benchmark Jobs -^^^^^^^^^^^^^^ +* ``/usr/workspace/sundials/ci/spack_stuff`` contains the Spack build caches amongst other Spack + files. The permissions for this directory and directories below should be ``drwxrws---``. -See :ref:`SUNDIALS Continuous Performance Testing (CPT)` for more details. GitLab CI Test Script --------------------- @@ -257,26 +258,27 @@ build, and test SUNDIALS. This script leverages two Git submodules: * `radiuss-spack-configs `_ -- is the SUNDIALS fork of the `LLNL radiuss-spack-configs `_ - repository that provides spack configuration files for various LLNL platfornms - i.e., ``compilers.yaml`` and ``packages.yaml`` files for Quartz, Lassen, etc. + repository that provides spack environment files for various LLNL platfornms + i.e., ``spack.yaml`` for Dane, Tioga, etc. -These submodules work in conjunction with ``spack_packages/sundials/package.py`` +These submodules work in conjunction with ``scripts/sundials/package.py`` to configure and build any third-party libraries needed by the SUNDIALS configuration and generates an initial CMake cache file for building SUNDIALS. -Other packages can be added to ``spack_packages//package.py`` -if the default Spack package needs to be overridden. We do this currently for -Caliper, as we need a newer version than in the Spack commit currently used. +Other packages can be added to ``spack/packages`` if the default Spack package +needs to be overridden. -Updating Spack --------------- +Spack Build Cache +^^^^^^^^^^^^^^^^^ + +The ``build_and_test.sh`` script leverage Spack build caches in ``/usr/workspace/sundials/ci/spack_stuff/`` +to speedup builds. These caches store binaries of packages that have been built previously. Separate caches are +made for each ``SPACK_REF`` to avoid conflicts across Spack versions. -To update the spack commit used for the CI: -1. The first thing to do is update the spack commit in the -``.uberenv_config.json`` file. -2. Then, a pipeline should be manually launched from the GitLab UI with the -``SHARED_SPACK`` CI variable set to ``ON`` and the ``SPACK_PREFIX`` variable to -the version of spack being set in the uberenv_config.json. +Running Locally +^^^^^^^^^^^^^^^ -This will create a new spack installation and rebuild all of the specs. +It is possible to run these scripts locally on an LC machine. First set a ``SPACK_REF`` +environment variable to a spack commit that you want to use, and then set a ``SPEC`` +environment variable with a SUNDIALS spack spec that you want to test. diff --git a/examples/nvector/petsc/CMakeLists.txt b/examples/nvector/petsc/CMakeLists.txt index 9b18176bee..83809bab49 100644 --- a/examples/nvector/petsc/CMakeLists.txt +++ b/examples/nvector/petsc/CMakeLists.txt @@ -18,8 +18,9 @@ # develop for examples excluded from 'make test' in releases # Examples using SUNDIALS PETSc nvector -set(nvector_petsc_examples "test_nvector_petsc\;1000 0\;\;\;" # run sequentially - "test_nvector_petsc\;1000 0\;1\;4\;" # run 4 procs +set(nvector_petsc_examples + "test_nvector_petsc\;1000 0\;1\;1\;" # run sequentially + "test_nvector_petsc\;1000 0\;1\;4\;" # run 4 procs ) # Dependencies for nvector examples diff --git a/examples/sunnonlinsol/petsc/CMakeLists.txt b/examples/sunnonlinsol/petsc/CMakeLists.txt index 7146134ea8..2c366597a6 100644 --- a/examples/sunnonlinsol/petsc/CMakeLists.txt +++ b/examples/sunnonlinsol/petsc/CMakeLists.txt @@ -18,7 +18,7 @@ # examples excluded from 'make test' in releases # Example programs -set(examples "test_sunnonlinsol_petscsnes\;\;") +set(examples "test_sunnonlinsol_petscsnes\;\;1\;1\;") if(MPI_C_COMPILER) # use MPI wrapper as the compiler @@ -41,7 +41,9 @@ foreach(example_tuple ${examples}) # parse the example tuple list(GET example_tuple 0 example) list(GET example_tuple 1 example_args) - list(GET example_tuple 2 example_type) + list(GET example_tuple 2 number_of_nodes) + list(GET example_tuple 3 number_of_tasks) + list(GET example_tuple 4 example_type) # check if this example has already been added, only need to add example # source files once for testing with different inputs @@ -67,6 +69,7 @@ foreach(example_tuple ${examples}) sundials_add_test( ${test_name} ${example} TEST_ARGS ${example_args} + MPI_NPROCS ${number_of_tasks} EXAMPLE_TYPE ${example_type} NODIFF) diff --git a/examples/sunnonlinsol/petsc/test_sunnonlinsol_petscsnes.c b/examples/sunnonlinsol/petsc/test_sunnonlinsol_petscsnes.c index b9486208b8..d66fb5526a 100644 --- a/examples/sunnonlinsol/petsc/test_sunnonlinsol_petscsnes.c +++ b/examples/sunnonlinsol/petsc/test_sunnonlinsol_petscsnes.c @@ -157,6 +157,7 @@ int main(int argc, char* argv[]) N_VDestroy(y0); N_VDestroy(w); SUNNonlinSolFree(NLS); + PetscFinalize(); SUNContext_Free(&sunctx); /* Print result */ diff --git a/.gitlab/spack_packages/sundials/0001-add-missing-README-to-examples-cvode-hip.patch b/scripts/spack/packages/sundials/0001-add-missing-README-to-examples-cvode-hip.patch similarity index 100% rename from .gitlab/spack_packages/sundials/0001-add-missing-README-to-examples-cvode-hip.patch rename to scripts/spack/packages/sundials/0001-add-missing-README-to-examples-cvode-hip.patch diff --git a/.gitlab/spack_packages/sundials/5.5.0-xsdk-patches.patch b/scripts/spack/packages/sundials/5.5.0-xsdk-patches.patch similarity index 100% rename from .gitlab/spack_packages/sundials/5.5.0-xsdk-patches.patch rename to scripts/spack/packages/sundials/5.5.0-xsdk-patches.patch diff --git a/.gitlab/spack_packages/sundials/FindPackageMultipass.cmake.patch b/scripts/spack/packages/sundials/FindPackageMultipass.cmake.patch similarity index 100% rename from .gitlab/spack_packages/sundials/FindPackageMultipass.cmake.patch rename to scripts/spack/packages/sundials/FindPackageMultipass.cmake.patch diff --git a/.gitlab/spack_packages/sundials/nvector-pic.patch b/scripts/spack/packages/sundials/nvector-pic.patch similarity index 100% rename from .gitlab/spack_packages/sundials/nvector-pic.patch rename to scripts/spack/packages/sundials/nvector-pic.patch diff --git a/.gitlab/spack_packages/sundials/package.py b/scripts/spack/packages/sundials/package.py similarity index 98% rename from .gitlab/spack_packages/sundials/package.py rename to scripts/spack/packages/sundials/package.py index ce7f4ece91..2257576317 100644 --- a/.gitlab/spack_packages/sundials/package.py +++ b/scripts/spack/packages/sundials/package.py @@ -183,9 +183,9 @@ class Sundials(CachedCMakePackage, CudaPackage, ROCmPackage): # Scheduler variant( - "scheduler", - default="slurm", - description="Specify which scheduler the system runs on", + "scheduler", + default="slurm", + description="Specify which scheduler the system runs on", values=("flux", "lsf", "slurm") ) @@ -194,9 +194,9 @@ class Sundials(CachedCMakePackage, CudaPackage, ROCmPackage): # Profiling examples variant( - "profile-examples", - default=False, - when="+adiak +caliper", + "profile-examples", + default=False, + when="+adiak +caliper", description="Build examples with profiling capabilities") # Caliper Directory @@ -251,7 +251,8 @@ class Sundials(CachedCMakePackage, CudaPackage, ROCmPackage): depends_on("superlu-dist@6.3.0:", when="@5.5.0:6.3.0 +superlu-dist") depends_on("superlu-dist@6.1.1:", when="@:5.4.0 +superlu-dist") depends_on("superlu-mt+blas", when="+superlu-mt") - depends_on("trilinos+tpetra", when="+trilinos") + depends_on("trilinos+tpetra@:13", when="@:7.1.1 +trilinos") + depends_on("trilinos+tpetra@14:", when="@7.2.0: +trilinos") # Require that external libraries built with the same precision depends_on("petsc~double~complex", when="+petsc precision=single") @@ -697,7 +698,7 @@ def initconfig_mpi_entries(self): entries.append(cmake_cache_string("SUNDIALS_SCHEDULER_COMMAND", "srun")) if "scheduler=lsf" in spec: entries.append(cmake_cache_string("SUNDIALS_SCHEDULER_COMMAND", "jsrun")) - + return entries @@ -719,11 +720,10 @@ def initconfig_hardware_entries(self): entries.extend( [ self.cache_option_from_variant("ENABLE_HIP", "rocm"), - cmake_cache_path("CMAKE_C_COMPILER", spec["llvm-amdgpu"].prefix.bin.clang), - cmake_cache_path("CMAKE_CXX_COMPILER", spec["hip"].hipcc), cmake_cache_path("HIP_PATH", spec["hip"].prefix), + cmake_cache_path("HIP_DIR", spec["hip"].prefix.cmake), cmake_cache_path("HIP_CLANG_INCLUDE_PATH", spec["llvm-amdgpu"].prefix.include), - cmake_cache_path("ROCM_PATH", spec["llvm-amdgpu"].prefix), + cmake_cache_path("ROCM_PATH", spec["hsa-rocr-dev"].prefix), cmake_cache_string("AMDGPU_TARGETS", ";".join(spec.variants["amdgpu_target"].value)) ] ) @@ -763,7 +763,7 @@ def initconfig_package_entries(self): self.cache_option_from_variant("SUNDIALS_TEST_PROFILE", "profile-examples"), self.cache_option_from_variant("SUNDIALS_TEST_DEVTESTS", "profile-examples"), cmake_cache_string("SPACK_VERSION", ".".join(map(str, spack.spack_version_info))) - + ] ) @@ -799,7 +799,7 @@ def initconfig_package_entries(self): ) # Building with Adiak - if "+adiak" in spec: + if "+adiak" in spec: entries.append(cmake_cache_path("adiak_DIR", spec["adiak"].prefix.lib.cmake + "/adiak")) # Building with Caliper diff --git a/.gitlab/spack_packages/sundials/remove-links-to-OpenMP-vector.patch b/scripts/spack/packages/sundials/remove-links-to-OpenMP-vector.patch similarity index 100% rename from .gitlab/spack_packages/sundials/remove-links-to-OpenMP-vector.patch rename to scripts/spack/packages/sundials/remove-links-to-OpenMP-vector.patch diff --git a/.gitlab/spack_packages/sundials/sundials-v5.8.0.patch b/scripts/spack/packages/sundials/sundials-v5.8.0.patch similarity index 100% rename from .gitlab/spack_packages/sundials/sundials-v5.8.0.patch rename to scripts/spack/packages/sundials/sundials-v5.8.0.patch diff --git a/.gitlab/spack_packages/sundials/test_nvector_parhyp.patch b/scripts/spack/packages/sundials/test_nvector_parhyp.patch similarity index 100% rename from .gitlab/spack_packages/sundials/test_nvector_parhyp.patch rename to scripts/spack/packages/sundials/test_nvector_parhyp.patch diff --git a/scripts/spack/repo.yaml b/scripts/spack/repo.yaml new file mode 100644 index 0000000000..97f36d22aa --- /dev/null +++ b/scripts/spack/repo.yaml @@ -0,0 +1,2 @@ +repo: + namespace: 'sundials' From 8c72a8b601384443bb5fc0484fcbcf829656af6c Mon Sep 17 00:00:00 2001 From: Steven Roberts Date: Fri, 1 Nov 2024 13:13:54 -0700 Subject: [PATCH 15/89] Docs: Fix typos in linear solver section of CVODE skeleton (#599) --- doc/cvode/guide/source/Usage/index.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/cvode/guide/source/Usage/index.rst b/doc/cvode/guide/source/Usage/index.rst index 3c56d48587..b2e793d5e3 100644 --- a/doc/cvode/guide/source/Usage/index.rst +++ b/doc/cvode/guide/source/Usage/index.rst @@ -208,15 +208,15 @@ function to be called or macro to be referenced. If a nonlinear solver requiring a linear solver is chosen (e.g., the default Newton iteration), then initialize the CVLS linear solver interface by attaching the linear solver object (and matrix object, - if applicable) with a call ``ier = CVodeSetLinearSolver(cvode_mem, NLS)`` (for details see - :numref:`CVODE.Usage.CC.callable_fct_sim.lin_solv_init`): + if applicable) with a call ``ier = CVodeSetLinearSolver(cvode_mem, LS, A)`` + (for details see :numref:`CVODE.Usage.CC.callable_fct_sim.lin_solv_init`). Alternately, if the CVODE-specific diagonal linear solver module, CVDIAG, is desired, initialize the linear solver module and attach it to CVODE with the call to :c:func:`CVodeSetLinearSolver`. #. **Set optional inputs** - Call ```CVodeSet***`` functions to change any optional inputs that control the + Call ``CVodeSet***`` functions to change any optional inputs that control the behavior of CVODE from their default values. See :numref:`CVODE.Usage.CC.optional_input` for details. From a3fa77f75657754a5b9659c14a120e46c188a5d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mustafa=20A=C4=9Fg=C3=BCl?= <33010171+maggul@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:36:02 -0600 Subject: [PATCH 16/89] Feature: Add STS and SSPs method to ARKODE (#541) Add LSRKStep module to ARKODE with RKC, RKL, and SSPs methods. --------- Co-authored-by: Daniel R. Reynolds Co-authored-by: David Gardner --- .gitignore | 2 + CHANGELOG.md | 5 + benchmarks/diffusion_2D/main_arkode.cpp | 392 ++- doc/arkode/guide/source/Constants.rst | 25 + doc/arkode/guide/source/Mathematics.rst | 71 +- .../source/Usage/ARKStep/User_callable.rst | 106 +- .../source/Usage/ERKStep/User_callable.rst | 76 +- doc/arkode/guide/source/Usage/General.rst | 3 +- .../source/Usage/LSRKStep/User_callable.rst | 389 +++ .../source/Usage/LSRKStep/User_supplied.rst | 52 + .../guide/source/Usage/LSRKStep/index.rst | 32 + .../source/Usage/MRIStep/User_callable.rst | 63 +- .../source/Usage/SPRKStep/User_callable.rst | 28 +- .../guide/source/Usage/User_callable.rst | 8 +- doc/arkode/guide/source/Usage/index.rst | 5 +- doc/shared/RecentChanges.rst | 6 + doc/shared/sundials.bib | 69 +- examples/arkode/CMakeLists.txt | 3 + examples/arkode/CXX_manyvector/CMakeLists.txt | 84 + .../arkode/CXX_manyvector/ark_sod_lsrk.cpp | 580 +++++ .../arkode/CXX_manyvector/ark_sod_lsrk.hpp | 538 ++++ .../arkode/CXX_manyvector/ark_sod_lsrk.out | 48 + examples/arkode/CXX_manyvector/plot_sod.py | 231 ++ examples/arkode/CXX_parallel/CMakeLists.txt | 9 +- .../arkode/CXX_parallel/ark_heat2D_lsrk_p.cpp | 1743 +++++++++++++ .../ark_heat2D_lsrk_p_--np_2_2.out | 77 + .../CXX_parhyp/ark_heat2D_hypre_pfmg.cpp | 105 +- examples/arkode/CXX_serial/CMakeLists.txt | 1 + .../arkode/CXX_serial/ark_heat2D_lsrk.cpp | 986 ++++++++ .../arkode/CXX_serial/ark_heat2D_lsrk.out | 71 + examples/arkode/C_serial/CMakeLists.txt | 3 + examples/arkode/C_serial/ark_analytic_lsrk.c | 328 +++ .../arkode/C_serial/ark_analytic_lsrk.out | 40 + .../C_serial/ark_analytic_lsrk_varjac.c | 364 +++ .../C_serial/ark_analytic_lsrk_varjac.out | 43 + examples/arkode/C_serial/ark_analytic_ssprk.c | 271 ++ .../arkode/C_serial/ark_analytic_ssprk.out | 36 + include/arkode/arkode.h | 3 + include/arkode/arkode_lsrkstep.h | 99 + include/sundials/sundials_math.h | 26 + src/arkode/CMakeLists.txt | 3 + src/arkode/arkode.c | 43 +- src/arkode/arkode_arkstep_io.c | 2 +- src/arkode/arkode_erkstep_impl.h | 1 - src/arkode/arkode_erkstep_io.c | 3 +- src/arkode/arkode_impl.h | 1 + src/arkode/arkode_io.c | 4 + src/arkode/arkode_lsrkstep.c | 2236 +++++++++++++++++ src/arkode/arkode_lsrkstep_impl.h | 219 ++ src/arkode/arkode_lsrkstep_io.c | 759 ++++++ src/arkode/arkode_mristep_io.c | 2 +- src/arkode/arkode_sprkstep_io.c | 2 +- src/arkode/fmod_int32/farkode_lsrkstep_mod.c | 459 ++++ .../fmod_int32/farkode_lsrkstep_mod.f90 | 496 ++++ src/arkode/fmod_int32/farkode_mod.f90 | 2 + src/arkode/fmod_int64/farkode_lsrkstep_mod.c | 459 ++++ .../fmod_int64/farkode_lsrkstep_mod.f90 | 496 ++++ src/arkode/fmod_int64/farkode_mod.f90 | 2 + swig/Makefile | 2 +- swig/arkode/farkode_lsrkstep_mod.i | 30 + test/answers | 2 +- 61 files changed, 11930 insertions(+), 314 deletions(-) create mode 100644 doc/arkode/guide/source/Usage/LSRKStep/User_callable.rst create mode 100644 doc/arkode/guide/source/Usage/LSRKStep/User_supplied.rst create mode 100644 doc/arkode/guide/source/Usage/LSRKStep/index.rst create mode 100644 examples/arkode/CXX_manyvector/CMakeLists.txt create mode 100644 examples/arkode/CXX_manyvector/ark_sod_lsrk.cpp create mode 100644 examples/arkode/CXX_manyvector/ark_sod_lsrk.hpp create mode 100644 examples/arkode/CXX_manyvector/ark_sod_lsrk.out create mode 100755 examples/arkode/CXX_manyvector/plot_sod.py create mode 100644 examples/arkode/CXX_parallel/ark_heat2D_lsrk_p.cpp create mode 100644 examples/arkode/CXX_parallel/ark_heat2D_lsrk_p_--np_2_2.out create mode 100644 examples/arkode/CXX_serial/ark_heat2D_lsrk.cpp create mode 100644 examples/arkode/CXX_serial/ark_heat2D_lsrk.out create mode 100644 examples/arkode/C_serial/ark_analytic_lsrk.c create mode 100644 examples/arkode/C_serial/ark_analytic_lsrk.out create mode 100644 examples/arkode/C_serial/ark_analytic_lsrk_varjac.c create mode 100644 examples/arkode/C_serial/ark_analytic_lsrk_varjac.out create mode 100644 examples/arkode/C_serial/ark_analytic_ssprk.c create mode 100644 examples/arkode/C_serial/ark_analytic_ssprk.out create mode 100644 include/arkode/arkode_lsrkstep.h create mode 100644 src/arkode/arkode_lsrkstep.c create mode 100644 src/arkode/arkode_lsrkstep_impl.h create mode 100644 src/arkode/arkode_lsrkstep_io.c create mode 100644 src/arkode/fmod_int32/farkode_lsrkstep_mod.c create mode 100644 src/arkode/fmod_int32/farkode_lsrkstep_mod.f90 create mode 100644 src/arkode/fmod_int64/farkode_lsrkstep_mod.c create mode 100644 src/arkode/fmod_int64/farkode_lsrkstep_mod.f90 create mode 100644 swig/arkode/farkode_lsrkstep_mod.i diff --git a/.gitignore b/.gitignore index 3e9185713d..763405865e 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,8 @@ compile_commands.json *.orig *.nvvp *.ptp-sync* +*.project +*.cproject *~ \#* diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a2184439e..ee1021d575 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,11 @@ Volta GPUs while the automatically selected value will vary across compilers and compiler versions. As such, users are encouraged to override this value with the architecture for their system. +Added a time-stepping module to ARKODE for low storage Runge--Kutta methods, LSRKStep. +This currently supports five explicit low-storage methods: the second-order Runge--Kutta--Chebyshev +and Runge--Kutta--Legendre methods, and the second- through fourth-order optimal strong stability +preserving Runge--Kutta methods. All methods include embeddings for temporal adaptivity. + The Trilinos Teptra NVector interface has been updated to utilize CMake imported targets added in Trilinos 14 to improve support for different Kokkos backends with Trilinos. As such, Trilinos 14 or newer is required and the diff --git a/benchmarks/diffusion_2D/main_arkode.cpp b/benchmarks/diffusion_2D/main_arkode.cpp index 39c6274a6e..e569cffec2 100644 --- a/benchmarks/diffusion_2D/main_arkode.cpp +++ b/benchmarks/diffusion_2D/main_arkode.cpp @@ -15,7 +15,10 @@ * ---------------------------------------------------------------------------*/ #include "arkode/arkode_arkstep.h" +#include "arkode/arkode_lsrkstep.h" #include "diffusion_2D.hpp" +#include "sunadaptcontroller/sunadaptcontroller_imexgus.h" +#include "sunadaptcontroller/sunadaptcontroller_soderlind.h" struct UserOptions { @@ -28,6 +31,8 @@ struct UserOptions int maxsteps = 0; // max steps between outputs int onestep = 0; // one step mode, number of steps bool linear = true; // linearly implicit RHS + bool implicit = true; // implicit (ARKStep) vs explicit STS (LSRKStep) + ARKODE_LSRKMethodType lsrkmethod = ARKODE_LSRK_RKC_2; // LSRK method type // Linear solver and preconditioner settings std::string ls = "cg"; // linear solver to use @@ -43,6 +48,14 @@ struct UserOptions void print(); }; +// ----------------------------------------------------------------------------- +// LSRKStep-specific dominant eigenvalue function prototype +// ----------------------------------------------------------------------------- + +static int dom_eig(sunrealtype t, N_Vector y, N_Vector fn, sunrealtype* lambdaR, + sunrealtype* lambdaI, void* user_data, N_Vector temp1, + N_Vector temp2, N_Vector temp3); + // ----------------------------------------------------------------------------- // Main Program // ----------------------------------------------------------------------------- @@ -58,8 +71,8 @@ int main(int argc, char* argv[]) // Create SUNDIALS context MPI_Comm comm = MPI_COMM_WORLD; - SUNContext ctx = NULL; - SUNProfiler prof = NULL; + SUNContext ctx = nullptr; + SUNProfiler prof = nullptr; flag = SUNContext_Create(comm, &ctx); if (check_flag(&flag, "SUNContextCreate", 1)) { return 1; } @@ -109,6 +122,17 @@ int main(int argc, char* argv[]) return 1; } + // Return with error on unsupported LSRK method type + if (!uopts.implicit) + { + if ((uopts.lsrkmethod != ARKODE_LSRK_RKC_2) && + (uopts.lsrkmethod != ARKODE_LSRK_RKL_2)) + { + cerr << "ERROR: illegal lsrkmethod" << endl; + return 1; + } + } + // ----------------------------- // Setup parallel decomposition // ----------------------------- @@ -152,12 +176,8 @@ int main(int argc, char* argv[]) if (check_flag((void*)(uout.error), "N_VClone", 0)) { return 1; } } - // --------------------- - // Create linear solver - // --------------------- - - // Create linear solver - SUNLinearSolver LS = NULL; + // Set up implicit solver, if applicable + SUNLinearSolver LS = nullptr; SUNMatrix A = nullptr; #if defined(USE_SUPERLU_DIST) // SuperLU-DIST objects @@ -172,77 +192,96 @@ int main(int argc, char* argv[]) sunindextype* A_col_idxs = nullptr; sunindextype* A_row_ptrs = nullptr; #endif - - int prectype = (uopts.preconditioning) ? SUN_PREC_RIGHT : SUN_PREC_NONE; - - if (uopts.ls == "cg") - { - LS = SUNLinSol_PCG(u, prectype, uopts.liniters, ctx); - if (check_flag((void*)LS, "SUNLinSol_PCG", 0)) { return 1; } - } - else if (uopts.ls == "gmres") + if (uopts.implicit) { - LS = SUNLinSol_SPGMR(u, prectype, uopts.liniters, ctx); - if (check_flag((void*)LS, "SUNLinSol_SPGMR", 0)) { return 1; } - } - else - { -#if defined(USE_SUPERLU_DIST) - // Initialize SuperLU-DIST grid - superlu_gridinit(udata.comm_c, udata.npx, udata.npy, &grid); - - // Create arrays for CSR matrix: data, column indices, and row pointers - sunindextype nnz_loc = 5 * udata.nodes_loc; - - A_data = (sunrealtype*)malloc(nnz_loc * sizeof(sunrealtype)); - if (check_flag((void*)A_data, "malloc Adata", 0)) return 1; - - A_col_idxs = (sunindextype*)malloc(nnz_loc * sizeof(sunindextype)); - if (check_flag((void*)A_col_idxs, "malloc Acolind", 0)) return 1; + // --------------------- + // Create linear solver + // --------------------- - A_row_ptrs = - (sunindextype*)malloc((udata.nodes_loc + 1) * sizeof(sunindextype)); - if (check_flag((void*)A_row_ptrs, "malloc Arowptr", 0)) return 1; + // Create linear solver - // Create and initialize SuperLU_DIST structures - dCreate_CompRowLoc_Matrix_dist(&A_super, udata.nodes, udata.nodes, nnz_loc, - udata.nodes_loc, 0, A_data, A_col_idxs, - A_row_ptrs, SLU_NR_loc, SLU_D, SLU_GE); - dScalePermstructInit(udata.nodes, udata.nodes, &A_scaleperm); - dLUstructInit(udata.nodes, &A_lu); - PStatInit(&A_stat); - set_default_options_dist(&A_opts); - A_opts.PrintStat = NO; + int prectype = (uopts.preconditioning) ? SUN_PREC_RIGHT : SUN_PREC_NONE; - // SUNDIALS structures - A = SUNMatrix_SLUNRloc(&A_super, &grid, ctx); - if (check_flag((void*)A, "SUNMatrix_SLUNRloc", 0)) return 1; - - LS = SUNLinSol_SuperLUDIST(u, A, &grid, &A_lu, &A_scaleperm, &A_solve, - &A_stat, &A_opts, ctx); - if (check_flag((void*)LS, "SUNLinSol_SuperLUDIST", 0)) return 1; - - uopts.preconditioning = false; + if (uopts.ls == "cg") + { + LS = SUNLinSol_PCG(u, prectype, uopts.liniters, ctx); + if (check_flag((void*)LS, "SUNLinSol_PCG", 0)) { return 1; } + } + else if (uopts.ls == "gmres") + { + LS = SUNLinSol_SPGMR(u, prectype, uopts.liniters, ctx); + if (check_flag((void*)LS, "SUNLinSol_SPGMR", 0)) { return 1; } + } + else + { +#if defined(USE_SUPERLU_DIST) + // Initialize SuperLU-DIST grid + superlu_gridinit(udata.comm_c, udata.npx, udata.npy, &grid); + + // Create arrays for CSR matrix: data, column indices, and row pointers + sunindextype nnz_loc = 5 * udata.nodes_loc; + + A_data = (sunrealtype*)malloc(nnz_loc * sizeof(sunrealtype)); + if (check_flag((void*)A_data, "malloc Adata", 0)) return 1; + + A_col_idxs = (sunindextype*)malloc(nnz_loc * sizeof(sunindextype)); + if (check_flag((void*)A_col_idxs, "malloc Acolind", 0)) return 1; + + A_row_ptrs = + (sunindextype*)malloc((udata.nodes_loc + 1) * sizeof(sunindextype)); + if (check_flag((void*)A_row_ptrs, "malloc Arowptr", 0)) return 1; + + // Create and initialize SuperLU_DIST structures + dCreate_CompRowLoc_Matrix_dist(&A_super, udata.nodes, udata.nodes, + nnz_loc, udata.nodes_loc, 0, A_data, + A_col_idxs, A_row_ptrs, SLU_NR_loc, + SLU_D, SLU_GE); + dScalePermstructInit(udata.nodes, udata.nodes, &A_scaleperm); + dLUstructInit(udata.nodes, &A_lu); + PStatInit(&A_stat); + set_default_options_dist(&A_opts); + A_opts.PrintStat = NO; + + // SUNDIALS structures + A = SUNMatrix_SLUNRloc(&A_super, &grid, ctx); + if (check_flag((void*)A, "SUNMatrix_SLUNRloc", 0)) return 1; + + LS = SUNLinSol_SuperLUDIST(u, A, &grid, &A_lu, &A_scaleperm, &A_solve, + &A_stat, &A_opts, ctx); + if (check_flag((void*)LS, "SUNLinSol_SuperLUDIST", 0)) return 1; + + uopts.preconditioning = false; #else - std::cerr << "ERROR: Benchmark was not built with SuperLU_DIST enabled\n"; - return 1; + std::cerr + << "ERROR: Benchmark was not built with SuperLU_DIST enabled\n"; + return 1; #endif - } + } - // Allocate preconditioner workspace - if (uopts.preconditioning) - { - udata.diag = N_VClone(u); - if (check_flag((void*)(udata.diag), "N_VClone", 0)) { return 1; } + // Allocate preconditioner workspace + if (uopts.preconditioning) + { + udata.diag = N_VClone(u); + if (check_flag((void*)(udata.diag), "N_VClone", 0)) { return 1; } + } } - // -------------- - // Setup ARKStep - // -------------- + // ---------------------- + // Setup ARKStep/LSRKStep + // ---------------------- // Create integrator - void* arkode_mem = ARKStepCreate(NULL, diffusion, ZERO, u, ctx); - if (check_flag((void*)arkode_mem, "ARKStepCreate", 0)) { return 1; } + void* arkode_mem = nullptr; + if (uopts.implicit) + { + arkode_mem = ARKStepCreate(nullptr, diffusion, ZERO, u, ctx); + if (check_flag((void*)arkode_mem, "ARKStepCreate", 0)) { return 1; } + } + else + { + arkode_mem = LSRKStepCreateSTS(diffusion, ZERO, u, ctx); + if (check_flag((void*)arkode_mem, "LSRKStepCreateSTS", 0)) { return 1; } + } // Specify tolerances flag = ARKodeSStolerances(arkode_mem, uopts.rtol, uopts.atol); @@ -252,38 +291,60 @@ int main(int argc, char* argv[]) flag = ARKodeSetUserData(arkode_mem, (void*)&udata); if (check_flag(&flag, "ARKodeSetUserData", 1)) { return 1; } - // Attach linear solver - flag = ARKodeSetLinearSolver(arkode_mem, LS, A); - if (check_flag(&flag, "ARKodeSetLinearSolver", 1)) { return 1; } + // Configure implicit solver + if (uopts.implicit) + { + // Attach linear solver + flag = ARKodeSetLinearSolver(arkode_mem, LS, A); + if (check_flag(&flag, "ARKodeSetLinearSolver", 1)) { return 1; } #if defined(USE_SUPERLU_DIST) - if (uopts.ls == "sludist") - { - ARKodeSetJacFn(arkode_mem, diffusion_jac); - if (check_flag(&flag, "ARKodeSetJacFn", 1)) return 1; - } + if (uopts.ls == "sludist") + { + ARKodeSetJacFn(arkode_mem, diffusion_jac); + if (check_flag(&flag, "ARKodeSetJacFn", 1)) return 1; + } #endif - if (uopts.preconditioning) - { - // Attach preconditioner - flag = ARKodeSetPreconditioner(arkode_mem, PSetup, PSolve); - if (check_flag(&flag, "ARKodeSetPreconditioner", 1)) { return 1; } + if (uopts.preconditioning) + { + // Attach preconditioner + flag = ARKodeSetPreconditioner(arkode_mem, PSetup, PSolve); + if (check_flag(&flag, "ARKodeSetPreconditioner", 1)) { return 1; } - // Set linear solver setup frequency (update preconditioner) - flag = ARKodeSetLSetupFrequency(arkode_mem, uopts.msbp); - if (check_flag(&flag, "ARKodeSetLSetupFrequency", 1)) { return 1; } - } + // Set linear solver setup frequency (update preconditioner) + flag = ARKodeSetLSetupFrequency(arkode_mem, uopts.msbp); + if (check_flag(&flag, "ARKodeSetLSetupFrequency", 1)) { return 1; } + } + + // Set linear solver tolerance factor + flag = ARKodeSetEpsLin(arkode_mem, uopts.epslin); + if (check_flag(&flag, "ARKodeSetEpsLin", 1)) { return 1; } + + // Select method order + flag = ARKodeSetOrder(arkode_mem, uopts.order); + if (check_flag(&flag, "ARKodeSetOrder", 1)) { return 1; } - // Set linear solver tolerance factor - flag = ARKodeSetEpsLin(arkode_mem, uopts.epslin); - if (check_flag(&flag, "ARKodeSetEpsLin", 1)) { return 1; } + // Specify linearly implicit non-time-dependent RHS + if (uopts.linear) + { + flag = ARKodeSetLinear(arkode_mem, 0); + if (check_flag(&flag, "ARKodeSetLinear", 1)) { return 1; } + } + } + else // Configure explicit STS solver + { + // Select LSRK method + flag = LSRKStepSetSTSMethod(arkode_mem, uopts.lsrkmethod); + if (check_flag(&flag, "LSRKStepSetSTSMethod", 1)) { return 1; } - // Select method order - flag = ARKodeSetOrder(arkode_mem, uopts.order); - if (check_flag(&flag, "ARKodeSetOrder", 1)) { return 1; } + // Provide dominant eigenvalue function + flag = LSRKStepSetDomEigFn(arkode_mem, dom_eig); + if (check_flag(&flag, "LSRKStepSetDomEigFn", 1)) { return 1; } + } // Set fixed step size or adaptivity method + SUNAdaptController C = nullptr; if (uopts.hfixed > ZERO) { flag = ARKodeSetFixedStep(arkode_mem, uopts.hfixed); @@ -291,16 +352,17 @@ int main(int argc, char* argv[]) } else { - flag = ARKStepSetAdaptivityMethod(arkode_mem, uopts.controller, SUNTRUE, - SUNFALSE, NULL); - if (check_flag(&flag, "ARKStepSetAdaptivityMethod", 1)) { return 1; } - } - - // Specify linearly implicit non-time-dependent RHS - if (uopts.linear) - { - flag = ARKodeSetLinear(arkode_mem, 0); - if (check_flag(&flag, "ARKodeSetLinear", 1)) { return 1; } + switch (uopts.controller) + { + case (ARK_ADAPT_PID): C = SUNAdaptController_PID(ctx); break; + case (ARK_ADAPT_PI): C = SUNAdaptController_PI(ctx); break; + case (ARK_ADAPT_I): C = SUNAdaptController_I(ctx); break; + case (ARK_ADAPT_EXP_GUS): C = SUNAdaptController_ExpGus(ctx); break; + case (ARK_ADAPT_IMP_GUS): C = SUNAdaptController_ImpGus(ctx); break; + case (ARK_ADAPT_IMEX_GUS): C = SUNAdaptController_ImExGus(ctx); break; + } + flag = ARKodeSetAdaptController(arkode_mem, C); + if (check_flag(&flag, "ARKodeSetAdaptController", 1)) { return 1; } } // Set max steps between outputs @@ -377,22 +439,26 @@ int main(int argc, char* argv[]) // Free MPI Cartesian communicator MPI_Comm_free(&(udata.comm_c)); + (void)SUNAdaptController_Destroy(C); // Free timestep adaptivity controller ARKodeFree(&arkode_mem); - SUNLinSolFree(LS); + if (uopts.implicit) + { + SUNLinSolFree(LS); - // Free the SuperLU_DIST structures (also frees user allocated arrays - // A_data, A_col_idxs, and A_row_ptrs) + // Free the SuperLU_DIST structures (also frees user allocated arrays + // A_data, A_col_idxs, and A_row_ptrs) #if defined(USE_SUPERLU_DIST) - if (uopts.ls == "sludist") - { - PStatFree(&A_stat); - dScalePermstructFree(&A_scaleperm); - dLUstructFree(&A_lu); - Destroy_CompRowLoc_Matrix_dist(&A_super); - superlu_gridexit(&grid); - } + if (uopts.ls == "sludist") + { + PStatFree(&A_stat); + dScalePermstructFree(&A_scaleperm); + dLUstructFree(&A_lu); + Destroy_CompRowLoc_Matrix_dist(&A_super); + superlu_gridexit(&grid); + } #endif + } // Free vectors #if defined(USE_HIP) || defined(USE_CUDA) @@ -409,6 +475,26 @@ int main(int argc, char* argv[]) return 0; } +// ----------------------------------------------------------------------------- +// Dominant eigenvalue estimation function +// ----------------------------------------------------------------------------- + +static int dom_eig(sunrealtype t, N_Vector y, N_Vector fn, sunrealtype* lambdaR, + sunrealtype* lambdaI, void* user_data, N_Vector temp1, + N_Vector temp2, N_Vector temp3) +{ + // Access problem data + UserData* udata = (UserData*)user_data; + + // Fill in spectral radius value + *lambdaR = -SUN_RCONST(8.0) * std::max(udata->kx / udata->dx / udata->dx, + udata->ky / udata->dy / udata->dy); + *lambdaI = SUN_RCONST(0.0); + + // return with success + return 0; +} + // ----------------------------------------------------------------------------- // UserOptions Helper functions // ----------------------------------------------------------------------------- @@ -445,6 +531,13 @@ int UserOptions::parse_args(vector& args, bool outproc) args.erase(it, it + 2); } + it = find(args.begin(), args.end(), "--explicitSTS"); + if (it != args.end()) + { + implicit = false; + args.erase(it); + } + it = find(args.begin(), args.end(), "--order"); if (it != args.end()) { @@ -452,6 +545,13 @@ int UserOptions::parse_args(vector& args, bool outproc) args.erase(it, it + 2); } + it = find(args.begin(), args.end(), "--lsrkmethod"); + if (it != args.end()) + { + lsrkmethod = (ARKODE_LSRKMethodType)stoi(*(it + 1)); + args.erase(it, it + 2); + } + it = find(args.begin(), args.end(), "--controller"); if (it != args.end()) { @@ -525,16 +625,22 @@ void UserOptions::help() cout << "Integrator command line options:" << endl; cout << " --rtol : relative tolerance" << endl; cout << " --atol : absolute tolerance" << endl; + cout << " --controller : time step adaptivity controller" << endl; + cout << " --fixedstep : used fixed step size" << endl; + cout << " --explicitSTS : use LSRKStep (instead of ARKStep)" << endl; + cout << endl; + cout << "Implicit (ARKStep) solver command line options:" << endl; cout << " --nonlinear : disable linearly implicit flag" << endl; cout << " --order : method order" << endl; - cout << " --fixedstep : used fixed step size" << endl; - cout << " --controller : time step adaptivity controller" << endl; cout << " --ls : linear solver" << endl; cout << " --lsinfo : output residual history" << endl; cout << " --liniters : max number of iterations" << endl; cout << " --epslin : linear tolerance factor" << endl; cout << " --noprec : disable preconditioner" << endl; cout << " --msbp : max steps between prec setups" << endl; + cout << endl; + cout << "Explicit STS (LSRKStep) solver command line options:" << endl; + cout << " --lsrkmethod : LSRK method choice" << endl; } // Print user options @@ -545,39 +651,57 @@ void UserOptions::print() cout << " --------------------------------- " << endl; cout << " rtol = " << rtol << endl; cout << " atol = " << atol << endl; - cout << " hfixed = " << hfixed << endl; - cout << " order = " << order << endl; cout << " controller = " << controller << endl; - cout << " max steps = " << maxsteps << endl; - cout << " linear RHS = " << linear << endl; + cout << " hfixed = " << hfixed << endl; cout << " --------------------------------- " << endl; - cout << endl; - if (ls == "sludist") + if (implicit) { - cout << " Linear solver options:" << endl; + cout << " ARKStep options:" << endl; cout << " --------------------------------- " << endl; + cout << " order = " << order << endl; + cout << " max steps = " << maxsteps << endl; + cout << " linear RHS = " << linear << endl; + cout << " --------------------------------- " << endl; + cout << endl; + if (ls == "sludist") + { + cout << " Linear solver options:" << endl; + cout << " --------------------------------- " << endl; #if defined(HAVE_HIP) - cout << " LS = SuperLU_DIST (HIP enabled)" << endl; + cout << " LS = SuperLU_DIST (HIP enabled)" << endl; #elif defined(HAVE_CUDA) - cout << " LS = SuperLU_DIST (CUDA enabled)" << endl; + cout << " LS = SuperLU_DIST (CUDA enabled)" << endl; #else - cout << " LS = SuperLU_DIST" << endl; + cout << " LS = SuperLU_DIST" << endl; #endif - cout << " LS info = " << lsinfo << endl; - cout << " msbp = " << msbp << endl; - cout << " --------------------------------- " << endl; + cout << " LS info = " << lsinfo << endl; + cout << " msbp = " << msbp << endl; + cout << " --------------------------------- " << endl; + } + else + { + cout << " Linear solver options:" << endl; + cout << " --------------------------------- " << endl; + cout << " LS = " << ls << endl; + cout << " precond = " << preconditioning << endl; + cout << " LS info = " << lsinfo << endl; + cout << " LS iters = " << liniters << endl; + cout << " msbp = " << msbp << endl; + cout << " epslin = " << epslin << endl; + cout << " --------------------------------- " << endl; + } } else { - cout << " Linear solver options:" << endl; + cout << " LSRKStep options:" << endl; cout << " --------------------------------- " << endl; - cout << " LS = " << ls << endl; - cout << " precond = " << preconditioning << endl; - cout << " LS info = " << lsinfo << endl; - cout << " LS iters = " << liniters << endl; - cout << " msbp = " << msbp << endl; - cout << " epslin = " << epslin << endl; + switch (lsrkmethod) + { + case (ARKODE_LSRK_RKC_2): cout << " method = RKC_2 " << endl; break; + case (ARKODE_LSRK_RKL_2): cout << " method = RKL_2 " << endl; break; + default: cout << " ERROR: illegal lsrkmethod " << endl; + } cout << " --------------------------------- " << endl; } } diff --git a/doc/arkode/guide/source/Constants.rst b/doc/arkode/guide/source/Constants.rst index 22363ef243..695a517ee5 100644 --- a/doc/arkode/guide/source/Constants.rst +++ b/doc/arkode/guide/source/Constants.rst @@ -317,6 +317,25 @@ contains the ARKODE output constants. +-----------------------------------------------+------------------------------------------------------------+ | | | +-----------------------------------------------+------------------------------------------------------------+ + | **LSRK method types** | | + +-----------------------------------------------+------------------------------------------------------------+ + | :index:`ARKODE_LSRK_RKC_2` | 2nd order Runge-Kutta-Chebyshev (RKC) method | + | | :c:enumerator:`ARKODE_LSRK_RKC_2` | + +-----------------------------------------------+------------------------------------------------------------+ + | :index:`ARKODE_LSRK_RKL_2` | 2nd order Runge-Kutta-Legendre (RKL) method | + | | :c:enumerator:`ARKODE_LSRK_RKL_2` | + +-----------------------------------------------+------------------------------------------------------------+ + | :index:`ARKODE_LSRK_SSP_S_2` | Optimal 2nd order s-stage SSP RK method | + | | :c:enumerator:`ARKODE_LSRK_SSP_S_2` | + +-----------------------------------------------+------------------------------------------------------------+ + | :index:`ARKODE_LSRK_SSP_S_3` | Optimal 3rd order s-stage SSP RK method | + | | :c:enumerator:`ARKODE_LSRK_SSP_S_3` | + +-----------------------------------------------+------------------------------------------------------------+ + | :index:`ARKODE_LSRK_SSP_10_4` | Optimal 4th order 10-stage SSP RK method | + | | :c:enumerator:`ARKODE_LSRK_SSP_10_4` | + +-----------------------------------------------+------------------------------------------------------------+ + | | | + +-----------------------------------------------+------------------------------------------------------------+ | **MRI method types** | | +-----------------------------------------------+------------------------------------------------------------+ | :index:`MRISTEP_EXPLICIT` | Use an explicit (at the slow time scale) MRI method. | @@ -538,6 +557,12 @@ contains the ARKODE output constants. | :index:`ARK_STEPPER_UNSUPPORTED` | -48 | An operation was not supported by the current | | | | time-stepping module. | +-------------------------------------+------+------------------------------------------------------------+ + | :index:`ARK_DOMEIG_FAIL` | -49 | The dominant eigenvalue function failed. It is either not | + | | | provided or returns an illegal value. | + +-------------------------------------+------+------------------------------------------------------------+ + | :index:`ARK_MAX_STAGE_LIMIT_FAIL` | -50 | Stepper failed to achieve stable results. Either reduce | + | | | the step size or increase the stage_max_limit | + +-------------------------------------+------+------------------------------------------------------------+ | :index:`ARK_UNRECOGNIZED_ERROR` | -99 | An unknown error was encountered. | +-------------------------------------+------+------------------------------------------------------------+ | | diff --git a/doc/arkode/guide/source/Mathematics.rst b/doc/arkode/guide/source/Mathematics.rst index 9d9835c53d..10a053b879 100644 --- a/doc/arkode/guide/source/Mathematics.rst +++ b/doc/arkode/guide/source/Mathematics.rst @@ -61,13 +61,15 @@ for interpolated solution output. We then discuss the current suite of time-stepping modules supplied with ARKODE, including the ARKStep module for :ref:`additive Runge--Kutta methods `, the ERKStep module that is optimized for :ref:`explicit Runge--Kutta -methods `, and the MRIStep module for :ref:`multirate -infinitesimal step (MIS), multirate infinitesimal GARK (MRI-GARK), and -implicit-explicit MRI-GARK (IMEX-MRI-GARK) methods `. -We then discuss the :ref:`adaptive temporal error controllers -` shared by the time-stepping modules, including -discussion of our choice of norms for measuring errors within various components -of the solver. +methods `, the SPRKStep module that provides +:ref:`symplectic partitioned Runge--Kutta methods ` +for Hamiltonian dynamics, the MRIStep module that provides a variety of +:ref:`multirate infinitesimal methods `, and the +LSRKStep module that supports :ref:`low-storage Runge--Kutta methods +`. We then discuss the :ref:`adaptive temporal +error controllers ` shared by the time-stepping +modules, including discussion of our choice of norms for measuring errors +within various components of the solver. We then discuss the nonlinear and linear solver strategies used by ARKODE for solving implicit algebraic systems that arise in computing each @@ -729,6 +731,61 @@ may supply their own method by defining and attaching a coupling table, see :numref:`ARKODE.Usage.MRIStep.MRIStepCoupling` for more information. +.. _ARKODE.Mathematics.LSRK: + +LSRKStep -- Low-Storage Runge--Kutta methods +============================================ + +The LSRKStep time-stepping module in ARKODE supports a variety of so-called +"low-storage" Runge--Kutta (LSRK) methods, :cite:p:`VSH:04, MBA:14, K:08, FCS:22`. This category includes traditional explicit +fixed-step and low-storage Runge--Kutta methods, adaptive +low-storage Runge--Kutta methods, and others. These are characterized by coefficient tables +that have an exploitable structure, such that their implementation does not require +that all stages be stored simultaneously. At present, this module supports explicit, +adaptive "super-time-stepping" (STS) and "strong-stability-preserving" (SSP) methods. + +The LSRK time-stepping module in ARKODE currently supports IVP +of the form :eq:`ARKODE_IVP_simple_explicit`, i.e., unlike the more general problem form :eq:`ARKODE_IMEX_IVP`, LSRKStep +requires that problems have an identity mass matrix (i.e., :math:`M(t)=I`) +and that the right-hand side function is not split into separate +components. + +LSRKStep currently supports two families of second-order, explicit, and temporally adaptive STS methods: +Runge--Kutta--Chebyshev (RKC), :cite:p:`VSH:04` and Runge--Kutta--Legendre (RKL), :cite:p:`MBA:14`. These methods have the form + +.. math:: + z_0 &= y_n,\\ + z_1 &= z_0 + h \tilde{\mu}_1 f(t_n,z_0),\\ + z_j &= (1-\mu_j-\nu_j)z_0 + \mu_j z_{j-1} + \nu_jz_{j-2} + h \tilde{\gamma}_j f(t_n,z_0) + h \tilde{\mu}_j f(t_n + c_{j-1}h, z_{j-1}) \\ + y_{n+1} &= z_s. + :label: ARKODE_RKC_RKL + +The corresponding coefficients can be found in :cite:p:`VSH:04` and :cite:p:`MBA:14`, respectively. + +LSRK methods of STS type are designed for stiff problems characterized by +having Jacobians with eigenvalues that have large real and small imaginary parts. +While those problems are traditionally treated using implicit methods, STS methods +are explicit. To achieve stability for these stiff problems, STS methods use more stages than +conventional Runge-Kutta methods to extend the stability region along the negative +real axis. The extent of this stability region is proportional to the square of the number +of stages used. + +LSRK methods of the SSP type are designed to preserve the so-called "strong-stability" properties of advection-type equations. +For details, see :cite:p:`K:08`. +The SSPRK methods in ARKODE use the following Shu--Osher representation :cite:p:`SO:88` of explicit Runge--Kutta methods: + +.. math:: + z_1 &= y_n,\\ + z_i &= \sum_{j = 1}^{i-1} \left(\alpha_{i,j}y_j + \beta_{i,j}h f(t_n + c_jh, z_j)\right),\\ + y_{n+1} &= z_s. + :label: ARKODE_SSP + +The coefficients of the Shu--Osher representation are not uniquely determined by the Butcher table :cite:p:`SR:02`. +In particular, the methods SSP(s,2), SSP(s,3), and SSP(10,4) implemented herein and presented in +:cite:p:`K:08` have "almost" all zero coefficients appearing in :math:`\alpha_{i,i-1}` and +:math:`\beta_{i,i-1}`. This feature facilitates their implementation in a low-storage manner. The +corresponding coefficients and embedding weights can be found in :cite:p:`K:08` and :cite:p:`FCS:22`, respectively. + .. _ARKODE.Mathematics.Error.Norm: Error norms diff --git a/doc/arkode/guide/source/Usage/ARKStep/User_callable.rst b/doc/arkode/guide/source/Usage/ARKStep/User_callable.rst index bef540030c..0795c81651 100644 --- a/doc/arkode/guide/source/Usage/ARKStep/User_callable.rst +++ b/doc/arkode/guide/source/Usage/ARKStep/User_callable.rst @@ -98,7 +98,7 @@ ARKStep tolerance specification functions * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory was ``NULL`` * *ARK_NO_MALLOC* if the ARKStep memory was not allocated by the time-stepping module - * *ARK_ILL_INPUT* if an argument has an illegal value (e.g. a negative tolerance). + * *ARK_ILL_INPUT* if an argument had an illegal value (e.g. a negative tolerance). .. deprecated:: 6.1.0 @@ -121,7 +121,7 @@ ARKStep tolerance specification functions * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory was ``NULL`` * *ARK_NO_MALLOC* if the ARKStep memory was not allocated by the time-stepping module - * *ARK_ILL_INPUT* if an argument has an illegal value (e.g. a negative tolerance). + * *ARK_ILL_INPUT* if an argument had an illegal value (e.g. a negative tolerance). .. deprecated:: 6.1.0 @@ -161,7 +161,7 @@ ARKStep tolerance specification functions * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory was ``NULL`` * *ARK_NO_MALLOC* if the ARKStep memory was not allocated by the time-stepping module - * *ARK_ILL_INPUT* if an argument has an illegal value (e.g. a negative tolerance). + * *ARK_ILL_INPUT* if an argument had an illegal value (e.g. a negative tolerance). .. deprecated:: 6.1.0 @@ -181,7 +181,7 @@ ARKStep tolerance specification functions * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory was ``NULL`` * *ARK_NO_MALLOC* if the ARKStep memory was not allocated by the time-stepping module - * *ARK_ILL_INPUT* if an argument has an illegal value (e.g. a negative tolerance). + * *ARK_ILL_INPUT* if an argument had an illegal value (e.g. a negative tolerance). .. deprecated:: 6.1.0 @@ -536,7 +536,7 @@ Optional inputs for ARKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Does not change the *user_data* pointer or any @@ -572,7 +572,7 @@ Optional inputs for ARKStep * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory or interpolation module are ``NULL`` * *ARK_INTERP_FAIL* if this is called after :c:func:`ARKStepEvolve()` - * *ARK_ILL_INPUT* if an argument has an illegal value or the + * *ARK_ILL_INPUT* if an argument had an illegal value or the interpolation module has already been initialized **Notes:** @@ -622,7 +622,7 @@ Optional inputs for ARKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** This parameter can be ``stdout`` or ``stderr``, although the @@ -651,7 +651,7 @@ Optional inputs for ARKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Pass 0.0 to return ARKStep to the default (adaptive-step) mode. @@ -712,7 +712,7 @@ Optional inputs for ARKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Pass 0.0 to use the default value. @@ -742,7 +742,7 @@ Optional inputs for ARKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** The default value is 10; set *mxhnil* to zero to specify @@ -768,7 +768,7 @@ Optional inputs for ARKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Passing *mxsteps* = 0 results in ARKStep using the @@ -792,7 +792,7 @@ Optional inputs for ARKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Pass *hmax* :math:`\le 0.0` to set the default value of :math:`\infty`. @@ -813,7 +813,7 @@ Optional inputs for ARKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Pass *hmin* :math:`\le 0.0` to set the default value of 0. @@ -835,7 +835,7 @@ Optional inputs for ARKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** The default is that no stop time is imposed. @@ -908,7 +908,7 @@ Optional inputs for ARKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** If specified, the pointer to *user_data* is passed to all @@ -936,7 +936,7 @@ Optional inputs for ARKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** The default value is 7; set *maxnef* :math:`\le 0` @@ -959,7 +959,7 @@ Optional inputs for ARKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Should only be called after the method order and integration @@ -1214,7 +1214,7 @@ Set additive RK tables via their names :c:func:`ARKStepSetTableName()` int **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** For explicit methods, the allowed values are :math:`2 \le` @@ -1243,7 +1243,7 @@ Set additive RK tables via their names :c:func:`ARKStepSetTableName()` int **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** This is automatically deduced when neither of the function @@ -1263,7 +1263,7 @@ Set additive RK tables via their names :c:func:`ARKStepSetTableName()` int **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** This is automatically deduced when the function pointer `fi` @@ -1286,7 +1286,7 @@ Set additive RK tables via their names :c:func:`ARKStepSetTableName()` int **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** This is automatically deduced when the function pointer `fe` @@ -1309,7 +1309,7 @@ Set additive RK tables via their names :c:func:`ARKStepSetTableName()` int **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** For a description of the :c:type:`ARKodeButcherTable` type and related @@ -1366,7 +1366,7 @@ Set additive RK tables via their names :c:func:`ARKStepSetTableName()` int **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** The allowable values for both the *itable* and *etable* arguments @@ -1408,7 +1408,7 @@ Set additive RK tables via their names :c:func:`ARKStepSetTableName()` int **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** The allowable values for both the *itable* and *etable* arguments @@ -1477,7 +1477,7 @@ Optional inputs for time step adaptivity **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** This function should focus on accuracy-based time step @@ -1515,7 +1515,7 @@ Optional inputs for time step adaptivity **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** If custom parameters are supplied, they will be checked @@ -1549,7 +1549,7 @@ Optional inputs for time step adaptivity **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** This should be called prior to calling :c:func:`ARKStepEvolve()`, and can only be @@ -1574,7 +1574,7 @@ Optional inputs for time step adaptivity **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any non-positive parameter will imply a reset to the default @@ -1598,7 +1598,7 @@ Optional inputs for time step adaptivity **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any value below 1.0 will imply a reset to the default value. @@ -1624,7 +1624,7 @@ Optional inputs for time step adaptivity **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any interval *not* containing 1.0 will imply a reset to the default values. @@ -1648,7 +1648,7 @@ Optional inputs for time step adaptivity **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any value outside the interval :math:`(0,1]` will imply a reset to the default value. @@ -1670,7 +1670,7 @@ Optional inputs for time step adaptivity **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any value outside the interval :math:`(0,1]` will imply a reset to the default value. @@ -1693,7 +1693,7 @@ Optional inputs for time step adaptivity **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any value :math:`\le 1.0` will imply a reset to the default value. @@ -1715,7 +1715,7 @@ Optional inputs for time step adaptivity **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any value :math:`\le 1.0` will imply a reset to the default @@ -1740,7 +1740,7 @@ Optional inputs for time step adaptivity **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any value outside the interval :math:`(0,1)` will imply a reset to @@ -1763,7 +1763,7 @@ Optional inputs for time step adaptivity **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any value :math:`\le 0` will imply a reset to the default @@ -1787,7 +1787,7 @@ Optional inputs for time step adaptivity **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any value :math:`\le 0` will imply a reset to the default value. @@ -1811,7 +1811,7 @@ Optional inputs for time step adaptivity **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** This function should return an estimate of the absolute @@ -1845,7 +1845,7 @@ Optional inputs for implicit stage solves **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Tightens the linear solver tolerances and takes only a @@ -1876,7 +1876,7 @@ Optional inputs for implicit stage solves **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** This is the default behavior of ARKStep, so the function @@ -1922,7 +1922,7 @@ Optional inputs for implicit stage solves **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** The default value is 0. If *method* is set to an @@ -2001,7 +2001,7 @@ Optional inputs for implicit stage solves **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value or if the SUNNONLINSOL module is ``NULL`` + * *ARK_ILL_INPUT* if an argument had an illegal value or if the SUNNONLINSOL module is ``NULL`` * *ARK_NLS_OP_ERR* if the SUNNONLINSOL object returned a failure flag **Notes:** @@ -2025,7 +2025,7 @@ Optional inputs for implicit stage solves **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** The default value is 0.1; set *nlscoef* :math:`\le 0` @@ -2047,7 +2047,7 @@ Optional inputs for implicit stage solves **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any non-positive parameter will imply a reset to the default value. @@ -2070,7 +2070,7 @@ Optional inputs for implicit stage solves **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any non-positive parameter will imply a reset to the default value. @@ -2095,7 +2095,7 @@ Optional inputs for implicit stage solves **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** The default value is 10; set *maxncf* :math:`\le 0` @@ -2162,7 +2162,7 @@ Optional inputs for the ARKLS linear solver interface **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any non-positive parameter will imply a reset to the default value. @@ -2321,7 +2321,7 @@ Optional inputs for matrix-based ``SUNLinearSolver`` modules * *ARKLS_SUCCESS* if successful * *ARKLS_MEM_NULL* if the ARKStep memory was ``NULL`` * *ARKLS_MASSMEM_NULL* if the mass matrix solver memory was ``NULL`` - * *ARKLS_ILL_INPUT* if an argument has an illegal value + * *ARKLS_ILL_INPUT* if an argument had an illegal value **Notes:** This routine must be called after the ARKLS mass matrix @@ -2701,7 +2701,7 @@ Rootfinding optional input functions **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** The default behavior is to monitor for both zero-crossing directions. @@ -4225,7 +4225,7 @@ vector. * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory was ``NULL`` * *ARK_MEM_FAIL* if a memory allocation failed - * *ARK_ILL_INPUT* if an argument has an illegal value. + * *ARK_ILL_INPUT* if an argument had an illegal value. **Notes:** All previously set options are retained but may be updated by calling @@ -4257,7 +4257,7 @@ ARKStep reset function * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory was ``NULL`` * *ARK_MEM_FAIL* if a memory allocation failed - * *ARK_ILL_INPUT* if an argument has an illegal value. + * *ARK_ILL_INPUT* if an argument had an illegal value. **Notes:** By default the next call to :c:func:`ARKStepEvolve()` will use the step size @@ -4304,7 +4304,7 @@ ARKStep system resize function * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ARKStep memory was ``NULL`` * *ARK_NO_MALLOC* if *arkode_mem* was not allocated. - * *ARK_ILL_INPUT* if an argument has an illegal value. + * *ARK_ILL_INPUT* if an argument had an illegal value. **Notes:** If an error occurred, :c:func:`ARKStepResize()` also sends an error @@ -4375,7 +4375,7 @@ wrap an ARKStep memory block as an :c:type:`MRIStepInnerStepper`. **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_FAIL* if a memory allocation failed - * *ARK_ILL_INPUT* if an argument has an illegal value. + * *ARK_ILL_INPUT* if an argument had an illegal value. **Example usage:** .. code-block:: C diff --git a/doc/arkode/guide/source/Usage/ERKStep/User_callable.rst b/doc/arkode/guide/source/Usage/ERKStep/User_callable.rst index 6c7b7b9cdf..1f4dc8f140 100644 --- a/doc/arkode/guide/source/Usage/ERKStep/User_callable.rst +++ b/doc/arkode/guide/source/Usage/ERKStep/User_callable.rst @@ -95,7 +95,7 @@ ERKStep tolerance specification functions * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory was ``NULL`` * *ARK_NO_MALLOC* if the ERKStep memory was not allocated by the time-stepping module - * *ARK_ILL_INPUT* if an argument has an illegal value (e.g. a negative tolerance). + * *ARK_ILL_INPUT* if an argument had an illegal value (e.g. a negative tolerance). .. deprecated:: 6.1.0 @@ -119,7 +119,7 @@ ERKStep tolerance specification functions * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory was ``NULL`` * *ARK_NO_MALLOC* if the ERKStep memory was not allocated by the time-stepping module - * *ARK_ILL_INPUT* if an argument has an illegal value (e.g. a negative tolerance). + * *ARK_ILL_INPUT* if an argument had an illegal value (e.g. a negative tolerance). .. deprecated:: 6.1.0 @@ -312,7 +312,7 @@ Optional inputs for ERKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Does not change problem-defining function pointer *f* @@ -350,7 +350,7 @@ Optional inputs for ERKStep * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory or interpolation module are ``NULL`` * *ARK_INTERP_FAIL* if this is called after :c:func:`ERKStepEvolve()` - * *ARK_ILL_INPUT* if an argument has an illegal value or the + * *ARK_ILL_INPUT* if an argument had an illegal value or the interpolation module has already been initialized **Notes:** @@ -402,7 +402,7 @@ Optional inputs for ERKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** This parameter can be ``stdout`` or ``stderr``, although the @@ -431,7 +431,7 @@ Optional inputs for ERKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Pass 0.0 to return ERKStep to the default (adaptive-step) mode. @@ -491,7 +491,7 @@ Optional inputs for ERKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Pass 0.0 to use the default value. @@ -522,7 +522,7 @@ Optional inputs for ERKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** The default value is 10; set *mxhnil* to zero to specify @@ -549,7 +549,7 @@ Optional inputs for ERKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Passing *mxsteps* = 0 results in ERKStep using the @@ -574,7 +574,7 @@ Optional inputs for ERKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Pass *hmax* :math:`\le 0.0` to set the default value of :math:`\infty`. @@ -596,7 +596,7 @@ Optional inputs for ERKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Pass *hmin* :math:`\le 0.0` to set the default value of 0. @@ -619,7 +619,7 @@ Optional inputs for ERKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** The default is that no stop time is imposed. @@ -650,7 +650,7 @@ Optional inputs for ERKStep **Return value:** * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` + * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` .. versionadded:: 5.6.0 @@ -695,7 +695,7 @@ Optional inputs for ERKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** If specified, the pointer to *user_data* is passed to all @@ -720,7 +720,7 @@ Optional inputs for ERKStep **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** The default value is 7; set *maxnef* :math:`\le 0` @@ -836,7 +836,7 @@ Optional inputs for IVP method selection **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** The allowed values are :math:`2 \le` *ord* :math:`\le @@ -863,7 +863,7 @@ Optional inputs for IVP method selection **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** @@ -896,7 +896,7 @@ Optional inputs for IVP method selection **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** *etable* should match an existing explicit method from @@ -919,7 +919,7 @@ Optional inputs for IVP method selection **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** *etable* should match an existing explicit method from @@ -982,7 +982,7 @@ the code, is provided in :numref:`ARKODE.Mathematics.Adaptivity`. **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** This function should focus on accuracy-based time step @@ -1019,7 +1019,7 @@ the code, is provided in :numref:`ARKODE.Mathematics.Adaptivity`. **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** If custom parameters are supplied, they will be checked @@ -1051,7 +1051,7 @@ the code, is provided in :numref:`ARKODE.Mathematics.Adaptivity`. **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** This should be called prior to calling :c:func:`ERKStepEvolve()`, and can only be @@ -1076,7 +1076,7 @@ the code, is provided in :numref:`ARKODE.Mathematics.Adaptivity`. **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any non-positive parameter will imply a reset to the default @@ -1101,7 +1101,7 @@ the code, is provided in :numref:`ARKODE.Mathematics.Adaptivity`. **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any value below 1.0 will imply a reset to the default value. @@ -1128,7 +1128,7 @@ the code, is provided in :numref:`ARKODE.Mathematics.Adaptivity`. **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any interval *not* containing 1.0 will imply a reset to the default values. @@ -1151,7 +1151,7 @@ the code, is provided in :numref:`ARKODE.Mathematics.Adaptivity`. **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any value outside the interval :math:`(0,1]` will imply a reset to the default value. @@ -1175,7 +1175,7 @@ the code, is provided in :numref:`ARKODE.Mathematics.Adaptivity`. **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any value :math:`\le 1.0` will imply a reset to the default value. @@ -1198,7 +1198,7 @@ the code, is provided in :numref:`ARKODE.Mathematics.Adaptivity`. **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any value :math:`\le 1.0` will imply a reset to the default @@ -1224,7 +1224,7 @@ the code, is provided in :numref:`ARKODE.Mathematics.Adaptivity`. **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any value :math:`\ge 1.0` or :math:`\le 0.0` will imply a reset to @@ -1248,7 +1248,7 @@ the code, is provided in :numref:`ARKODE.Mathematics.Adaptivity`. **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any non-positive parameter will imply a reset to the default @@ -1273,7 +1273,7 @@ the code, is provided in :numref:`ARKODE.Mathematics.Adaptivity`. **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any non-positive parameter will imply a reset to the default value. @@ -1298,7 +1298,7 @@ the code, is provided in :numref:`ARKODE.Mathematics.Adaptivity`. **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** This function should return an estimate of the absolute @@ -1338,7 +1338,7 @@ Rootfinding optional input functions **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** The default behavior is to monitor for both zero-crossing directions. @@ -1877,7 +1877,7 @@ Main solver optional output functions **Return value:** * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the ARKStep memory was ``NULL`` + * *ARK_MEM_NULL* if the ERKStep memory was ``NULL`` .. versionadded:: 5.3.0 @@ -2016,7 +2016,7 @@ user must call the function :c:func:`ERKStepReInit()`. The new problem must have the same size as the previous one. This routine retains the current settings for all ERKstep module options and performs the same input checking and initializations that are done in -:c:func:`ERKStepCreate`, but it performs no memory allocation as is +:c:func:`ERKStepCreate`, but it performs no memory allocation as it assumes that the existing internal memory is sufficient for the new problem. A call to this re-initialization routine deletes the solution history that was stored internally during the previous @@ -2065,7 +2065,7 @@ vector. * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory was ``NULL`` * *ARK_MEM_FAIL* if a memory allocation failed - * *ARK_ILL_INPUT* if an argument has an illegal value. + * *ARK_ILL_INPUT* if an argument had an illegal value. **Notes:** All previously set options are retained but may be updated by calling @@ -2097,7 +2097,7 @@ ERKStep reset function * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory was ``NULL`` * *ARK_MEM_FAIL* if a memory allocation failed - * *ARK_ILL_INPUT* if an argument has an illegal value. + * *ARK_ILL_INPUT* if an argument had an illegal value. **Notes:** By default the next call to :c:func:`ERKStepEvolve()` will use the step size @@ -2146,7 +2146,7 @@ ERKStep system resize function * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the ERKStep memory was ``NULL`` * *ARK_NO_MALLOC* if *arkode_mem* was not allocated. - * *ARK_ILL_INPUT* if an argument has an illegal value. + * *ARK_ILL_INPUT* if an argument had an illegal value. **Notes:** If an error occurred, :c:func:`ERKStepResize()` also sends an error diff --git a/doc/arkode/guide/source/Usage/General.rst b/doc/arkode/guide/source/Usage/General.rst index c0980dfcee..745e9e9ed9 100644 --- a/doc/arkode/guide/source/Usage/General.rst +++ b/doc/arkode/guide/source/Usage/General.rst @@ -56,7 +56,8 @@ to the SUNDIALS core header file. #include // ARKStep provides explicit, implicit, IMEX additive RK methods. #include // MRIStep provides mutlirate RK methods. #include // SPRKStep provides symplectic partition RK methods. - + #include // LSRKStep provides low-storage RK methods. + Each of these define several types and various constants, include function prototypes, and include the shared ``arkode/arkode.h`` and ``arkode/arkode_ls.h`` header files. No other header files are required to be diff --git a/doc/arkode/guide/source/Usage/LSRKStep/User_callable.rst b/doc/arkode/guide/source/Usage/LSRKStep/User_callable.rst new file mode 100644 index 0000000000..a08e5918b4 --- /dev/null +++ b/doc/arkode/guide/source/Usage/LSRKStep/User_callable.rst @@ -0,0 +1,389 @@ +.. ---------------------------------------------------------------- + Programmer(s): Mustafa Aggul @ SMU + ---------------------------------------------------------------- + SUNDIALS Copyright Start + Copyright (c) 2002-2024, Lawrence Livermore National Security + and Southern Methodist University. + All rights reserved. + + See the top-level LICENSE and NOTICE files for details. + + SPDX-License-Identifier: BSD-3-Clause + SUNDIALS Copyright End + ---------------------------------------------------------------- + +.. _ARKODE.Usage.LSRKStep.UserCallable: + +LSRKStep User-callable functions +================================== + +This section describes the LSRKStep-specific functions that may be called +by the user to setup and then solve an IVP using the LSRKStep time-stepping +module. As mentioned in Section :numref:`ARKODE.Usage.UserCallable`, +shared ARKODE-level routines may be used for the large majority of LSRKStep +configuration and use. In this section, we describe only those routines +that are specific to LSRKStep. + +As discussed in the main :ref:`ARKODE user-callable function introduction +`, each of ARKODE's time-stepping modules +clarifies the categories of user-callable functions that it supports. +LSRKStep supports the following categories: + +* temporal adaptivity + + + +.. _ARKODE.Usage.LSRKStep.Initialization: + +LSRKStep initialization functions +--------------------------------- + + +.. c:function:: void* LSRKStepCreateSTS(ARKRhsFn rhs, sunrealtype t0, N_Vector y0, SUNContext sunctx); + + This function allocates and initializes memory for a problem to + be solved using STS methods from the LSRKStep time-stepping module in ARKODE. + + **Arguments:** + * *rhs* -- the name of the C function (of type :c:func:`ARKRhsFn()`) + defining the right-hand side function. + * *t0* -- the initial value of :math:`t`. + * *y0* -- the initial condition vector :math:`y(t_0)`. + * *sunctx* -- the :c:type:`SUNContext` object (see :numref:`SUNDIALS.SUNContext`) + + **Return value:** + If successful, a pointer to initialized problem memory + of type ``void*``, to be passed to all user-facing LSRKStep routines + listed below. If unsuccessful, a ``NULL`` pointer will be + returned, and an error message will be printed to ``stderr``. + + +.. c:function:: void* LSRKStepCreateSSP(ARKRhsFn rhs, sunrealtype t0, N_Vector y0, SUNContext sunctx); + + This function allocates and initializes memory for a problem to + be solved using SSP methods from the LSRKStep time-stepping module in ARKODE. + + **Arguments:** + * *rhs* -- the name of the C function (of type :c:func:`ARKRhsFn()`) + defining the right-hand side function. + * *t0* -- the initial value of :math:`t`. + * *y0* -- the initial condition vector :math:`y(t_0)`. + * *sunctx* -- the :c:type:`SUNContext` object (see :numref:`SUNDIALS.SUNContext`) + + **Return value:** + If successful, a pointer to initialized problem memory + of type ``void*``, to be passed to all user-facing LSRKStep routines + listed below. If unsuccessful, a ``NULL`` pointer will be + returned, and an error message will be printed to ``stderr``. + + +.. _ARKODE.Usage.LSRKStep.OptionalInputs: + +Optional input functions +------------------------- + + +.. c:function:: int LSRKStepSetSTSMethod(void* arkode_mem, ARKODE_LSRKMethodType method); + + This function selects the LSRK STS method that should be used. The list of allowable + values for this input is below. :c:func:`LSRKStepCreateSTS` defaults to using + :c:enumerator:`ARKODE_LSRK_RKC_2`. + + **Arguments:** + * *arkode_mem* -- pointer to the LSRKStep memory block. + * *method* -- Type of the method. + + **Return value:** + * *ARK_SUCCESS* if successful + * *ARK_ILL_INPUT* if an argument had an illegal value (e.g. typo in the method type). + + +.. c:function:: int LSRKStepSetSSPMethod(void* arkode_mem, ARKODE_LSRKMethodType method); + + This function selects the LSRK SSP method that should be used. The list of allowable + values for this input is below. :c:func:`LSRKStepCreateSSP` defaults to using + :c:enumerator:`ARKODE_LSRK_SSP_S_2`. + + **Arguments:** + * *arkode_mem* -- pointer to the LSRKStep memory block. + * *method* -- Type of the method. + + **Return value:** + * *ARK_SUCCESS* if successful + * *ARK_ILL_INPUT* if an argument had an illegal value (e.g. typo in the method type). + + +Allowable Method Families + +.. c:enum:: ARKODE_LSRKMethodType + + .. c:enumerator:: ARKODE_LSRK_RKC_2 + + Second order Runge--Kutta--Chebyshev method + + .. c:enumerator:: ARKODE_LSRK_RKL_2 + + Second order Runge--Kutta--Legendre method + + .. c:enumerator:: ARKODE_LSRK_SSP_S_2 + + Second order, s-stage SSP(s,2) method + + .. c:enumerator:: ARKODE_LSRK_SSP_S_3 + + Third order, s-stage SSP(s,3) method + + .. c:enumerator:: ARKODE_LSRK_SSP_10_4 + + Fourth order, 10-stage SSP(10,4) method + + +.. c:function:: int LSRKStepSetSTSMethodByName(void* arkode_mem, const char* emethod); + + This function selects the LSRK STS method by name. The list of allowable values + for this input is above. :c:func:`LSRKStepCreateSTS` defaults to using + :c:enumerator:`ARKODE_LSRK_RKC_2`. + + **Arguments:** + * *arkode_mem* -- pointer to the LSRKStep memory block. + * *emethod* -- the method name. + + **Return value:** + * *ARK_SUCCESS* if successful + * *ARK_ILL_INPUT* if an argument had an illegal value (e.g. typo in the method name). + + +.. c:function:: int LSRKStepSetSSPMethodByName(void* arkode_mem, const char* emethod); + + This function selects the LSRK SSP method by name. The list of allowable values + for this input is above. :c:func:`LSRKStepCreateSSP` defaults to using + :c:enumerator:`ARKODE_LSRK_SSP_S_2`. + + **Arguments:** + * *arkode_mem* -- pointer to the LSRKStep memory block. + * *emethod* -- the method name. + + **Return value:** + * *ARK_SUCCESS* if successful + * *ARK_ILL_INPUT* if an argument had an illegal value (e.g. typo in the method name). + + +.. c:function:: int LSRKStepSetDomEigFn(void* arkode_mem, ARKDomEigFn dom_eig); + + Specifies the dominant eigenvalue approximation routine to + be used for determining the number of stages that will be used by either the + RKC or RKL methods. + + **Arguments:** + * *arkode_mem* -- pointer to the LSRKStep memory block. + * *dom_eig* -- name of user-supplied dominant eigenvalue approximation function (of type :c:func:`ARKDomEigFn()`). + + **Return value:** + * *ARK_SUCCESS* if successful + * *ARKLS_MEM_NULL* if ``arkode_mem`` was ``NULL``. + * *ARK_ILL_INPUT* ``dom_eig = NULL`` and LSRKStep does not currently estimate this internally. + + .. note:: This function is currently required when either the RKC or RKL methods are used. + + +.. c:function:: int LSRKStepSetDomEigFrequency(void* arkode_mem, long int nsteps); + + Specifies the number of steps after which the dominant eigenvalue information is + considered out-of-date, and should be recomputed. This only applies to RKL and RKC methods. + + **Arguments:** + * *arkode_mem* -- pointer to the LSRKStep memory block. + * *nsteps* -- the dominant eigenvalue re-computation update frequency. A value ``nsteps = 0`` indicates that the dominant eigenvalue will not change throughout the simulation. + + **Return value:** + * *ARK_SUCCESS* if successful + * *ARKLS_MEM_NULL* if ``arkode_mem`` was ``NULL``. + +.. note:: If LSRKStepSetDomEigFrequency routine is not called, then the default ``nsteps`` is set to :math:`25` as recommended in :cite:p:`VSH:04`. + Calling this function with ``nsteps < 0`` resets the default value while ``nsteps = 0`` refers to constant dominant eigenvalue. + + +.. c:function:: int LSRKStepSetMaxNumStages(void* arkode_mem, int stage_max_limit); + + Specifies the maximum number of stages allowed within each time step. This bound only applies to + RKL and RKC methods. + + **Arguments:** + * *arkode_mem* -- pointer to the LSRKStep memory block. + * *stage_max_limit* -- maximum allowed number of stages :math:`(>=2)`. + + **Return value:** + * *ARK_SUCCESS* if successful + * *ARKLS_MEM_NULL* if ``arkode_mem`` was ``NULL``. + +.. note:: If LSRKStepSetMaxNumStages routine is not called, then the default ``stage_max_limit`` is + set to :math:`200`. Calling this function with ``stage_max_limit < 2`` resets the default value. + This limit should be chosen with consideration of the following proportionality: :math:`s^2 \sim - h\lambda`, + where :math:`s` is the number of stages used, :math:`h` is the current step size and :math:`\lambda` is the dominant eigenvalue. + + +.. c:function:: int LSRKStepSetDomEigSafetyFactor(void* arkode_mem, sunrealtype dom_eig_safety); + + Specifies a safety factor to use for the result of the dominant eigenvalue estimation function. + This value is used to scale the magnitude of the dominant eigenvalue, in the hope of ensuring + a sufficient number of stages for the method to be stable. This input is only used for RKC + and RKL methods. + + **Arguments:** + * *arkode_mem* -- pointer to the LSRKStep memory block. + * *dom_eig_safety* -- safety factor :math:`(\ge 1)`. + + **Return value:** + * *ARK_SUCCESS* if successful + * *ARKLS_MEM_NULL* if ``arkode_mem`` was ``NULL``. + +.. note:: If LSRKStepSetDomEigSafetyFactor routine is not called, then the default ``dom_eig_safety`` is + set to :math:`1.01`. Calling this function with ``dom_eig_safety < 1`` resets the default value. + + +.. c:function:: int LSRKStepSetSSPStageNum(void* arkode_mem, int num_of_stages); + + Sets the number of stages, ``s`` in ``SSP(s, p)`` methods. This input is only utilized by SSPRK methods. + + * :c:enumerator:`ARKODE_LSRK_SSP_S_2` -- ``num_of_stages`` must be greater than or equal to 2 + * :c:enumerator:`ARKODE_LSRK_SSP_S_3` -- ``num_of_stages`` must be a perfect-square greater than or equal to 4 + * :c:enumerator:`ARKODE_LSRK_SSP_10_4` -- ``num_of_stages`` cannot be modified from 10, so this function should not be called. + + **Arguments:** + * *arkode_mem* -- pointer to the LSRKStep memory block. + * *num_of_stages* -- number of stages :math:`(>1)` for ``SSP(s,2)`` and :math:`(n^2 = s \geq 4)` for ``SSP(s,3)``. + + **Return value:** + * *ARK_SUCCESS* if successful + * *ARKLS_MEM_NULL* if ``arkode_mem`` was ``NULL``. + * *ARK_ILL_INPUT* if an argument had an illegal value (e.g. SSP method is not declared) + +.. note:: If LSRKStepSetSSPStageNum routine is not called, then the default ``num_of_stages`` is + set. Calling this function with ``num_of_stages <= 0`` resets the default values: + + * ``num_of_stages = 10`` for :c:enumerator:`ARKODE_LSRK_SSP_S_2` + * ``num_of_stages = 9`` for :c:enumerator:`ARKODE_LSRK_SSP_S_3` + * ``num_of_stages = 10`` for :c:enumerator:`ARKODE_LSRK_SSP_10_4` + +.. _ARKODE.Usage.LSRKStep.OptionalOutputs: + +Optional output functions +------------------------------ + +.. c:function:: int LSRKStepGetNumDomEigUpdates(void* arkode_mem, long int* dom_eig_num_evals); + + Returns the number of dominant eigenvalue evaluations (so far). + + **Arguments:** + * *arkode_mem* -- pointer to the LSRKStep memory block. + * *dom_eig_num_evals* -- number of calls to the user's ``dom_eig`` function. + + **Return value:** + * *ARK_SUCCESS* if successful + * *ARK_MEM_NULL* if the LSRKStep memory was ``NULL`` + + +.. c:function:: int LSRKStepGetMaxNumStages(void* arkode_mem, int* stage_max); + + Returns the max number of stages used in any single step (so far). + + **Arguments:** + * *arkode_mem* -- pointer to the LSRKStep memory block. + * *stage_max* -- max number of stages used. + + **Return value:** + * *ARK_SUCCESS* if successful + * *ARK_MEM_NULL* if the LSRKStep memory was ``NULL`` + +.. _ARKODE.Usage.LSRKStep.Reinitialization: + +LSRKStep re-initialization function +------------------------------------- + +To reinitialize the LSRKStep module for the solution of a new problem, +where a prior call to :c:func:`LSRKStepCreateSTS` or :c:func:`LSRKStepCreateSSP` +has been made, the user must call the function :c:func:`LSRKStepReInitSTS()` +or :c:func:`LSRKStepReInitSSP()`, accordingly. The new problem must have +the same size as the previous one. This routine retains the current settings +for all LSRKstep module options and performs the same input checking and +initializations that are done in :c:func:`LSRKStepCreateSTS` or +:c:func:`LSRKStepCreateSSP`, but it performs no memory allocation as it +assumes that the existing internal memory is sufficient for the new problem. +A call to this re-initialization routine deletes the solution history that +was stored internally during the previous integration, and deletes any +previously-set *tstop* value specified via a call to +:c:func:`ARKodeSetStopTime()`. Following a successful call to +:c:func:`LSRKStepReInitSTS()` or :c:func:`LSRKStepReInitSSP()`, +call :c:func:`ARKodeEvolve()` again for the solution of the new problem. + +One important use of the :c:func:`LSRKStepReInitSTS()` and +:c:func:`LSRKStepReInitSSP()` function is in the treating of jump +discontinuities in the RHS function. Except in cases of fairly small +jumps, it is usually more efficient to stop at each point of discontinuity +and restart the integrator with a readjusted ODE model, using a call to this +routine. To stop when the location of the discontinuity is known, simply +make that location a value of ``tout``. To stop when the location of +the discontinuity is determined by the solution, use the rootfinding feature. +In either case, it is critical that the RHS function *not* incorporate the +discontinuity, but rather have a smooth extension over the discontinuity, +so that the step across it (and subsequent rootfinding, if used) can be done +efficiently. Then use a switch within the RHS function (communicated through +``user_data``) that can be flipped between the stopping of the integration +and the restart, so that the restarted problem uses the new values (which +have jumped). Similar comments apply if there is to be a jump in the +dependent variable vector. + + +.. c:function:: int LSRKStepReInitSTS(void* arkode_mem, ARKRhsFn rhs, sunrealtype t0, N_Vector y0); + + Provides required problem specifications and re-initializes the + LSRKStep time-stepper module when using STS methods. + + **Arguments:** + * *arkode_mem* -- pointer to the LSRKStep memory block. + * *rhs* -- the name of the C function (of type :c:func:`ARKRhsFn()`) + defining the right-hand side function. + * *t0* -- the initial value of :math:`t`. + * *y0* -- the initial condition vector :math:`y(t_0)`. + + **Return value:** + * *ARK_SUCCESS* if successful + * *ARK_MEM_NULL* if the LSRKStep memory was ``NULL`` + * *ARK_MEM_FAIL* if memory allocation failed + * *ARK_NO_MALLOC* if memory allocation failed + * *ARK_CONTROLLER_ERR* if unable to reset error controller object + * *ARK_ILL_INPUT* if an argument had an illegal value. + + .. note:: + All previously set options are retained but may be updated by calling + the appropriate "Set" functions. + + If an error occurred, :c:func:`LSRKStepReInitSTS()` also + sends an error message to the error handler function. + +.. c:function:: int LSRKStepReInitSSP(void* arkode_mem, ARKRhsFn rhs, sunrealtype t0, N_Vector y0); + + Provides required problem specifications and re-initializes the + LSRKStep time-stepper module when using SSP methods. + + **Arguments:** + * *arkode_mem* -- pointer to the LSRKStep memory block. + * *rhs* -- the name of the C function (of type :c:func:`ARKRhsFn()`) + defining the right-hand side function. + * *t0* -- the initial value of :math:`t`. + * *y0* -- the initial condition vector :math:`y(t_0)`. + + **Return value:** + * *ARK_SUCCESS* if successful + * *ARK_MEM_NULL* if the LSRKStep memory was ``NULL`` + * *ARK_MEM_FAIL* if memory allocation failed + * *ARK_NO_MALLOC* if memory allocation failed + * *ARK_CONTROLLER_ERR* if unable to reset error controller object + * *ARK_ILL_INPUT* if an argument had an illegal value. + + .. note:: + All previously set options are retained but may be updated by calling + the appropriate "Set" functions. + + If an error occurred, :c:func:`LSRKStepReInitSSP()` also + sends an error message to the error handler function. \ No newline at end of file diff --git a/doc/arkode/guide/source/Usage/LSRKStep/User_supplied.rst b/doc/arkode/guide/source/Usage/LSRKStep/User_supplied.rst new file mode 100644 index 0000000000..2363898955 --- /dev/null +++ b/doc/arkode/guide/source/Usage/LSRKStep/User_supplied.rst @@ -0,0 +1,52 @@ +.. ---------------------------------------------------------------- + Programmer(s): Mustafa Aggul @ SMU + ---------------------------------------------------------------- + SUNDIALS Copyright Start + Copyright (c) 2002-2024, Lawrence Livermore National Security + and Southern Methodist University. + All rights reserved. + + See the top-level LICENSE and NOTICE files for details. + + SPDX-License-Identifier: BSD-3-Clause + SUNDIALS Copyright End + ---------------------------------------------------------------- + +.. _LSRKSTEP.Usage.UserSupplied: + +User-supplied functions +============================= + +In addition to the required :c:type:`ARKRhsFn` arguments that define the IVP, +RKL and RKC methods additionally require an :c:type:`ARKDomEigFn` function to +estimate the dominant eigenvalue. + + + + +.. _LSRKStep.Usage.dom_eig: + +The dominant eigenvalue estimation +---------------------------------- + +When running LSRKStep with either the RKC or RKL methods, the user must supply +a dominant eigenvalue estimation function of type :c:type:`ARKDomEigFn`: + +.. c:type:: int (*ARKDomEigFn)(sunrealtype t, N_Vector y, N_Vector fn, sunrealtype* lambdaR, sunrealtype* lambdaI, void* user_data, N_Vector temp1, N_Vector temp2, N_Vector temp3); + + These functions compute the dominant eigenvalue of the Jacobian of the ODE + right-hand side for a given value of the independent variable :math:`t` and + state vector :math:`y`. + + :param t: the current value of the independent variable. + :param y: the current value of the dependent variable vector. + :param fn: the current value of the vector :math:`f(t,y)`. + :param lambdaR: The real part of the dominant eigenvalue. + :param lambdaI: The imaginary part of the dominant eigenvalue. + :param user_data: the `user_data` pointer that was passed to + :c:func:`ARKodeSetUserData`. + :param tmp*: pointers to memory allocated to + variables of type ``N_Vector`` which can be used by an + ARKDomEigFn as temporary storage or work space. + + :return: An *ARKDomEigFn* should return 0 if successful and any nonzero for a failure. \ No newline at end of file diff --git a/doc/arkode/guide/source/Usage/LSRKStep/index.rst b/doc/arkode/guide/source/Usage/LSRKStep/index.rst new file mode 100644 index 0000000000..ca07bfffc3 --- /dev/null +++ b/doc/arkode/guide/source/Usage/LSRKStep/index.rst @@ -0,0 +1,32 @@ +.. ---------------------------------------------------------------- + Programmer(s): Mustafa Aggul @ SMU + ---------------------------------------------------------------- + SUNDIALS Copyright Start + Copyright (c) 2002-2024, Lawrence Livermore National Security + and Southern Methodist University. + All rights reserved. + + See the top-level LICENSE and NOTICE files for details. + + SPDX-License-Identifier: BSD-3-Clause + SUNDIALS Copyright End + ---------------------------------------------------------------- + +.. _ARKODE.Usage.LSRKStep: + +======================================= +Using the LSRKStep time-stepping module +======================================= + +This section is concerned with the use of the LSRKStep time-stepping +module for the solution of initial value problems (IVPs) in a C or C++ +language setting. Usage of LSRKStep follows that of the rest of ARKODE, +and so in this section we primarily focus on those usage aspects that +are specific to LSRKStep. + +.. toctree:: + :maxdepth: 1 + + User_callable + User_supplied + \ No newline at end of file diff --git a/doc/arkode/guide/source/Usage/MRIStep/User_callable.rst b/doc/arkode/guide/source/Usage/MRIStep/User_callable.rst index a6354a6037..967e8e7c12 100644 --- a/doc/arkode/guide/source/Usage/MRIStep/User_callable.rst +++ b/doc/arkode/guide/source/Usage/MRIStep/User_callable.rst @@ -134,7 +134,7 @@ MRIStep tolerance specification functions * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` * *ARK_NO_MALLOC* if the MRIStep memory was not allocated by the time-stepping module - * *ARK_ILL_INPUT* if an argument has an illegal value (e.g. a negative tolerance). + * *ARK_ILL_INPUT* if an argument had an illegal value (e.g. a negative tolerance). .. deprecated:: 6.1.0 @@ -158,7 +158,7 @@ MRIStep tolerance specification functions * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` * *ARK_NO_MALLOC* if the MRIStep memory was not allocated by the time-stepping module - * *ARK_ILL_INPUT* if an argument has an illegal value (e.g. a negative tolerance). + * *ARK_ILL_INPUT* if an argument had an illegal value (e.g. a negative tolerance). .. deprecated:: 6.1.0 @@ -361,7 +361,7 @@ MRIStep solver function internal time-stepping. (b) The linear solver initialization function (called by the - user after calling :c:func:`ARKStepCreate`) failed to set + user after calling :c:func:`MRIStepCreate`) failed to set the linear solver-specific *lsolve* field in *arkode_mem*. @@ -447,7 +447,7 @@ Optional inputs for MRIStep * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** This function does not change problem-defining function pointers *fs* and *ff* or the *user_data* pointer. It also does not affect any data @@ -489,7 +489,7 @@ Optional inputs for MRIStep * *ARK_INTERP_FAIL* if this is called after :c:func:`MRIStepEvolve()` - * *ARK_ILL_INPUT* if an argument has an illegal value or the + * *ARK_ILL_INPUT* if an argument had an illegal value or the interpolation module has already been initialized **Notes:** Allowed values are between 0 and 5. @@ -544,7 +544,7 @@ Optional inputs for MRIStep * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** This parameter can be ``stdout`` or ``stderr``, although the suggested approach is to specify a pointer to a unique file opened @@ -577,7 +577,7 @@ Optional inputs for MRIStep * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** @@ -608,7 +608,7 @@ Optional inputs for MRIStep * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** The default value is 10; set *mxhnil* to zero to specify this default. @@ -639,7 +639,7 @@ Optional inputs for MRIStep * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Passing *mxsteps* = 0 results in MRIStep using the default value (500). @@ -669,7 +669,7 @@ Optional inputs for MRIStep * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** @@ -701,7 +701,7 @@ Optional inputs for MRIStep **Return value:** * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the ARKStep memory is ``NULL`` + * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` .. versionadded:: 5.6.0 @@ -751,17 +751,16 @@ Optional inputs for MRIStep * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** If specified, the pointer to *user_data* is passed to all user-supplied functions called by the outer integrator for which it is an argument; otherwise ``NULL`` is passed. - To attach a user data block to the inner integrator call the appropriate - *SetUserData* function for the inner integrator memory structure (e.g., - :c:func:`ARKStepSetUserData()` if the inner stepper is ARKStep). This pointer - may be the same as or different from the pointer attached to the outer - integrator depending on what is required by the user code. + To attach a user data block to the inner integrator call :c:func:`ARKodeSetUserData` + for the inner integrator memory structure. This pointer may be the same as or + different from the pointer attached to the outer integrator depending on what is + required by the user code. .. deprecated:: 6.1.0 @@ -867,7 +866,7 @@ Optional inputs for IVP method selection * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** @@ -900,7 +899,7 @@ Optional inputs for implicit stage solves **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Tightens the linear solver tolerances and takes only a single Newton iteration. Calls :c:func:`MRIStepSetDeltaGammaMax()` @@ -930,7 +929,7 @@ Optional inputs for implicit stage solves **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** This is the default behavior of MRIStep, so the function is primarily useful to undo a previous call to @@ -970,7 +969,7 @@ Optional inputs for implicit stage solves **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** The default value is 0. If *method* is set to an undefined value, this default predictor will be used. @@ -996,7 +995,7 @@ Optional inputs for implicit stage solves **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value or if the SUNNONLINSOL module is ``NULL`` + * *ARK_ILL_INPUT* if an argument had an illegal value or if the SUNNONLINSOL module is ``NULL`` * *ARK_NLS_OP_ERR* if the SUNNONLINSOL object returned a failure flag **Notes:** The default value is 3; set *maxcor* :math:`\le 0` @@ -1019,7 +1018,7 @@ Optional inputs for implicit stage solves **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** The default value is 0.1; set *nlscoef* :math:`\le 0` to specify this default. @@ -1041,7 +1040,7 @@ Optional inputs for implicit stage solves **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any non-positive parameter will imply a reset to the default value. @@ -1064,7 +1063,7 @@ Optional inputs for implicit stage solves **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any non-positive parameter will imply a reset to the default value. @@ -1173,7 +1172,7 @@ Optional inputs for the ARKLS linear solver interface **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** Any non-positive parameter will imply a reset to the default value. @@ -1534,7 +1533,7 @@ Rootfinding optional input functions **Return value:** * *ARK_SUCCESS* if successful * *ARK_MEM_NULL* if the MRIStep memory is ``NULL`` - * *ARK_ILL_INPUT* if an argument has an illegal value + * *ARK_ILL_INPUT* if an argument had an illegal value **Notes:** The default behavior is to monitor for both zero-crossing directions. @@ -1990,7 +1989,7 @@ Main solver optional output functions * *ARK_SUCCESS* if successful - * *ARK_MEM_NULL* if the ARKStep memory was ``NULL`` + * *ARK_MEM_NULL* if the MRIStep memory was ``NULL`` .. versionadded:: 5.3.0 @@ -2645,7 +2644,7 @@ To reinitialize the MRIStep module for the solution of a new problem, where a prior call to :c:func:`MRIStepCreate()` has been made, the user must call the function :c:func:`MRIStepReInit()`. The new problem must have the same size as the previous one. This routine -retains the current settings for all ARKstep module options and +retains the current settings for all MRIStep module options and performs the same input checking and initializations that are done in :c:func:`MRIStepCreate()`, but it performs no memory allocation as is assumes that the existing internal memory is sufficient for the new @@ -2708,7 +2707,7 @@ vector. * *ARK_MEM_FAIL* if a memory allocation failed - * *ARK_ILL_INPUT* if an argument has an illegal value. + * *ARK_ILL_INPUT* if an argument had an illegal value. **Notes:** If the inner (fast) stepper also needs to be reinitialized, its @@ -2749,7 +2748,7 @@ MRIStep reset function * *ARK_MEM_FAIL* if a memory allocation failed - * *ARK_ILL_INPUT* if an argument has an illegal value. + * *ARK_ILL_INPUT* if an argument had an illegal value. **Notes:** If the inner (fast) stepper also needs to be reset, its reset function should @@ -2806,7 +2805,7 @@ MRIStep system resize function * *ARK_NO_MALLOC* if *arkode_mem* was not allocated. - * *ARK_ILL_INPUT* if an argument has an illegal value. + * *ARK_ILL_INPUT* if an argument had an illegal value. **Notes:** If an error occurred, :c:func:`MRIStepResize()` also sends an error message to the error handler function. diff --git a/doc/arkode/guide/source/Usage/SPRKStep/User_callable.rst b/doc/arkode/guide/source/Usage/SPRKStep/User_callable.rst index 73bde21f90..e4a88b1d18 100644 --- a/doc/arkode/guide/source/Usage/SPRKStep/User_callable.rst +++ b/doc/arkode/guide/source/Usage/SPRKStep/User_callable.rst @@ -227,7 +227,7 @@ Optional inputs for SPRKStep :retval ARK_SUCCESS: if successful :retval ARK_MEM_NULL: if the SPRKStep memory is ``NULL`` - :retval ARK_ILL_INPUT: if an argument has an illegal value + :retval ARK_ILL_INPUT: if an argument had an illegal value .. note:: @@ -262,7 +262,7 @@ Optional inputs for SPRKStep :retval ARK_SUCCESS: if successful :retval ARK_MEM_NULL: if the SPRKStep memory or interpolation module are ``NULL`` :retval ARK_INTERP_FAIL: if this is called after :c:func:`SPRKStepEvolve()` - :retval ARK_ILL_INPUT: if an argument has an illegal value or the + :retval ARK_ILL_INPUT: if an argument had an illegal value or the interpolation module has already been initialized .. note:: @@ -298,7 +298,7 @@ Optional inputs for SPRKStep :retval ARK_SUCCESS: if successful :retval ARK_MEM_NULL: if the SPRKStep memory is ``NULL`` - :retval ARK_ILL_INPUT: if an argument has an illegal value + :retval ARK_ILL_INPUT: if an argument had an illegal value .. deprecated:: 6.1.0 @@ -321,7 +321,7 @@ Optional inputs for SPRKStep :retval ARK_SUCCESS: if successful :retval ARK_MEM_NULL: if the SPRKStep memory is ``NULL`` - :retval ARK_ILL_INPUT: if an argument has an illegal value + :retval ARK_ILL_INPUT: if an argument had an illegal value .. deprecated:: 6.1.0 @@ -348,7 +348,7 @@ Optional inputs for SPRKStep :retval ARK_SUCCESS: if successful :retval ARK_MEM_NULL: if the SPRKStep memory is ``NULL`` - :retval ARK_ILL_INPUT: if an argument has an illegal value + :retval ARK_ILL_INPUT: if an argument had an illegal value .. deprecated:: 6.1.0 @@ -386,7 +386,7 @@ Optional inputs for SPRKStep :retval ARK_SUCCESS: if successful :retval ARK_MEM_NULL: if the SPRKStep memory is ``NULL`` - :retval ARK_ILL_INPUT: if an argument has an illegal value + :retval ARK_ILL_INPUT: if an argument had an illegal value .. deprecated:: 6.1.0 @@ -430,7 +430,7 @@ Optional inputs for IVP method selection :retval ARK_SUCCESS: if successful :retval ARK_MEM_NULL: if the SPRKStep memory is ``NULL`` - :retval ARK_ILL_INPUT: if an argument has an illegal value + :retval ARK_ILL_INPUT: if an argument had an illegal value .. warning:: @@ -451,7 +451,7 @@ Optional inputs for IVP method selection :retval ARK_SUCCESS: if successful :retval ARK_MEM_NULL: if the SPRKStep memory is ``NULL`` - :retval ARK_ILL_INPUT: if an argument has an illegal value + :retval ARK_ILL_INPUT: if an argument had an illegal value .. note:: @@ -472,7 +472,7 @@ Optional inputs for IVP method selection :retval ARK_SUCCESS: if successful :retval ARK_MEM_NULL: if the SPRKStep memory is ``NULL`` - :retval ARK_ILL_INPUT: if an argument has an illegal value + :retval ARK_ILL_INPUT: if an argument had an illegal value .. warning:: @@ -494,7 +494,7 @@ Optional inputs for IVP method selection :retval ARK_SUCCESS: if successful :retval ARK_MEM_NULL: if the SPRKStep memory is ``NULL`` - :retval ARK_ILL_INPUT: if an argument has an illegal value + :retval ARK_ILL_INPUT: if an argument had an illegal value @@ -522,7 +522,7 @@ Rootfinding optional input functions :retval ARK_SUCCESS: if successful :retval ARK_MEM_NULL: if the SPRKStep memory is ``NULL`` - :retval ARK_ILL_INPUT: if an argument has an illegal value + :retval ARK_ILL_INPUT: if an argument had an illegal value .. deprecated:: 6.1.0 @@ -809,7 +809,7 @@ Main solver optional output functions :param user_data: memory reference to a user data pointer :retval ARK_SUCCESS: if successful - :retval ARK_MEM_NULL: if the ARKStep memory was ``NULL`` + :retval ARK_MEM_NULL: if the SPRKStep memory was ``NULL`` .. deprecated:: 6.1.0 @@ -945,7 +945,7 @@ the RHS function should not incorporate the discontinuity. :retval ARK_SUCCESS: if successful :retval ARK_MEM_NULL: if the SPRKStep memory was ``NULL`` :retval ARK_MEM_FAIL: if a memory allocation failed - :retval ARK_ILL_INPUT: if an argument has an illegal value. + :retval ARK_ILL_INPUT: if an argument had an illegal value. .. _ARKODE.Usage.SPRKStep.Reset: @@ -971,7 +971,7 @@ SPRKStep reset function :retval ARK_SUCCESS: if successful :retval ARK_MEM_NULL: if the SPRKStep memory was ``NULL`` :retval ARK_MEM_FAIL: if a memory allocation failed - :retval ARK_ILL_INPUTL: if an argument has an illegal value. + :retval ARK_ILL_INPUTL: if an argument had an illegal value. .. note:: diff --git a/doc/arkode/guide/source/Usage/User_callable.rst b/doc/arkode/guide/source/Usage/User_callable.rst index 98de3a33b6..8737483ddd 100644 --- a/doc/arkode/guide/source/Usage/User_callable.rst +++ b/doc/arkode/guide/source/Usage/User_callable.rst @@ -790,6 +790,10 @@ the user has set a stop time (with a call to the optional input function :retval ARK_MASSSETUP_FAIL: the mass matrix solver's setup routine failed. :retval ARK_MASSSOLVE_FAIL: the mass matrix solver's solve routine failed. :retval ARK_VECTOROP_ERR: a vector operation error occurred. + :retval ARK_DOMEIG_FAIL: the dominant eigenvalue function failed. It is either + not provided or returns an illegal value. + :retval ARK_MAX_STAGE_LIMIT_FAIL: stepper failed to achieve stable results. Either + reduce the step size or increase the stage_max_limit .. note:: @@ -3421,7 +3425,9 @@ Retrieve a pointer for user data :c:func:`ARKodeGetUserDat .. c:function:: int ARKodeGetNumExpSteps(void* arkode_mem, long int* expsteps) Returns the cumulative number of stability-limited steps - taken by the solver (so far). + taken by the solver (so far). If the combination of the maximum number of stages + and the current time step size in the LSRKStep module will not allow for a stable + step, the counter also accounts for such returns. :param arkode_mem: pointer to the ARKODE memory block. :param expsteps: number of stability-limited steps taken in the solver. diff --git a/doc/arkode/guide/source/Usage/index.rst b/doc/arkode/guide/source/Usage/index.rst index 93b63d84b8..88cbfa7d3d 100644 --- a/doc/arkode/guide/source/Usage/index.rst +++ b/doc/arkode/guide/source/Usage/index.rst @@ -37,8 +37,8 @@ ARKODE's time stepping modules, including "relaxation" methods and preconitioners. Following our discussion of these commonalities, we separately discuss the usage details that that are specific to each of ARKODE's time stepping modules: :ref:`ARKStep `, -:ref:`ERKStep `, :ref:`SPRKStep ` -and :ref:`MRIStep `. +:ref:`ERKStep `, :ref:`SPRKStep `, +:ref:`MRIStep `, and :ref:`LSRKStep `. ARKODE also uses various input and output constants; these are defined as needed throughout this chapter, but for convenience the full list is provided @@ -77,5 +77,6 @@ ARKBBDPRE can only be used with NVECTOR_PARALLEL. Preconditioners ARKStep/index.rst ERKStep/index.rst + LSRKStep/index.rst SPRKStep/index.rst MRIStep/index.rst diff --git a/doc/shared/RecentChanges.rst b/doc/shared/RecentChanges.rst index 2be479f59c..d487a4a8d0 100644 --- a/doc/shared/RecentChanges.rst +++ b/doc/shared/RecentChanges.rst @@ -22,6 +22,12 @@ only valid for Volta GPUs while the automatically selected value will vary across compilers and compiler versions. As such, users are encouraged to override this value with the architecture for their system. +Added a time-stepping module to ARKODE for low storage Runge--Kutta methods, +:ref:`LSRKStep `. This currently supports five explicit low-storage +methods: the second-order Runge--Kutta--Chebyshev and Runge--Kutta--Legendre methods, +and the second- through fourth-order optimal strong stability preserving Runge--Kutta methods. +All methods include embeddings for temporal adaptivity. + The Trilinos Tpetra NVector interface has been updated to utilize CMake imported targets added in Trilinos 14 to improve support for different Kokkos backends with Trilinos. As such, Trilinos 14 or newer is required and the diff --git a/doc/shared/sundials.bib b/doc/shared/sundials.bib index b000f2c3dc..8d3ccec6e6 100644 --- a/doc/shared/sundials.bib +++ b/doc/shared/sundials.bib @@ -713,7 +713,7 @@ @article{ginkgo-toms-2022 copyright = {All rights reserved}, issn = {0098-3500}, shorttitle = {Ginkgo}, -url = {https://doi.org/10.1145/3480935}, +url = {10.1145/3480935}, doi = {10.1145/3480935}, number = {1}, urldate = {2022-02-17}, @@ -2114,7 +2114,7 @@ @article{Sof:03 year = {2003}, note = {Special Issue on Geometric Numerical Algorithms}, issn = {0167-739X}, - doi = {https://doi.org/10.1016/S0167-739X(02)00164-4}, + doi = {10.1016/S0167-739X(02)00164-4}, url = {https://www.sciencedirect.com/science/article/pii/S0167739X02001644}, author = {Mark Sofroniou and Giulia Spaletta} } @@ -2199,7 +2199,7 @@ @article{Tao:22 pages = {110846}, year = {2022}, issn = {0021-9991}, - doi = {https://doi.org/10.1016/j.jcp.2021.110846}, + doi = {10.1016/j.jcp.2021.110846}, url = {https://www.sciencedirect.com/science/article/pii/S0021999121007415}, author = {Molei Tao and Shi Jin}, keywords = {Symplectic integrator, Time-reversible / symmetric integrator, Hamiltonian with discontinuous potential, Contact and impact at interface, Reflection and refraction, Sauteed mushroom} @@ -2369,3 +2369,66 @@ @article{edwards2014kokkos issn = {0743-7315}, doi = {10.1016/j.jpdc.2014.07.003} } + +@article{VSH:04, +title = {{RKC} time-stepping for advection–diffusion–reaction problems}, +journal = {Journal of Computational Physics}, +volume = {201}, +number = {1}, +pages = {61-79}, +year = {2004}, +issn = {0021-9991}, +doi = {10.1016/j.jcp.2004.05.002}, +author = {J.G. Verwer and B.P. Sommeijer and W. Hundsdorfer}} + +@article{MBA:14, +title = {A stabilized {Runge--Kutta--Legendre} method for explicit super-time-stepping of parabolic and mixed equations}, +journal = {Journal of Computational Physics}, +volume = {257}, +pages = {594-626}, +year = {2014}, +issn = {0021-9991}, +doi = {10.1016/j.jcp.2013.08.021}, +author = {Chad D. Meyer and Dinshaw S. Balsara and Tariq D. Aslam}} + +@article{K:08, +title = {Highly Efficient Strong Stability-Preserving {Runge--Kutta} Methods with Low-Storage Implementations}, +journal = {SIAM Journal on Scientific Computing}, +volume = {30}, +number = {4}, +pages = {2113-2136}, +year = {2008}, +doi = {10.1137/07070485X}, +author = {Ketcheson, David I.}} + +@article{FCS:22, +title = {Embedded pairs for optimal explicit strong stability preserving {Runge--Kutta} methods}, +journal = {Journal of Computational and Applied Mathematics}, +volume = {412}, +pages = {114325}, +year = {2022}, +issn = {0377-0427}, +doi = {10.1016/j.cam.2022.114325}, +author = {Imre Fekete and Sidafa Conde and John N. Shadid}} + +@article{SO:88, +title={Efficient implementation of essentially non-oscillatory shock-capturing schemes}, +journal={Journal of computational physics}, +volume={77}, +number={2}, +pages={439--471}, +year={1988}, +publisher={Elsevier}, +doi={10.1016/0021-9991(88)90177-5}, +author={Shu, Chi-Wang and Osher, Stanley}} + +@article{SR:02, +title={A new class of optimal high-order strong-stability-preserving time discretization methods}, +journal={SIAM Journal on Numerical Analysis}, +volume={40}, +number={2}, +pages={469--491}, +year={2002}, +publisher={SIAM}, +doi={10.1137/S0036142901389025}, +author={Spiteri, Raymond J and Ruuth, Steven J}} \ No newline at end of file diff --git a/examples/arkode/CMakeLists.txt b/examples/arkode/CMakeLists.txt index bfcbe267fd..611ac56cd8 100644 --- a/examples/arkode/CMakeLists.txt +++ b/examples/arkode/CMakeLists.txt @@ -42,6 +42,9 @@ endif() # C++ examples if(EXAMPLES_ENABLE_CXX) add_subdirectory(CXX_serial) + if(BUILD_NVECTOR_MANYVECTOR) + add_subdirectory(CXX_manyvector) + endif() if(ENABLE_MPI AND MPI_CXX_FOUND) add_subdirectory(CXX_parallel) endif() diff --git a/examples/arkode/CXX_manyvector/CMakeLists.txt b/examples/arkode/CXX_manyvector/CMakeLists.txt new file mode 100644 index 0000000000..037f1fd83b --- /dev/null +++ b/examples/arkode/CXX_manyvector/CMakeLists.txt @@ -0,0 +1,84 @@ +# --------------------------------------------------------------- +# Programmer(s): Daniel R. Reynolds @ SMU +# --------------------------------------------------------------- +# SUNDIALS Copyright Start +# Copyright (c) 2002-2024, Lawrence Livermore National Security +# and Southern Methodist University. +# All rights reserved. +# +# See the top-level LICENSE and NOTICE files for details. +# +# SPDX-License-Identifier: BSD-3-Clause +# SUNDIALS Copyright End +# --------------------------------------------------------------- +# CMakeLists.txt file for ARKODE C++ manyvector examples +# --------------------------------------------------------------- + +# Example lists are tuples "name\;args\;type" where the type is 'develop' for +# examples excluded from 'make test' in releases + +# Examples using SUNDIALS linear solvers +set(ARKODE_examples "ark_sod_lsrk.cpp\;\;exclude-single") + +# Header files to install +set(ARKODE_headers) + +# Auxiliary files to install +set(ARKODE_extras plot_sod.py) + +# Add the build and install targets for each example +foreach(example_tuple ${ARKODE_examples}) + + # parse the example tuple + list(GET example_tuple 0 example) + list(GET example_tuple 1 example_args) + list(GET example_tuple 2 example_type) + + # extract the file name without extension + get_filename_component(example_target ${example} NAME_WE) + + # add example executable + if(NOT TARGET ${example_target}) + add_executable(${example_target} ${example}) + + set_target_properties(${example_target} PROPERTIES FOLDER "Examples") + + # directories to include + target_include_directories(${example_target} + PRIVATE ${PROJECT_SOURCE_DIR}/examples/utilities) + + # libraries to link against + target_link_libraries(${example_target} sundials_arkode sundials_nvecserial + sundials_nvecmanyvector ${EXE_EXTRA_LINK_LIBS}) + + endif() + + # check if example args are provided and set the test name + if("${example_args}" STREQUAL "") + set(test_name ${example_target}) + else() + string(REGEX REPLACE " " "_" test_name ${example_target}_${example_args}) + endif() + + # add example to regression tests + sundials_add_test( + ${test_name} ${example_target} + TEST_ARGS ${example_args} + ANSWER_DIR ${CMAKE_CURRENT_SOURCE_DIR} + ANSWER_FILE ${test_name}.out + EXAMPLE_TYPE ${example_type}) + +endforeach(example_tuple ${ARKODE_examples}) + +if(EXAMPLES_INSTALL) + + sundials_install_examples( + arkode ARKODE_examples + CMAKE_TEMPLATE cmakelists_CXX_ex.in + MAKE_TEMPLATE makefile_serial_CXX_ex.in + SUNDIALS_TARGETS nvecserial nvecmanyvector arkode + DESTINATION arkode/CXX_manyvector + EXTRA_FILES ${ARKODE_extras} ${ARKODE_headers} + TEST_INSTALL CXX_manyvector) + +endif() diff --git a/examples/arkode/CXX_manyvector/ark_sod_lsrk.cpp b/examples/arkode/CXX_manyvector/ark_sod_lsrk.cpp new file mode 100644 index 0000000000..2813b150bf --- /dev/null +++ b/examples/arkode/CXX_manyvector/ark_sod_lsrk.cpp @@ -0,0 +1,580 @@ +/* ----------------------------------------------------------------------------- + * Programmer(s): Daniel R. Reynolds @ SMU + * ----------------------------------------------------------------------------- + * SUNDIALS Copyright Start + * Copyright (c) 2002-2024, Lawrence Livermore National Security + * and Southern Methodist University. + * All rights reserved. + * + * See the top-level LICENSE and NOTICE files for details. + * + * SPDX-License-Identifier: BSD-3-Clause + * SUNDIALS Copyright End + * ----------------------------------------------------------------------------- + * This example performs a standard 1D sod shock tube (see section 5.2 of J.A. + * Greenough and W.J. Rider, "A quantitative comparison of numerical methods for + * the compressible Euler equations: fifth-order WENO and piecewise-linear + * Godunov," J. Comput. Phys., 196:259-281, 2004) + * [rho, vx, p] = { [1, 0, 1] if x < 0.5 + * { [0.125, 0, 0.1] if x > 0.5 + * + * The code solves the 1D compressible Euler equations in conserved variables, + * over the domain (t,x) in [0, 0.2] x [0, 1]. + * + * Since the Sod shock tube is specified in terms of primitive variables, we + * convert between primitive and conserved variables for the initial conditions + * and accuracy results. + * + * This problem should be run with homogeneous Neumann boundary conditions. + * + * The system is advanced in time using one of the strong-stability-preserving + * Runge--Kutta methods from LSRKStep, based on the --integrator METHOD input + * value. The following options are available: + * + * SSPRK(s,2) -- specified via METHOD = ARKODE_LSRK_SSP_S_2. The number of + * stages to use defaults to 10. + * + * SSPRK(s,3) -- specified via METHOD = ARKODE_LSRK_SSP_S_3. The number of + * stages to use defaults to 9. + * + * SSPRK(10,4) -- specified via METHOD = ARKODE_LSRK_SSP_10_4. + * + * Both the SSPRK(s,2) and SSPRK(s,3) methods allow specification of a + * non-default number of stages. This may be specified using the --stages S + * input value, where S is an integer. Note: SSPRK(s,2) requires S at least + * 2, and SSPRK(s,3) requires S be a perfect square, with S at least 4. + * + * Alternately, if METHOD corresponds with a valid ARKODE_ERKTableID then + * the system will be advanced using that method in ERKStep. + * + * Several additional command line options are available to change the + * and integrator settings. Use the flag --help for more information. + * ---------------------------------------------------------------------------*/ + +#include "ark_sod_lsrk.hpp" +using namespace std; + +int main(int argc, char* argv[]) +{ + // SUNDIALS context object for this simulation + sundials::Context ctx; + + // ----------------- + // Setup the problem + // ----------------- + + EulerData udata; + ARKODEParameters uopts; + + vector args(argv + 1, argv + argc); + + int flag = ReadInputs(args, udata, uopts, ctx); + if (check_flag(flag, "ReadInputs")) { return 1; } + if (flag > 0) { return 0; } + + flag = PrintSetup(udata, uopts); + if (check_flag(flag, "PrintSetup")) { return 1; } + + // Create state vector and set initial condition + N_Vector vecs[NSPECIES]; + for (int i = 0; i < NSPECIES; i++) + { + vecs[i] = N_VNew_Serial((sunindextype)udata.nx, ctx); // rho (density) + if (check_ptr(vecs[i], "N_VNew_Serial")) { return 1; } + } + N_Vector y = N_VNew_ManyVector(NSPECIES, vecs, ctx); + if (check_ptr(y, "N_VNew_ManyVector")) { return 1; } + + flag = SetIC(y, udata); + if (check_flag(flag, "SetIC")) { return 1; } + + // -------------------- + // Setup the integrator + // -------------------- + void* arkode_mem = nullptr; + + // Determine type (LSRKStep vs ERKStep) + bool lsrk = false; + if (uopts.integrator == "ARKODE_LSRK_SSP_S_2") { lsrk = true; } + if (uopts.integrator == "ARKODE_LSRK_SSP_S_3") { lsrk = true; } + if (uopts.integrator == "ARKODE_LSRK_SSP_10_4") { lsrk = true; } + + if (lsrk) // Setup LSRKStep + { + // ARKODE memory structure + arkode_mem = LSRKStepCreateSSP(frhs, udata.t0, y, ctx); + if (check_ptr(arkode_mem, "LSRKStepCreateSSP")) { return 1; } + + // Select SSPRK method type + flag = LSRKStepSetSSPMethodByName(arkode_mem, uopts.integrator.c_str()); + if (check_flag(flag, "LSRKStepSetSSPMethodByName")) { return 1; } + + // Select number of SSPRK stages + if (uopts.stages > 0) + { + flag = LSRKStepSetSSPStageNum(arkode_mem, uopts.stages); + if (check_flag(flag, "LSRKStepSetSSPStageNum")) { return 1; } + } + } + else + { // Setup ERKStep + + // ARKODE memory structure + arkode_mem = ERKStepCreate(frhs, udata.t0, y, ctx); + if (check_ptr(arkode_mem, "ERKStepCreate")) { return 1; } + + // Select ERK method + flag = ERKStepSetTableName(arkode_mem, uopts.integrator.c_str()); + if (check_flag(flag, "ERKStepSetTableName")) { return 1; } + } + + // Shared setup + + // Specify tolerances + flag = ARKodeSStolerances(arkode_mem, uopts.rtol, uopts.atol); + if (check_flag(flag, "ARKodeSStolerances")) { return 1; } + + // Attach user data + flag = ARKodeSetUserData(arkode_mem, &udata); + if (check_flag(flag, "ARKodeSetUserData")) { return 1; } + + // Set fixed step size or adaptivity method + if (uopts.fixed_h > ZERO) + { + flag = ARKodeSetFixedStep(arkode_mem, uopts.fixed_h); + if (check_flag(flag, "ARKodeSetFixedStep")) { return 1; } + } + + // Set max steps between outputs + flag = ARKodeSetMaxNumSteps(arkode_mem, uopts.maxsteps); + if (check_flag(flag, "ARKodeSetMaxNumSteps")) { return 1; } + + // Set stopping time + flag = ARKodeSetStopTime(arkode_mem, udata.tf); + if (check_flag(flag, "ARKodeSetStopTime")) { return 1; } + + // ---------------------- + // Evolve problem in time + // ---------------------- + + // Initial time, time between outputs, output time + sunrealtype t = ZERO; + sunrealtype dTout = udata.tf / uopts.nout; + sunrealtype tout = dTout; + + // initial output + flag = OpenOutput(udata, uopts); + if (check_flag(flag, "OpenOutput")) { return 1; } + + flag = WriteOutput(t, y, udata, uopts); + if (check_flag(flag, "WriteOutput")) { return 1; } + + // Loop over output times + for (int iout = 0; iout < uopts.nout; iout++) + { + // Evolve + if (uopts.output == 3) + { + // Stop at output time (do not interpolate output) + flag = ARKodeSetStopTime(arkode_mem, tout); + if (check_flag(flag, "ARKodeSetStopTime")) { return 1; } + } + + // Advance in time + flag = ARKodeEvolve(arkode_mem, tout, y, &t, ARK_NORMAL); + if (check_flag(flag, "ARKodeEvolve")) { break; } + + // Output solution + flag = WriteOutput(t, y, udata, uopts); + if (check_flag(flag, "WriteOutput")) { return 1; } + + // Update output time + tout += dTout; + tout = (tout > udata.tf) ? udata.tf : tout; + } + + // Close output + flag = CloseOutput(uopts); + if (check_flag(flag, "CloseOutput")) { return 1; } + + // ------------ + // Output stats + // ------------ + + if (uopts.output) + { + cout << "Final integrator statistics:" << endl; + flag = ARKodePrintAllStats(arkode_mem, stdout, SUN_OUTPUTFORMAT_TABLE); + } + + // -------- + // Clean up + // -------- + + ARKodeFree(&arkode_mem); + for (int i = 0; i < NSPECIES; i++) { N_VDestroy(vecs[i]); } + N_VDestroy(y); + + return 0; +} + +// ----------------------------------------------------------------------------- +// Functions called by the integrator +// ----------------------------------------------------------------------------- + +// ODE RHS function +int frhs(sunrealtype t, N_Vector y, N_Vector f, void* user_data) +{ + // Access problem data + EulerData* udata = (EulerData*)user_data; + + // initialize output to zeros + N_VConst(ZERO, f); + + // Access data arrays + sunrealtype* rho = N_VGetSubvectorArrayPointer_ManyVector(y, 0); + if (check_ptr(rho, "N_VGetSubvectorArrayPointer_ManyVector")) { return -1; } + sunrealtype* mx = N_VGetSubvectorArrayPointer_ManyVector(y, 1); + if (check_ptr(mx, "N_VGetSubvectorArrayPointer_ManyVector")) { return -1; } + sunrealtype* my = N_VGetSubvectorArrayPointer_ManyVector(y, 2); + if (check_ptr(my, "N_VGetSubvectorArrayPointer_ManyVector")) { return -1; } + sunrealtype* mz = N_VGetSubvectorArrayPointer_ManyVector(y, 3); + if (check_ptr(mz, "N_VGetSubvectorArrayPointer_ManyVector")) { return -1; } + sunrealtype* et = N_VGetSubvectorArrayPointer_ManyVector(y, 4); + if (check_ptr(et, "N_VGetSubvectorArrayPointer_ManyVector")) { return -1; } + + sunrealtype* rhodot = N_VGetSubvectorArrayPointer_ManyVector(f, 0); + if (check_ptr(rhodot, "N_VGetSubvectorArrayPointer_ManyVector")) + { + return -1; + } + sunrealtype* mxdot = N_VGetSubvectorArrayPointer_ManyVector(f, 1); + if (check_ptr(mxdot, "N_VGetSubvectorArrayPointer_ManyVector")) { return -1; } + sunrealtype* mydot = N_VGetSubvectorArrayPointer_ManyVector(f, 2); + if (check_ptr(mydot, "N_VGetSubvectorArrayPointer_ManyVector")) { return -1; } + sunrealtype* mzdot = N_VGetSubvectorArrayPointer_ManyVector(f, 3); + if (check_ptr(mzdot, "N_VGetSubvectorArrayPointer_ManyVector")) { return -1; } + sunrealtype* etdot = N_VGetSubvectorArrayPointer_ManyVector(f, 4); + if (check_ptr(etdot, "N_VGetSubvectorArrayPointer_ManyVector")) { return -1; } + + // Set shortcut variables + const long int nx = udata->nx; + const sunrealtype dx = udata->dx; + sunrealtype* flux = udata->flux; + + // compute face-centered fluxes over domain interior: pack 1D x-directional array + // of variable shortcuts, and compute flux at lower x-directional face + for (long int i = 3; i < nx - 2; i++) + { + udata->pack1D(rho, mx, my, mz, et, i); + face_flux(udata->w1d, &(flux[i * NSPECIES]), *udata); + } + + // compute face-centered fluxes at left boundary + for (long int i = 0; i < 3; i++) + { + udata->pack1D_bdry(rho, mx, my, mz, et, i); + face_flux(udata->w1d, &(flux[i * NSPECIES]), *udata); + } + + // compute face-centered fluxes at right boundary + for (long int i = nx - 2; i <= nx; i++) + { + udata->pack1D_bdry(rho, mx, my, mz, et, i); + face_flux(udata->w1d, &(flux[i * NSPECIES]), *udata); + } + + // iterate over subdomain, updating RHS + for (long int i = 0; i < nx; i++) + { + rhodot[i] -= (flux[(i + 1) * NSPECIES + 0] - flux[i * NSPECIES + 0]) / dx; + mxdot[i] -= (flux[(i + 1) * NSPECIES + 1] - flux[i * NSPECIES + 1]) / dx; + mydot[i] -= (flux[(i + 1) * NSPECIES + 2] - flux[i * NSPECIES + 2]) / dx; + mzdot[i] -= (flux[(i + 1) * NSPECIES + 3] - flux[i * NSPECIES + 3]) / dx; + etdot[i] -= (flux[(i + 1) * NSPECIES + 4] - flux[i * NSPECIES + 4]) / dx; + } + + return 0; +} + +// given a 6-point stencil of solution values, +// w(x_{j-3}) w(x_{j-2}) w(x_{j-1}), w(x_j), w(x_{j+1}), w(x_{j+2}), +// compute the face-centered flux (flux) at the center of the stencil, x_{j-1/2}. +// +// This precisely follows the recipe laid out in: +// Chi-Wang Shu (2003) "High-order Finite Difference and Finite Volume WENO +// Schemes and Discontinuous Galerkin Methods for CFD," International Journal of +// Computational Fluid Dynamics, 17:2, 107-118, DOI: 10.1080/1061856031000104851 +// with the only change that since this is 1D, we manually set the y- and +// z-velocities, v and w, to zero. +void face_flux(sunrealtype (&w1d)[STSIZE][NSPECIES], sunrealtype* f_face, + const EulerData& udata) +{ + // local data + int i, j; + sunrealtype rhosqrL, rhosqrR, rhosqrbar, u, v, w, H, qsq, csnd, cinv, gamm, + alpha, beta1, beta2, beta3, w1, w2, w3, f1, f2, f3; + sunrealtype RV[5][5], LV[5][5], p[STSIZE], flux[STSIZE][NSPECIES], + fproj[5][NSPECIES], fs[5][NSPECIES], ff[NSPECIES]; + const sunrealtype bc = + SUN_RCONST(1.083333333333333333333333333333333333333); // 13/12 + const sunrealtype epsilon = SUN_RCONST(1.0e-6); + + // compute pressures over stencil + for (i = 0; i < STSIZE; i++) + { + p[i] = udata.eos(w1d[i][0], w1d[i][1], w1d[i][2], w1d[i][3], w1d[i][4]); + } + + // compute Roe-average state at face: + // wbar = [sqrt(rho), sqrt(rho)*vx, sqrt(rho)*vy, sqrt(rho)*vz, (e+p)/sqrt(rho)] + // [sqrt(rho), mx/sqrt(rho), my/sqrt(rho), mz/sqrt(rho), (e+p)/sqrt(rho)] + // u = wbar_2 / wbar_1 + // v = wbar_3 / wbar_1 + // w = wbar_4 / wbar_1 + // H = wbar_5 / wbar_1 + rhosqrL = sqrt(w1d[2][0]); + rhosqrR = sqrt(w1d[3][0]); + rhosqrbar = HALF * (rhosqrL + rhosqrR); + u = HALF * (w1d[2][1] / rhosqrL + w1d[3][1] / rhosqrR) / rhosqrbar; + v = HALF * (w1d[2][2] / rhosqrL + w1d[3][2] / rhosqrR) / rhosqrbar; + w = HALF * (w1d[2][3] / rhosqrL + w1d[3][3] / rhosqrR) / rhosqrbar; + H = HALF * ((p[2] + w1d[2][4]) / rhosqrL + (p[3] + w1d[3][4]) / rhosqrR) / + rhosqrbar; + + // compute eigenvectors at face (note: eigenvectors for tracers are just identity) + qsq = u * u + v * v + w * w; + gamm = udata.gamma - ONE; + csnd = gamm * (H - HALF * qsq); + cinv = ONE / csnd; + for (i = 0; i < 5; i++) + { + for (j = 0; j < 5; j++) + { + RV[i][j] = ZERO; + LV[i][j] = ZERO; + } + } + + RV[0][0] = ONE; + RV[0][3] = ONE; + RV[0][4] = ONE; + + RV[1][0] = u - csnd; + RV[1][3] = u; + RV[1][4] = u + csnd; + + RV[2][0] = v; + RV[2][1] = ONE; + RV[2][3] = v; + RV[2][4] = v; + + RV[3][0] = w; + RV[3][2] = ONE; + RV[3][3] = w; + RV[3][4] = w; + + RV[4][0] = H - u * csnd; + RV[4][1] = v; + RV[4][2] = w; + RV[4][3] = HALF * qsq; + RV[4][4] = H + u * csnd; + + LV[0][0] = HALF * cinv * (u + HALF * gamm * qsq); + LV[0][1] = -HALF * cinv * (gamm * u + ONE); + LV[0][2] = -HALF * v * gamm * cinv; + LV[0][3] = -HALF * w * gamm * cinv; + LV[0][4] = HALF * gamm * cinv; + + LV[1][0] = -v; + LV[1][2] = ONE; + + LV[2][0] = -w; + LV[2][3] = ONE; + + LV[3][0] = -gamm * cinv * (qsq - H); + LV[3][1] = u * gamm * cinv; + LV[3][2] = v * gamm * cinv; + LV[3][3] = w * gamm * cinv; + LV[3][4] = -gamm * cinv; + + LV[4][0] = -HALF * cinv * (u - HALF * gamm * qsq); + LV[4][1] = -HALF * cinv * (gamm * u - ONE); + LV[4][2] = -HALF * v * gamm * cinv; + LV[4][3] = -HALF * w * gamm * cinv; + LV[4][4] = HALF * gamm * cinv; + + // compute fluxes and max wave speed over stencil + alpha = ZERO; + for (j = 0; j < STSIZE; j++) + { + u = w1d[j][1] / w1d[j][0]; // u = vx = mx/rho + flux[j][0] = w1d[j][1]; // f_rho = rho*u = mx + flux[j][1] = u * w1d[j][1] + p[j]; // f_mx = rho*u*u + p = mx*u + p + flux[j][2] = u * w1d[j][2]; // f_my = rho*v*u = my*u + flux[j][3] = u * w1d[j][3]; // f_mz = rho*w*u = mz*u + flux[j][4] = u * (w1d[j][4] + p[j]); // f_et = u*(et + p) + csnd = sqrt(udata.gamma * p[j] / w1d[j][0]); // csnd = sqrt(gamma*p/rho) + alpha = max(alpha, abs(u) + csnd); + } + + // compute flux from right side of face at x_{i+1/2}: + + // compute right-shifted Lax-Friedrichs flux over left portion of patch + for (j = 0; j < 5; j++) + { + for (i = 0; i < NSPECIES; i++) + { + fs[j][i] = HALF * (flux[j][i] + alpha * w1d[j][i]); + } + } + + // compute projected flux for fluid fields + for (j = 0; j < 5; j++) + { + for (i = 0; i < 5; i++) + { + fproj[j][i] = LV[i][0] * fs[j][0] + LV[i][1] * fs[j][1] + + LV[i][2] * fs[j][2] + LV[i][3] * fs[j][3] + + LV[i][4] * fs[j][4]; + } + } + + // compute WENO signed flux + for (i = 0; i < NSPECIES; i++) + { + // smoothness indicators + beta1 = bc * pow(fproj[2][i] - SUN_RCONST(2.0) * fproj[3][i] + fproj[4][i], + 2) + + FOURTH * pow(SUN_RCONST(3.0) * fproj[2][i] - + SUN_RCONST(4.0) * fproj[3][i] + fproj[4][i], + 2); + beta2 = bc * pow(fproj[1][i] - SUN_RCONST(2.0) * fproj[2][i] + fproj[3][i], + 2) + + FOURTH * pow(fproj[1][i] - fproj[3][i], 2); + beta3 = bc * pow(fproj[0][i] - SUN_RCONST(2.0) * fproj[1][i] + fproj[2][i], + 2) + + FOURTH * pow(fproj[0][i] - SUN_RCONST(4.0) * fproj[1][i] + + SUN_RCONST(3.0) * fproj[2][i], + 2); + // nonlinear weights + w1 = SUN_RCONST(0.3) / ((epsilon + beta1) * (epsilon + beta1)); + w2 = SUN_RCONST(0.6) / ((epsilon + beta2) * (epsilon + beta2)); + w3 = SUN_RCONST(0.1) / ((epsilon + beta3) * (epsilon + beta3)); + // flux stencils + f1 = SUN_RCONST(0.3333333333333333333333333333333333333333) * fproj[2][i] + + SUN_RCONST(0.8333333333333333333333333333333333333333) * fproj[3][i] - + SUN_RCONST(0.1666666666666666666666666666666666666667) * fproj[4][i]; + f2 = -SUN_RCONST(0.1666666666666666666666666666666666666667) * fproj[1][i] + + SUN_RCONST(0.8333333333333333333333333333333333333333) * fproj[2][i] + + SUN_RCONST(0.3333333333333333333333333333333333333333) * fproj[3][i]; + f3 = SUN_RCONST(0.3333333333333333333333333333333333333333) * fproj[0][i] - + SUN_RCONST(1.166666666666666666666666666666666666667) * fproj[1][i] + + SUN_RCONST(1.833333333333333333333333333333333333333) * fproj[2][i]; + // resulting signed flux at face + ff[i] = (f1 * w1 + f2 * w2 + f3 * w3) / (w1 + w2 + w3); + } + + // compute flux from left side of face at x_{i+1/2}: + + // compute left-shifted Lax-Friedrichs flux over right portion of patch + for (j = 0; j < 5; j++) + { + for (i = 0; i < NSPECIES; i++) + { + fs[j][i] = HALF * (flux[j + 1][i] - alpha * w1d[j + 1][i]); + } + } + + // compute projected flux for fluid fields + for (j = 0; j < 5; j++) + { + for (i = 0; i < 5; i++) + { + fproj[j][i] = LV[i][0] * fs[j][0] + LV[i][1] * fs[j][1] + + LV[i][2] * fs[j][2] + LV[i][3] * fs[j][3] + + LV[i][4] * fs[j][4]; + } + } + + // compute WENO signed fluxes + for (i = 0; i < NSPECIES; i++) + { + // smoothness indicators + beta1 = bc * pow(fproj[2][i] - SUN_RCONST(2.0) * fproj[3][i] + fproj[4][i], + 2) + + FOURTH * pow(SUN_RCONST(3.0) * fproj[2][i] - + SUN_RCONST(4.0) * fproj[3][i] + fproj[4][i], + 2); + beta2 = bc * pow(fproj[1][i] - SUN_RCONST(2.0) * fproj[2][i] + fproj[3][i], + 2) + + FOURTH * pow(fproj[1][i] - fproj[3][i], 2); + beta3 = bc * pow(fproj[0][i] - SUN_RCONST(2.0) * fproj[1][i] + fproj[2][i], + 2) + + FOURTH * pow(fproj[0][i] - SUN_RCONST(4.0) * fproj[1][i] + + SUN_RCONST(3.0) * fproj[2][i], + 2); + // nonlinear weights + w1 = SUN_RCONST(0.1) / ((epsilon + beta1) * (epsilon + beta1)); + w2 = SUN_RCONST(0.6) / ((epsilon + beta2) * (epsilon + beta2)); + w3 = SUN_RCONST(0.3) / ((epsilon + beta3) * (epsilon + beta3)); + // flux stencils + f1 = SUN_RCONST(1.833333333333333333333333333333333333333) * fproj[2][i] - + SUN_RCONST(1.166666666666666666666666666666666666667) * fproj[3][i] + + SUN_RCONST(0.3333333333333333333333333333333333333333) * fproj[4][i]; + f2 = SUN_RCONST(0.3333333333333333333333333333333333333333) * fproj[1][i] + + SUN_RCONST(0.8333333333333333333333333333333333333333) * fproj[2][i] - + SUN_RCONST(0.1666666666666666666666666666666666666667) * fproj[3][i]; + f3 = -SUN_RCONST(0.1666666666666666666666666666666666666667) * fproj[0][i] + + SUN_RCONST(0.8333333333333333333333333333333333333333) * fproj[1][i] + + SUN_RCONST(0.3333333333333333333333333333333333333333) * fproj[2][i]; + // resulting signed flux (add to ff) + ff[i] += (f1 * w1 + f2 * w2 + f3 * w3) / (w1 + w2 + w3); + } + + // combine signed fluxes into output, converting back to conserved variables + for (i = 0; i < NSPECIES; i++) + { + f_face[i] = RV[i][0] * ff[0] + RV[i][1] * ff[1] + RV[i][2] * ff[2] + + RV[i][3] * ff[3] + RV[i][4] * ff[4]; + } + return; +} + +// Compute the initial condition +int SetIC(N_Vector y, EulerData& udata) +{ + sunrealtype* rho = N_VGetSubvectorArrayPointer_ManyVector(y, 0); + if (check_ptr(rho, "N_VGetSubvectorArrayPointer_ManyVector")) { return -1; } + sunrealtype* mx = N_VGetSubvectorArrayPointer_ManyVector(y, 1); + if (check_ptr(mx, "N_VGetSubvectorArrayPointer_ManyVector")) { return -1; } + sunrealtype* my = N_VGetSubvectorArrayPointer_ManyVector(y, 2); + if (check_ptr(my, "N_VGetSubvectorArrayPointer_ManyVector")) { return -1; } + sunrealtype* mz = N_VGetSubvectorArrayPointer_ManyVector(y, 3); + if (check_ptr(mz, "N_VGetSubvectorArrayPointer_ManyVector")) { return -1; } + sunrealtype* et = N_VGetSubvectorArrayPointer_ManyVector(y, 4); + if (check_ptr(et, "N_VGetSubvectorArrayPointer_ManyVector")) { return -1; } + + for (long int i = 0; i < udata.nx; i++) + { + sunrealtype xloc = ((sunrealtype)i + HALF) * udata.dx + udata.xl; + if (xloc < HALF) + { + rho[i] = rhoL; + et[i] = udata.eos_inv(rhoL, uL, ZERO, ZERO, pL); + mx[i] = rhoL * uL; + } + else + { + rho[i] = rhoR; + et[i] = udata.eos_inv(rhoR, uR, ZERO, ZERO, pR); + mx[i] = rhoR * uR; + } + my[i] = ZERO; + mz[i] = ZERO; + } + + return 0; +} + +//---- end of file ---- diff --git a/examples/arkode/CXX_manyvector/ark_sod_lsrk.hpp b/examples/arkode/CXX_manyvector/ark_sod_lsrk.hpp new file mode 100644 index 0000000000..0ccd7959df --- /dev/null +++ b/examples/arkode/CXX_manyvector/ark_sod_lsrk.hpp @@ -0,0 +1,538 @@ +/* ----------------------------------------------------------------------------- + * Programmer(s): Daniel R. Reynolds @ SMU + * ----------------------------------------------------------------------------- + * SUNDIALS Copyright Start + * Copyright (c) 2002-2024, Lawrence Livermore National Security + * and Southern Methodist University. + * All rights reserved. + * + * See the top-level LICENSE and NOTICE files for details. + * + * SPDX-License-Identifier: BSD-3-Clause + * SUNDIALS Copyright End + * ----------------------------------------------------------------------------- + * Header file for ARKODE LSRKStep Sod shock tube example, see + * ark_sod_lsrk.cpp for more details. + * ---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Include desired integrators, vectors, linear solvers, and nonlinear solvers +#include "arkode/arkode_erkstep.h" +#include "arkode/arkode_lsrkstep.h" +#include "nvector/nvector_manyvector.h" +#include "nvector/nvector_serial.h" +#include "sundials/sundials_core.hpp" + +// Macros for problem constants +#define rhoL SUN_RCONST(1.0) +#define rhoR SUN_RCONST(0.125) +#define pL SUN_RCONST(1.0) +#define pR SUN_RCONST(0.1) +#define uL SUN_RCONST(0.0) +#define uR SUN_RCONST(0.0) +#define HALF SUN_RCONST(0.5) +#define ZERO SUN_RCONST(0.0) +#define ONE SUN_RCONST(1.0) +#define TWO SUN_RCONST(2.0) +#define FOURTH SUN_RCONST(0.25) + +#define NSPECIES 5 +#define STSIZE 6 + +#define WIDTH (10 + std::numeric_limits::digits10) + +// ----------------------------------------------------------------------------- +// Problem options +// ----------------------------------------------------------------------------- + +class ARKODEParameters +{ +public: + // Integration method (ARKODE_LSRK_SSP_S_2, ARKODE_LSRK_SSP_S_3, ARKODE_LSRK_SSP_10_4, + // or any valid ARKODE_ERKTableID for ERK methods) + std::string integrator; + + // Method stages (0 => to use the default; ignored if using ARKODE_LSRK_SSP_10_4 or + // an ERK method) + int stages; + + // Relative and absolute tolerances + sunrealtype rtol; + sunrealtype atol; + + // Step size selection (ZERO = adaptive steps) + sunrealtype fixed_h; + + // Maximum number of time steps between outputs + int maxsteps; + + // Output-related information + int output; // 0 = none, 1 = stats, 2 = disk, 3 = disk with tstop + int nout; // number of output times + std::ofstream uout; // output file stream + + // constructor (with default values) + ARKODEParameters() + : integrator("ARKODE_LSRK_SSP_10_4"), + stages(0), + rtol(SUN_RCONST(1.e-4)), + atol(SUN_RCONST(1.e-11)), + fixed_h(ZERO), + maxsteps(10000), + output(1), + nout(10){}; + +}; // end ARKODEParameters + +// ----------------------------------------------------------------------------- +// Problem parameters +// ----------------------------------------------------------------------------- + +// user data class +class EulerData +{ +public: + ///// domain related data ///// + long int nx; // global number of x grid points + sunrealtype t0; // time domain extents + sunrealtype tf; + sunrealtype xl; // spatial domain extents + sunrealtype xr; + sunrealtype dx; // spatial mesh spacing + + ///// problem-defining data ///// + sunrealtype gamma; // ratio of specific heat capacities, cp/cv + + ///// reusable arrays for WENO flux calculations ///// + sunrealtype* flux; + sunrealtype w1d[STSIZE][NSPECIES]; + + ///// class operations ///// + + // constructor + EulerData() + : nx(512), + t0(ZERO), + tf(SUN_RCONST(0.1)), + xl(ZERO), + xr(ONE), + dx(ZERO), + gamma(SUN_RCONST(1.4)), + flux(nullptr){}; + + // manual destructor + void FreeData() + { + delete[] flux; + flux = nullptr; + }; + + // destructor + ~EulerData() { this->FreeData(); }; + + // Utility routine to pack 1-dimensional data for *interior only* data; + // e.g., in the x-direction given a location (i), we return values at + // the 6 nodal values closest to the (i-1/2) face along the x-direction, + // {w(i-3), w(i-2), w(i-1), w(i), w(i+1), w(i+2)}. + inline void pack1D(const sunrealtype* rho, const sunrealtype* mx, + const sunrealtype* my, const sunrealtype* mz, + const sunrealtype* et, const long int& i) + { + for (int l = 0; l < STSIZE; l++) { this->w1d[l][0] = rho[i - 3 + l]; } + for (int l = 0; l < STSIZE; l++) { this->w1d[l][1] = mx[i - 3 + l]; } + for (int l = 0; l < STSIZE; l++) { this->w1d[l][2] = my[i - 3 + l]; } + for (int l = 0; l < STSIZE; l++) { this->w1d[l][3] = mz[i - 3 + l]; } + for (int l = 0; l < STSIZE; l++) { this->w1d[l][4] = et[i - 3 + l]; } + } + + // Utility routine to pack 1-dimensional data for locations near the + // boundary; like the routine above this packs the 6 closest + // entries aligned with, e.g., the (i-1/2) face, but now some entries + // are set to satisfy homogeneous Neumann boundary conditions. + inline void pack1D_bdry(const sunrealtype* rho, const sunrealtype* mx, + const sunrealtype* my, const sunrealtype* mz, + const sunrealtype* et, const long int& i) + { + for (int l = 0; l < 3; l++) + { + this->w1d[l][0] = (i < (3 - l)) ? rho[2 - (i + l)] : rho[i - 3 + l]; + } + for (int l = 0; l < 3; l++) + { + this->w1d[l][1] = (i < (3 - l)) ? mx[2 - (i + l)] : mx[i - 3 + l]; + } + for (int l = 0; l < 3; l++) + { + this->w1d[l][2] = (i < (3 - l)) ? my[2 - (i + l)] : my[i - 3 + l]; + } + for (int l = 0; l < 3; l++) + { + this->w1d[l][3] = (i < (3 - l)) ? mz[2 - (i + l)] : mz[i - 3 + l]; + } + for (int l = 0; l < 3; l++) + { + this->w1d[l][4] = (i < (3 - l)) ? et[2 - (i + l)] : et[i - 3 + l]; + } + for (int l = 0; l < 3; l++) + { + this->w1d[l + 3][0] = (i > (nx - l - 1)) ? rho[i + l - 3] : rho[i + l]; + } + for (int l = 0; l < 3; l++) + { + this->w1d[l + 3][1] = (i > (nx - l - 1)) ? mx[i + l - 3] : mx[i + l]; + } + for (int l = 0; l < 3; l++) + { + this->w1d[l + 3][2] = (i > (nx - l - 1)) ? my[i + l - 3] : my[i + l]; + } + for (int l = 0; l < 3; l++) + { + this->w1d[l + 3][3] = (i > (nx - l - 1)) ? mz[i + l - 3] : mz[i + l]; + } + for (int l = 0; l < 3; l++) + { + this->w1d[l + 3][4] = (i > (nx - l - 1)) ? et[i + l - 3] : et[i + l]; + } + } + + // Equation of state -- compute and return pressure, + // p = (gamma-1)*(e - rho/2*(vx^2+vy^2+vz^2)), or equivalently + // p = (gamma-1)*(e - (mx^2+my^2+mz^2)/(2*rho)) + inline sunrealtype eos(const sunrealtype& rho, const sunrealtype& mx, + const sunrealtype& my, const sunrealtype& mz, + const sunrealtype& et) const + { + return ((gamma - ONE) * (et - (mx * mx + my * my + mz * mz) * HALF / rho)); + } + + // Equation of state inverse -- compute and return energy, + // e_t = p/(gamma-1) + rho/2*(vx^2+vy^2+vz^2), or equivalently + // e_t = p/(gamma-1) + (mx^2+my^2+mz^2)/(2*rho) + inline sunrealtype eos_inv(const sunrealtype& rho, const sunrealtype& mx, + const sunrealtype& my, const sunrealtype& mz, + const sunrealtype& pr) const + { + return (pr / (gamma - ONE) + (mx * mx + my * my + mz * mz) * HALF / rho); + } + +}; // end EulerData; + +// ----------------------------------------------------------------------------- +// Functions provided to the SUNDIALS integrators +// ----------------------------------------------------------------------------- + +// ODE right hand side (RHS) functions +int frhs(sunrealtype t, N_Vector y, N_Vector f, void* user_data); + +// ----------------------------------------------------------------------------- +// Helper functions +// ----------------------------------------------------------------------------- + +// WENO flux calculation helper function +void face_flux(sunrealtype (&w1d)[6][NSPECIES], sunrealtype* f_face, + const EulerData& udata); + +// Compute the initial condition +int SetIC(N_Vector y, EulerData& udata); + +// ----------------------------------------------------------------------------- +// Output and utility functions +// ----------------------------------------------------------------------------- + +// Check function return flag +static int check_flag(int flag, const std::string funcname) +{ + if (flag < 0) + { + std::cerr << "ERROR: " << funcname << " returned " << flag << std::endl; + return 1; + } + return 0; +} + +// Check if a function returned a NULL pointer +static int check_ptr(void* ptr, const std::string funcname) +{ + if (ptr) { return 0; } + std::cerr << "ERROR: " << funcname << " returned NULL" << std::endl; + return 1; +} + +// Print command line options +static void InputHelp() +{ + std::cout << std::endl; + std::cout << "Command line options:" << std::endl; + std::cout << " --integrator : method (ARKODE_LSRK_SSP_S_2, " + "ARKODE_LSRK_SSP_S_3, " + "ARKODE_LSRK_SSP_10_4, or any valid ARKODE_ERKTableID)\n"; + std::cout << " --stages : number of stages (ignored for " + "ARKODE_LSRK_SSP_10_4 and ERK)\n"; + std::cout << " --tf : final time\n"; + std::cout << " --xl : domain lower boundary\n"; + std::cout << " --xr : domain upper boundary\n"; + std::cout << " --gamma : ideal gas constant\n"; + std::cout << " --nx : number of mesh points\n"; + std::cout << " --rtol : relative tolerance\n"; + std::cout << " --atol : absolute tolerance\n"; + std::cout << " --fixed_h : fixed step size\n"; + std::cout << " --maxsteps : max steps between outputs\n"; + std::cout << " --output : output level\n"; + std::cout << " --nout : number of outputs\n"; + std::cout << " --help : print options and exit\n"; +} + +inline void find_arg(std::vector& args, const std::string key, + sunrealtype& dest) +{ + auto it = find(args.begin(), args.end(), key); + if (it != args.end()) + { +#if defined(SUNDIALS_SINGLE_PRECISION) + dest = stof(*(it + 1)); +#elif defined(SUNDIALS_DOUBLE_PRECISION) + dest = stod(*(it + 1)); +#elif defined(SUNDIALS_EXTENDED_PRECISION) + dest = stold(*(it + 1)); +#endif + args.erase(it, it + 2); + } +} + +inline void find_arg(std::vector& args, const std::string key, + long int& dest) +{ + auto it = find(args.begin(), args.end(), key); + if (it != args.end()) + { + dest = stoll(*(it + 1)); + args.erase(it, it + 2); + } +} + +inline void find_arg(std::vector& args, const std::string key, + int& dest) +{ + auto it = find(args.begin(), args.end(), key); + if (it != args.end()) + { + dest = stoi(*(it + 1)); + args.erase(it, it + 2); + } +} + +inline void find_arg(std::vector& args, const std::string key, + std::string& dest) +{ + auto it = find(args.begin(), args.end(), key); + if (it != args.end()) + { + dest = *(it + 1); + args.erase(it, it + 2); + } +} + +inline void find_arg(std::vector& args, const std::string key, + bool& dest, bool store = true) +{ + auto it = find(args.begin(), args.end(), key); + if (it != args.end()) + { + dest = store; + args.erase(it); + } +} + +static int ReadInputs(std::vector& args, EulerData& udata, + ARKODEParameters& uopts, SUNContext ctx) +{ + if (find(args.begin(), args.end(), "--help") != args.end()) + { + InputHelp(); + return 1; + } + + // Problem parameters + find_arg(args, "--gamma", udata.gamma); + find_arg(args, "--tf", udata.tf); + find_arg(args, "--xl", udata.xl); + find_arg(args, "--xr", udata.xr); + find_arg(args, "--nx", udata.nx); + + // Integrator options + find_arg(args, "--integrator", uopts.integrator); + find_arg(args, "--stages", uopts.stages); + find_arg(args, "--rtol", uopts.rtol); + find_arg(args, "--atol", uopts.atol); + find_arg(args, "--fixed_h", uopts.fixed_h); + find_arg(args, "--maxsteps", uopts.maxsteps); + find_arg(args, "--output", uopts.output); + find_arg(args, "--nout", uopts.nout); + + // Recompute mesh spacing and [re]allocate flux array + udata.dx = (udata.xr - udata.xl) / ((sunrealtype)udata.nx); + if (udata.flux) { delete[] udata.flux; } + udata.flux = new sunrealtype[NSPECIES * (udata.nx + 1)]; + + if (uopts.stages < 0) + { + std::cerr << "ERROR: Invalid number of stages" << std::endl; + return -1; + } + + return 0; +} + +// Print user data +static int PrintSetup(EulerData& udata, ARKODEParameters& uopts) +{ + std::cout << std::endl; + std::cout << "Problem parameters and options:" << std::endl; + std::cout << " --------------------------------- " << std::endl; + std::cout << " gamma = " << udata.gamma << std::endl; + std::cout << " --------------------------------- " << std::endl; + std::cout << " tf = " << udata.tf << std::endl; + std::cout << " xl = " << udata.xl << std::endl; + std::cout << " xr = " << udata.xr << std::endl; + std::cout << " nx = " << udata.nx << std::endl; + std::cout << " dx = " << udata.dx << std::endl; + std::cout << " --------------------------------- " << std::endl; + std::cout << " integrator = " << uopts.integrator << std::endl; + if (uopts.stages > 0) + { + std::cout << " stages = " << uopts.stages << std::endl; + } + std::cout << " rtol = " << uopts.rtol << std::endl; + std::cout << " atol = " << uopts.atol << std::endl; + std::cout << " fixed h = " << uopts.fixed_h << std::endl; + std::cout << " --------------------------------- " << std::endl; + std::cout << " output = " << uopts.output << std::endl; + std::cout << " --------------------------------- " << std::endl; + std::cout << std::endl; + + return 0; +} + +// Initialize output +static int OpenOutput(EulerData& udata, ARKODEParameters& uopts) +{ + // Header for status output + if (uopts.output) + { + std::cout << std::scientific; + std::cout << std::setprecision(std::numeric_limits::digits10); + std::cout << " t " + << " ||rho|| " + << " ||mx|| " + << " ||my|| " + << " ||mz|| " + << " ||et||" << std::endl; + std::cout + << " -----------------------------------------------------------------" + "---------" + << std::endl; + } + + // Open output stream and output problem information + if (uopts.output >= 2) + { + // Open output stream + std::stringstream fname; + fname << "sod.out"; + uopts.uout.open(fname.str()); + + uopts.uout << std::scientific; + uopts.uout << std::setprecision(std::numeric_limits::digits10); + uopts.uout << "# title Sod Shock Tube" << std::endl; + uopts.uout << "# nvar 5" << std::endl; + uopts.uout << "# vars rho mx my mz et" << std::endl; + uopts.uout << "# nt " << uopts.nout + 1 << std::endl; + uopts.uout << "# nx " << udata.nx << std::endl; + uopts.uout << "# xl " << udata.xl << std::endl; + uopts.uout << "# xr " << udata.xr << std::endl; + } + + return 0; +} + +// Write output +static int WriteOutput(sunrealtype t, N_Vector y, EulerData& udata, + ARKODEParameters& uopts) +{ + if (uopts.output) + { + // Compute rms norm of the state + N_Vector rho = N_VGetSubvector_ManyVector(y, 0); + N_Vector mx = N_VGetSubvector_ManyVector(y, 1); + N_Vector my = N_VGetSubvector_ManyVector(y, 2); + N_Vector mz = N_VGetSubvector_ManyVector(y, 3); + N_Vector et = N_VGetSubvector_ManyVector(y, 4); + sunrealtype rhorms = sqrt(N_VDotProd(rho, rho) / (sunrealtype)udata.nx); + sunrealtype mxrms = sqrt(N_VDotProd(mx, mx) / (sunrealtype)udata.nx); + sunrealtype myrms = sqrt(N_VDotProd(my, my) / (sunrealtype)udata.nx); + sunrealtype mzrms = sqrt(N_VDotProd(mz, mz) / (sunrealtype)udata.nx); + sunrealtype etrms = sqrt(N_VDotProd(et, et) / (sunrealtype)udata.nx); + std::cout << std::setprecision(2) << " " << t << std::setprecision(5) + << " " << rhorms << " " << mxrms << " " << myrms << " " + << mzrms << " " << etrms << std::endl; + + // Write solution to disk + if (uopts.output >= 2) + { + sunrealtype* rhodata = N_VGetArrayPointer(rho); + if (check_ptr(rhodata, "N_VGetArrayPointer")) { return -1; } + sunrealtype* mxdata = N_VGetArrayPointer(mx); + if (check_ptr(mxdata, "N_VGetArrayPointer")) { return -1; } + sunrealtype* mydata = N_VGetArrayPointer(my); + if (check_ptr(mydata, "N_VGetArrayPointer")) { return -1; } + sunrealtype* mzdata = N_VGetArrayPointer(mz); + if (check_ptr(mzdata, "N_VGetArrayPointer")) { return -1; } + sunrealtype* etdata = N_VGetArrayPointer(et); + if (check_ptr(etdata, "N_VGetArrayPointer")) { return -1; } + + uopts.uout << t; + for (sunindextype i = 0; i < udata.nx; i++) + { + uopts.uout << std::setw(WIDTH) << rhodata[i]; + uopts.uout << std::setw(WIDTH) << mxdata[i]; + uopts.uout << std::setw(WIDTH) << mydata[i]; + uopts.uout << std::setw(WIDTH) << mzdata[i]; + uopts.uout << std::setw(WIDTH) << etdata[i]; + } + uopts.uout << std::endl; + } + } + + return 0; +} + +// Finalize output +static int CloseOutput(ARKODEParameters& uopts) +{ + // Footer for status output + if (uopts.output) + { + std::cout + << " -----------------------------------------------------------------" + "---------" + << std::endl; + std::cout << std::endl; + } + + // Close output streams + if (uopts.output >= 2) { uopts.uout.close(); } + + return 0; +} + +//---- end of file ---- diff --git a/examples/arkode/CXX_manyvector/ark_sod_lsrk.out b/examples/arkode/CXX_manyvector/ark_sod_lsrk.out new file mode 100644 index 0000000000..24abdf255d --- /dev/null +++ b/examples/arkode/CXX_manyvector/ark_sod_lsrk.out @@ -0,0 +1,48 @@ + +Problem parameters and options: + --------------------------------- + gamma = 1.4 + --------------------------------- + tf = 0.1 + xl = 0 + xr = 1 + nx = 512 + dx = 0.00195312 + --------------------------------- + integrator = ARKODE_LSRK_SSP_10_4 + rtol = 0.0001 + atol = 1e-11 + fixed h = 0 + --------------------------------- + output = 1 + --------------------------------- + + t ||rho|| ||mx|| ||my|| ||mz|| ||et|| + -------------------------------------------------------------------------- + 0.00e+00 7.12610e-01 0.00000e+00 0.00000e+00 0.00000e+00 1.77658e+00 + 1.00e-02 7.09460e-01 5.28096e-02 0.00000e+00 0.00000e+00 1.76732e+00 + 2.00e-02 7.06459e-01 7.61804e-02 0.00000e+00 0.00000e+00 1.75863e+00 + 3.00e-02 7.03444e-01 9.39395e-02 0.00000e+00 0.00000e+00 1.74990e+00 + 4.00e-02 7.00418e-01 1.08850e-01 0.00000e+00 0.00000e+00 1.74113e+00 + 5.00e-02 6.97379e-01 1.21955e-01 0.00000e+00 0.00000e+00 1.73232e+00 + 6.00e-02 6.94326e-01 1.33784e-01 0.00000e+00 0.00000e+00 1.72346e+00 + 7.00e-02 6.91261e-01 1.44650e-01 0.00000e+00 0.00000e+00 1.71456e+00 + 8.00e-02 6.88182e-01 1.54756e-01 0.00000e+00 0.00000e+00 1.70561e+00 + 9.00e-02 6.85089e-01 1.64242e-01 0.00000e+00 0.00000e+00 1.69661e+00 + 1.00e-01 6.81982e-01 1.73210e-01 0.00000e+00 0.00000e+00 1.68756e+00 + -------------------------------------------------------------------------- + +Final integrator statistics: +Current time = 0.1 +Steps = 382 +Step attempts = 397 +Stability limited steps = 0 +Accuracy limited steps = 397 +Error test fails = 15 +NLS step fails = 0 +Inequality constraint fails = 0 +Initial step size = 1.122284259749542e-14 +Last step size = 0.0002334416078592081 +Current step size = 0.0002334416078592081 +RHS fn evals = 3957 +Number of stages used = 10 diff --git a/examples/arkode/CXX_manyvector/plot_sod.py b/examples/arkode/CXX_manyvector/plot_sod.py new file mode 100755 index 0000000000..2e87566718 --- /dev/null +++ b/examples/arkode/CXX_manyvector/plot_sod.py @@ -0,0 +1,231 @@ +#!/usr/bin/env python3 +# ------------------------------------------------------------------------------ +# Programmer(s): Daniel R. Reynolds @ SMU +# ------------------------------------------------------------------------------ +# SUNDIALS Copyright Start +# Copyright (c) 2002-2024, Lawrence Livermore National Security +# and Southern Methodist University. +# All rights reserved. +# +# See the top-level LICENSE and NOTICE files for details. +# +# SPDX-License-Identifier: BSD-3-Clause +# SUNDIALS Copyright End +# ------------------------------------------------------------------------------ +# matplotlib-based plotting script for the serial ark_sod_lsrk example +# ------------------------------------------------------------------------------ + +# imports +import sys, os +import numpy as np +import matplotlib.pyplot as plt +from matplotlib.gridspec import GridSpec + +# data file name +datafile = "sod.out" + +# return with an error if the file does not exist +if not os.path.isfile(datafile): + msg = "Error: file " + datafile + " does not exist" + sys.exit(msg) + +# read solution file, storing each line as a string in a list +with open(datafile, "r") as file: + lines = file.readlines() + + # extract header information + title = lines.pop(0) + nvar = int((lines.pop(0).split())[2]) + varnames = lines.pop(0) + nt = int((lines.pop(0).split())[2]) + nx = int((lines.pop(0).split())[2]) + xl = float((lines.pop(0).split())[2]) + xr = float((lines.pop(0).split())[2]) + + # allocate solution data as 2D Python arrays + t = np.zeros((nt), dtype=float) + rho = np.zeros((nt, nx), dtype=float) + mx = np.zeros((nt, nx), dtype=float) + my = np.zeros((nt, nx), dtype=float) + mz = np.zeros((nt, nx), dtype=float) + et = np.zeros((nt, nx), dtype=float) + x = np.linspace(xl, xr, nx) + + # store remaining data into numpy arrays + for it in range(nt): + line = (lines.pop(0)).split() + t[it] = line.pop(0) + for ix in range(nx): + rho[it, ix] = line.pop(0) + mx[it, ix] = line.pop(0) + my[it, ix] = line.pop(0) + mz[it, ix] = line.pop(0) + et[it, ix] = line.pop(0) + + gamma = 1.4 + u = mx / rho + p = (gamma - 1.0) * (et - (mx * mx + my * my + mz * mz) / (2.0 * rho)) + + +# utility routines for computing the analytical solution +def fsecant(p4, p1, p5, rho1, rho5, gamma): + """ + Utility routine for exact_Riemann function below + """ + z = p4 / p5 - 1.0 + c1 = np.sqrt(gamma * p1 / rho1) + c5 = np.sqrt(gamma * p5 / rho5) + gm1 = gamma - 1.0 + gp1 = gamma + 1.0 + g2 = 2.0 * gamma + fact = gm1 / g2 * (c5 / c1) * z / np.sqrt(1.0 + gp1 / g2 * z) + fact = (1.0 - fact) ** (g2 / gm1) + return p1 * fact - p4 + + +def exact_Riemann(t, x, xI): + """ + Exact 1D Riemann problem solver (retrieves domain from EulerData structure), + based on Fortran code at http://cococubed.asu.edu/codes/riemann/exact_riemann.f + + Inputs: (t,x) location for desired solution, + xI location of discontinuity at t=0, + gamma parameter for gas equation of state + Outputs: rho, u, p (density, velocity, and pressure at (t,x)) + """ + + # begin solution + rho1 = 1.0 + p1 = 1.0 + u1 = 0.0 + rho5 = 0.125 + p5 = 0.1 + u5 = 0.0 + + # solve for post-shock pressure by secant method initial guesses + p40 = p1 + p41 = p5 + f0 = fsecant(p40, p1, p5, rho1, rho5, gamma) + itmax = 50 + eps = 1.0e-14 + for iter in range(itmax): + f1 = fsecant(p41, p1, p5, rho1, rho5, gamma) + if f1 == f0: + break + p4 = p41 - (p41 - p40) * f1 / (f1 - f0) + if (np.abs(p4 - p41) / np.abs(p41)) < eps: + break + p40 = p41 + p41 = p4 + f0 = f1 + if iter == itmax - 1: + raise ValueError("exact_Riemann iteration failed to converge") + + # compute post-shock density and velocity + z = p4 / p5 - 1.0 + c5 = np.sqrt(gamma * p5 / rho5) + + gm1 = gamma - 1.0 + gp1 = gamma + 1.0 + + fact = np.sqrt(1.0 + 0.5 * gp1 * z / gamma) + + u4 = c5 * z / (gamma * fact) + rho4 = rho5 * (1.0 + 0.5 * gp1 * z / gamma) / (1.0 + 0.5 * gm1 * z / gamma) + + # shock speed + w = c5 * fact + + # compute values at foot of rarefaction + p3 = p4 + u3 = u4 + rho3 = rho1 * (p3 / p1) ** (1.0 / gamma) + + # compute positions of waves + c1 = np.sqrt(gamma * p1 / rho1) + c3 = np.sqrt(gamma * p3 / rho3) + + xsh = xI + w * t + xcd = xI + u3 * t + xft = xI + (u3 - c3) * t + xhd = xI - c1 * t + + # compute solution as a function of position + if x < xhd: + rho = rho1 + p = p1 + u = u1 + elif x < xft: + u = 2.0 / gp1 * (c1 + (x - xI) / t) + fact = 1.0 - 0.5 * gm1 * u / c1 + rho = rho1 * fact ** (2.0 / gm1) + p = p1 * fact ** (2.0 * gamma / gm1) + elif x < xcd: + rho = rho3 + p = p3 + u = u3 + elif x < xsh: + rho = rho4 + p = p4 + u = u4 + else: + rho = rho5 + p = p5 + u = u5 + + # return with success + return rho, u, p + + +# generate analytical solutions over same mesh and times as loaded from data file +rhotrue = np.zeros((nt, nx), dtype=float) +utrue = np.zeros((nt, nx), dtype=float) +ptrue = np.zeros((nt, nx), dtype=float) +for it in range(nt): + for ix in range(nx): + rhotrue[it, ix], utrue[it, ix], ptrue[it, ix] = exact_Riemann(t[it], x[ix], 0.5) + +# plot defaults: increase default font size, increase plot width, enable LaTeX rendering +plt.rc("font", size=15) +plt.rcParams["figure.figsize"] = [7.2, 4.8] +plt.rcParams["text.usetex"] = True +plt.rcParams["figure.constrained_layout.use"] = True + +# subplots with time snapshots of the density, x-velocity, and pressure +fig = plt.figure(figsize=(10, 5)) +gs = GridSpec(3, 3, figure=fig) +ax00 = fig.add_subplot(gs[0, 0]) # left column +ax10 = fig.add_subplot(gs[1, 0]) +ax20 = fig.add_subplot(gs[2, 0]) +ax01 = fig.add_subplot(gs[0, 1]) # middle column +ax11 = fig.add_subplot(gs[1, 1]) +ax21 = fig.add_subplot(gs[2, 1]) +ax02 = fig.add_subplot(gs[0, 2]) # right column +ax12 = fig.add_subplot(gs[1, 2]) +ax22 = fig.add_subplot(gs[2, 2]) +it = 0 +ax00.plot(x, rho[it, :], "-b", x, rhotrue[it, :], ":k") +ax10.plot(x, u[it, :], "-b", x, utrue[it, :], ":k") +ax20.plot(x, p[it, :], "-b", x, ptrue[it, :], ":k") +ax00.set_title(r"$t =$ " + repr(t[it]).zfill(3)) +ax00.set_ylabel(r"$\rho$") +ax10.set_ylabel(r"$v_x$") +ax20.set_ylabel(r"$p$") +ax20.set_xlabel(r"$x$") +it = nt // 2 +ax01.plot(x, rho[it, :], "-b", x, rhotrue[it, :], ":k") +ax11.plot(x, u[it, :], "-b", x, utrue[it, :], ":k") +ax21.plot(x, p[it, :], "-b", x, ptrue[it, :], ":k") +ax01.set_title(r"$t =$ " + repr(t[it]).zfill(3)) +ax21.set_xlabel(r"$x$") +it = nt - 1 +ax02.plot(x, rho[it, :], "-b", x, rhotrue[it, :], ":k") +ax12.plot(x, u[it, :], "-b", x, utrue[it, :], ":k") +ax22.plot(x, p[it, :], "-b", x, ptrue[it, :], ":k") +ax02.set_title(r"$t =$ " + repr(t[it]).zfill(3)) +ax22.set_xlabel(r"$x$") +plt.savefig("sod_frames.png") + +plt.show() + +##### end of script ##### diff --git a/examples/arkode/CXX_parallel/CMakeLists.txt b/examples/arkode/CXX_parallel/CMakeLists.txt index 05b2a87861..45b01819d5 100644 --- a/examples/arkode/CXX_parallel/CMakeLists.txt +++ b/examples/arkode/CXX_parallel/CMakeLists.txt @@ -121,9 +121,12 @@ set(OTHER_LIBS ${EXE_EXTRA_LINK_LIBS}) # MPI examples # ------------ -set(serial_examples "ark_heat2D_p.cpp\;\;--np 2 2\;1\;4\;develop\;default") +set(parallel_examples + "ark_heat2D_p.cpp\;\;--np 2 2\;1\;4\;develop\;default" + "ark_heat2D_lsrk_p.cpp\;\;--np 2 2\;1\;4\;exclude-single\;default") + set(SUNDIALS_LIBS sundials_arkode sundials_nvecparallel) -build_examples(serial_examples CXX) +build_examples(parallel_examples CXX) # Auxiliary files to install list(APPEND ARKODE_extras plot_heat2D_p.py) @@ -238,7 +241,7 @@ endif() if(EXAMPLES_INSTALL) - set(examples_to_install "${serial_examples}") + set(examples_to_install "${parallel_examples}") set(_sundials_targets arkode nvecparallel) if(examples_cvode) diff --git a/examples/arkode/CXX_parallel/ark_heat2D_lsrk_p.cpp b/examples/arkode/CXX_parallel/ark_heat2D_lsrk_p.cpp new file mode 100644 index 0000000000..5a69244b8b --- /dev/null +++ b/examples/arkode/CXX_parallel/ark_heat2D_lsrk_p.cpp @@ -0,0 +1,1743 @@ +/* ----------------------------------------------------------------------------- + * Programmer(s): Daniel R. Reynolds @ SMU + * + * (adapted from ark_heat2D_p.cpp, co-authored by Daniel Reynolds and David + * Gardner (LLNL)) + * ----------------------------------------------------------------------------- + * SUNDIALS Copyright Start + * Copyright (c) 2002-2024, Lawrence Livermore National Security + * and Southern Methodist University. + * All rights reserved. + * + * See the top-level LICENSE and NOTICE files for details. + * + * SPDX-License-Identifier: BSD-3-Clause + * SUNDIALS Copyright End + * ----------------------------------------------------------------------------- + * Example problem: + * + * The following test simulates a simple anisotropic 2D heat equation, + * + * u_t = kx u_xx + ky u_yy + b, + * + * for t in [0, 1] and (x,y) in [0, 1]^2, with initial conditions + * + * u(0,x,y) = sin^2(pi x) sin^2(pi y), + * + * stationary boundary conditions + * + * u_t(t,0,y) = u_t(t,1,y) = u_t(t,x,0) = u_t(t,x,1) = 0, + * + * and the heat source + * + * b(t,x,y) = -2 pi sin^2(pi x) sin^2(pi y) sin(pi t) cos(pi t) + * - kx 2 pi^2 (cos^2(pi x) - sin^2(pi x)) sin^2(pi y) cos^2(pi t) + * - ky 2 pi^2 (cos^2(pi y) - sin^2(pi y)) sin^2(pi x) cos^2(pi t). + * + * Under this setup, the problem has the analytical solution + * + * u(t,x,y) = sin^2(pi x) sin^2(pi y) cos^2(pi t). + * + * The spatial derivatives are computed using second-order centered differences, + * with the data distributed over nx * ny points on a uniform spatial grid. The + * problem is advanced in time with the LSRKStep module in ARKODE. + * Several command line options are available to change the problem parameters + * and ARKODE settings. Use the flag --help for more information. + * ---------------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "arkode/arkode_lsrkstep.h" // access to LSRKStep +#include "mpi.h" // MPI header file +#include "nvector/nvector_parallel.h" // access to the MPI N_Vector +#include "sunadaptcontroller/sunadaptcontroller_imexgus.h" +#include "sunadaptcontroller/sunadaptcontroller_soderlind.h" + +// Macros for problem constants +#define PI SUN_RCONST(3.141592653589793238462643383279502884197169) +#define ZERO SUN_RCONST(0.0) +#define ONE SUN_RCONST(1.0) +#define TWO SUN_RCONST(2.0) +#define EIGHT SUN_RCONST(8.0) + +// Macro to access (x,y) location in 1D NVector array +#define IDX(x, y, n) ((n) * (y) + (x)) + +using namespace std; + +// ----------------------------------------------------------------------------- +// User data structure +// ----------------------------------------------------------------------------- + +struct UserData +{ + // Diffusion coefficients in the x and y directions + sunrealtype kx; + sunrealtype ky; + + // Enable/disable forcing + bool forcing; + + // Final time + sunrealtype tf; + + // Upper bounds in x and y directions + sunrealtype xu; + sunrealtype yu; + + // Global number of nodes in the x and y directions + sunindextype nx; + sunindextype ny; + + // Global total number of nodes + sunindextype nodes; + + // Mesh spacing in the x and y directions + sunrealtype dx; + sunrealtype dy; + + // Local number of nodes in the x and y directions + sunindextype nx_loc; + sunindextype ny_loc; + + // Overall number of local nodes + sunindextype nodes_loc; + + // Global x and y indices of this subdomain + sunindextype is; // x starting index + sunindextype ie; // x ending index + sunindextype js; // y starting index + sunindextype je; // y ending index + + // MPI variables + MPI_Comm comm_c; // Cartesian communicator in space + + int nprocs_w; // total number of MPI processes in Comm world + int npx; // number of MPI processes in the x-direction + int npy; // number of MPI processes in the y-direction + + int myid_c; // process ID in Cartesian communicator + + // Flags denoting if this process has a neighbor + bool HaveNbrW; + bool HaveNbrE; + bool HaveNbrS; + bool HaveNbrN; + + // Neighbor IDs for exchange + int ipW; + int ipE; + int ipS; + int ipN; + + // Receive buffers for neighbor exchange + sunrealtype* Wrecv; + sunrealtype* Erecv; + sunrealtype* Srecv; + sunrealtype* Nrecv; + + // Receive requests for neighbor exchange + MPI_Request reqRW; + MPI_Request reqRE; + MPI_Request reqRS; + MPI_Request reqRN; + + // Send buffers for neighbor exchange + sunrealtype* Wsend; + sunrealtype* Esend; + sunrealtype* Ssend; + sunrealtype* Nsend; + + // Send requests for neighbor exchange + MPI_Request reqSW; + MPI_Request reqSE; + MPI_Request reqSS; + MPI_Request reqSN; + + // Integrator settings + sunrealtype rtol; // relative tolerance + sunrealtype atol; // absolute tolerance + sunrealtype hfixed; // fixed step size + int controller; // step size adaptivity method + int maxsteps; // max number of steps between outputs + bool diagnostics; // output diagnostics + + // LSRKStep options + ARKODE_LSRKMethodType method; // LSRK method choice + long int eigfrequency; // dominant eigenvalue update frequency + int stage_max_limit; // maximum number of stages per step + sunrealtype eigsafety; // dominant eigenvalue safety factor + + // Output variables + int output; // output level + int nout; // number of output times + ofstream uout; // output file stream + ofstream eout; // error file stream + N_Vector e; // error vector + + // Timing variables + bool timing; // print timings + double evolvetime; + double rhstime; + double exchangetime; +}; + +// ----------------------------------------------------------------------------- +// Functions provided to the SUNDIALS integrator +// ----------------------------------------------------------------------------- + +// ODE right hand side function +static int f(sunrealtype t, N_Vector u, N_Vector f, void* user_data); + +// Spectral radius estimation routine +static int eig(sunrealtype t, N_Vector y, N_Vector fn, sunrealtype* lambdaR, + sunrealtype* lambdaI, void* user_data, N_Vector temp1, + N_Vector temp2, N_Vector temp3); + +// ----------------------------------------------------------------------------- +// Helper functions +// ----------------------------------------------------------------------------- + +// Setup the parallel decomposition +static int SetupDecomp(MPI_Comm comm_w, UserData* udata); + +// Perform neighbor exchange +static int PostRecv(UserData* udata); +static int SendData(N_Vector y, UserData* udata); +static int WaitRecv(UserData* udata); + +// ----------------------------------------------------------------------------- +// UserData and input functions +// ----------------------------------------------------------------------------- + +// Set the default values in the UserData structure +static int InitUserData(UserData* udata); + +// Free memory allocated within UserData +static int FreeUserData(UserData* udata); + +// Read the command line inputs and set UserData values +static int ReadInputs(int* argc, char*** argv, UserData* udata, bool outproc); + +// ----------------------------------------------------------------------------- +// Output and utility functions +// ----------------------------------------------------------------------------- + +// Compute the true solution +static int Solution(sunrealtype t, N_Vector u, UserData* udata); + +// Compute the solution error solution +static int SolutionError(sunrealtype t, N_Vector u, N_Vector e, UserData* udata); + +// Print the command line options +static void InputHelp(); + +// Print some UserData information +static int PrintUserData(UserData* udata); + +// Output solution and error +static int OpenOutput(UserData* udata); +static int WriteOutput(sunrealtype t, N_Vector u, UserData* udata); +static int CloseOutput(UserData* udata); + +// Print integration timing +static int OutputTiming(UserData* udata); + +// Check function return values +static int check_flag(void* flagvalue, const string funcname, int opt); + +// ----------------------------------------------------------------------------- +// Main Program +// ----------------------------------------------------------------------------- + +int main(int argc, char* argv[]) +{ + int flag; // reusable error-checking flag + UserData* udata = NULL; // user data structure + N_Vector u = NULL; // vector for storing solution + void* arkode_mem = NULL; // ARKODE memory structure + SUNAdaptController C = NULL; // timestep adaptivity controller + + // Timing variables + double t1 = 0.0; + double t2 = 0.0; + + // MPI variables + MPI_Comm comm_w = MPI_COMM_WORLD; // MPI communicator + int myid; // MPI process ID + + // Initialize MPI + flag = MPI_Init(&argc, &argv); + if (check_flag(&flag, "MPI_Init", 1)) { return 1; } + + flag = MPI_Comm_rank(comm_w, &myid); + if (check_flag(&flag, "MPI_Comm_rank", 1)) { return 1; } + + // Create the SUNDIALS context object for this simulation + SUNContext ctx; + flag = SUNContext_Create(comm_w, &ctx); + if (check_flag(&flag, "SUNContext_Create", 1)) { return 1; } + + // Set output process flag + bool outproc = (myid == 0); + + // ------------------------------------------ + // Setup UserData and parallel decomposition + // ------------------------------------------ + + // Allocate and initialize user data structure with default values. The + // defaults may be overwritten by command line inputs in ReadInputs below. + udata = new UserData; + flag = InitUserData(udata); + if (check_flag(&flag, "InitUserData", 1)) { return 1; } + + // Parse command line inputs + flag = ReadInputs(&argc, &argv, udata, outproc); + if (flag != 0) { return 1; } + + // Setup parallel decomposition + flag = SetupDecomp(comm_w, udata); + if (check_flag(&flag, "SetupDecomp", 1)) { return 1; } + + // Output problem setup/options + if (outproc) + { + flag = PrintUserData(udata); + if (check_flag(&flag, "PrintUserData", 1)) { return 1; } + } + + if (udata->diagnostics) + { + SUNLogger logger = NULL; + + flag = SUNContext_GetLogger(ctx, &logger); + if (check_flag(&flag, "SUNContext_GetLogger", 1)) { return 1; } + + flag = SUNLogger_SetInfoFilename(logger, "diagnostics.txt"); + if (check_flag(&flag, "SUNLogger_SetInfoFilename", 1)) { return 1; } + + flag = SUNLogger_SetDebugFilename(logger, "diagnostics.txt"); + if (check_flag(&flag, "SUNLogger_SetDebugFilename", 1)) { return 1; } + } + + // ------------------------ + // Create parallel vectors + // ------------------------ + + // Create vector for solution + u = N_VNew_Parallel(udata->comm_c, udata->nodes_loc, udata->nodes, ctx); + if (check_flag((void*)u, "N_VNew_Parallel", 0)) { return 1; } + + // Set initial condition + flag = Solution(ZERO, u, udata); + if (check_flag(&flag, "Solution", 1)) { return 1; } + + // Create vector for error + udata->e = N_VClone(u); + if (check_flag((void*)(udata->e), "N_VClone", 0)) { return 1; } + + // -------------- + // Setup ARKODE + // -------------- + + // Create integrator + arkode_mem = LSRKStepCreateSTS(f, ZERO, u, ctx); + if (check_flag((void*)arkode_mem, "LSRKStepCreateSTS", 0)) { return 1; } + + // Specify tolerances + flag = ARKodeSStolerances(arkode_mem, udata->rtol, udata->atol); + if (check_flag(&flag, "ARKodeSStolerances", 1)) { return 1; } + + // Attach user data + flag = ARKodeSetUserData(arkode_mem, (void*)udata); + if (check_flag(&flag, "ARKodeSetUserData", 1)) { return 1; } + + // Select LSRK method + flag = LSRKStepSetSTSMethod(arkode_mem, udata->method); + if (check_flag(&flag, "LSRKStepSetSTSMethod", 1)) { return 1; } + + // Select LSRK spectral radius function and options + flag = LSRKStepSetDomEigFn(arkode_mem, eig); + if (check_flag(&flag, "LSRKStepSetDomEigFn", 1)) { return 1; } + flag = LSRKStepSetDomEigFrequency(arkode_mem, udata->eigfrequency); + if (check_flag(&flag, "LSRKStepSetDomEigFrequency", 1)) { return 1; } + + // Set maximum number of stages per step + flag = LSRKStepSetMaxNumStages(arkode_mem, udata->stage_max_limit); + if (check_flag(&flag, "LSRKStepSetMaxNumStages", 1)) { return 1; } + + // Set spectral radius safety factor + flag = LSRKStepSetDomEigSafetyFactor(arkode_mem, udata->eigsafety); + if (check_flag(&flag, "LSRKStepSetDomEigSafetyFactor", 1)) { return 1; } + + // Set fixed step size or adaptivity method + if (udata->hfixed > ZERO) + { + flag = ARKodeSetFixedStep(arkode_mem, udata->hfixed); + if (check_flag(&flag, "ARKodeSetFixedStep", 1)) { return 1; } + } + else + { + switch (udata->controller) + { + case (ARK_ADAPT_PID): C = SUNAdaptController_PID(ctx); break; + case (ARK_ADAPT_PI): C = SUNAdaptController_PI(ctx); break; + case (ARK_ADAPT_I): C = SUNAdaptController_I(ctx); break; + case (ARK_ADAPT_EXP_GUS): C = SUNAdaptController_ExpGus(ctx); break; + case (ARK_ADAPT_IMP_GUS): C = SUNAdaptController_ImpGus(ctx); break; + case (ARK_ADAPT_IMEX_GUS): C = SUNAdaptController_ImExGus(ctx); break; + } + flag = ARKodeSetAdaptController(arkode_mem, C); + if (check_flag(&flag, "ARKodeSetAdaptController", 1)) { return 1; } + } + + // Set max steps between outputs + flag = ARKodeSetMaxNumSteps(arkode_mem, udata->maxsteps); + if (check_flag(&flag, "ARKodeSetMaxNumSteps", 1)) { return 1; } + + // Set stopping time + flag = ARKodeSetStopTime(arkode_mem, udata->tf); + if (check_flag(&flag, "ARKodeSetStopTime", 1)) { return 1; } + + // ----------------------- + // Loop over output times + // ----------------------- + + sunrealtype t = ZERO; + sunrealtype dTout = udata->tf / udata->nout; + sunrealtype tout = dTout; + + // Initial output + flag = OpenOutput(udata); + if (check_flag(&flag, "OpenOutput", 1)) { return 1; } + + flag = WriteOutput(t, u, udata); + if (check_flag(&flag, "WriteOutput", 1)) { return 1; } + + for (int iout = 0; iout < udata->nout; iout++) + { + // Start timer + t1 = MPI_Wtime(); + + // Evolve in time + flag = ARKodeEvolve(arkode_mem, tout, u, &t, ARK_NORMAL); + if (check_flag(&flag, "ARKodeEvolve", 1)) { break; } + + // Stop timer + t2 = MPI_Wtime(); + + // Update timer + udata->evolvetime += t2 - t1; + + // Output solution and error + flag = WriteOutput(t, u, udata); + if (check_flag(&flag, "WriteOutput", 1)) { return 1; } + + // Update output time + tout += dTout; + tout = (tout > udata->tf) ? udata->tf : tout; + } + + // Close output + flag = CloseOutput(udata); + if (check_flag(&flag, "CloseOutput", 1)) { return 1; } + + // -------------- + // Final outputs + // -------------- + + // Print final integrator stats + if (udata->output > 0 && outproc) + { + cout << "Final integrator statistics:" << endl; + flag = ARKodePrintAllStats(arkode_mem, stdout, SUN_OUTPUTFORMAT_TABLE); + if (check_flag(&flag, "ARKodePrintAllStats", 1)) { return 1; } + } + + if (udata->forcing) + { + // Output final error + flag = SolutionError(t, u, udata->e, udata); + if (check_flag(&flag, "SolutionError", 1)) { return 1; } + + sunrealtype maxerr = N_VMaxNorm(udata->e); + + if (outproc) + { + cout << scientific; + cout << setprecision(numeric_limits::digits10); + cout << " Max error = " << maxerr << endl; + } + } + + // Print timing + if (udata->timing) + { + flag = OutputTiming(udata); + if (check_flag(&flag, "OutputTiming", 1)) { return 1; } + } + + // -------------------- + // Clean up and return + // -------------------- + + ARKodeFree(&arkode_mem); // Free integrator memory + N_VDestroy(u); // Free vectors + FreeUserData(udata); // Free user data + delete udata; + (void)SUNAdaptController_Destroy(C); // Free timestep adaptivity controller + SUNContext_Free(&ctx); // Free context + flag = MPI_Finalize(); // Finalize MPI + return 0; +} + +// ----------------------------------------------------------------------------- +// Setup the parallel decomposition +// ----------------------------------------------------------------------------- + +static int SetupDecomp(MPI_Comm comm_w, UserData* udata) +{ + int flag; + + // Check that this has not been called before + if (udata->Erecv != NULL || udata->Wrecv != NULL || udata->Srecv != NULL || + udata->Nrecv != NULL) + { + cerr << "SetupDecomp error: parallel decomposition already set up" << endl; + return -1; + } + + // Get the number of processes + flag = MPI_Comm_size(comm_w, &(udata->nprocs_w)); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Comm_size = " << flag << endl; + return -1; + } + + // Check the processor grid + if ((udata->npx * udata->npy) != udata->nprocs_w) + { + cerr << "Error: npx * npy != nproc" << endl; + return -1; + } + + // Set up 2D Cartesian communicator + int dims[2]; + dims[0] = udata->npx; + dims[1] = udata->npy; + + int periods[2]; + periods[0] = 0; + periods[1] = 0; + + flag = MPI_Cart_create(comm_w, 2, dims, periods, 0, &(udata->comm_c)); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Cart_create = " << flag << endl; + return -1; + } + + // Get my rank in the new Cartesian communicator + flag = MPI_Comm_rank(udata->comm_c, &(udata->myid_c)); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Comm_rank = " << flag << endl; + return -1; + } + + // Get dimension of the Cartesian communicator and my coordinates + int coords[2]; + flag = MPI_Cart_get(udata->comm_c, 2, dims, periods, coords); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Cart_get = " << flag << endl; + return -1; + } + + // Determine local extents in x-direction + int idx = coords[0]; + sunindextype qx = udata->nx / dims[0]; + sunindextype rx = udata->nx % dims[0]; + + udata->is = qx * idx + (idx < rx ? idx : rx); + udata->ie = udata->is + qx - 1 + (idx < rx ? 1 : 0); + + // Sanity check + if (udata->ie > (udata->nx - 1)) + { + cerr << "Error ie > nx - 1" << endl; + return -1; + } + + // Determine local extents in y-direction + int idy = coords[1]; + sunindextype qy = udata->ny / dims[1]; + sunindextype ry = udata->ny % dims[1]; + + udata->js = qy * idy + (idy < ry ? idy : ry); + udata->je = udata->js + qy - 1 + (idy < ry ? 1 : 0); + + // Sanity check + if (udata->je > (udata->ny - 1)) + { + cerr << "Error je > ny - 1" << endl; + return -1; + } + + // Number of local nodes + udata->nx_loc = (udata->ie) - (udata->is) + 1; + udata->ny_loc = (udata->je) - (udata->js) + 1; + + // Initialize global and local vector lengths + udata->nodes = udata->nx * udata->ny; + udata->nodes_loc = udata->nx_loc * udata->ny_loc; + + // Determine if this proc has neighbors + udata->HaveNbrW = (udata->is != 0); + udata->HaveNbrE = (udata->ie != udata->nx - 1); + udata->HaveNbrS = (udata->js != 0); + udata->HaveNbrN = (udata->je != udata->ny - 1); + + // Allocate exchange buffers if necessary + if (udata->HaveNbrW) + { + udata->Wrecv = new sunrealtype[udata->ny_loc]; + udata->Wsend = new sunrealtype[udata->ny_loc]; + } + if (udata->HaveNbrE) + { + udata->Erecv = new sunrealtype[udata->ny_loc]; + udata->Esend = new sunrealtype[udata->ny_loc]; + } + if (udata->HaveNbrS) + { + udata->Srecv = new sunrealtype[udata->nx_loc]; + udata->Ssend = new sunrealtype[udata->nx_loc]; + } + if (udata->HaveNbrN) + { + udata->Nrecv = new sunrealtype[udata->nx_loc]; + udata->Nsend = new sunrealtype[udata->nx_loc]; + } + + // MPI neighborhood information + int nbcoords[2]; + + // West neighbor + if (udata->HaveNbrW) + { + nbcoords[0] = coords[0] - 1; + nbcoords[1] = coords[1]; + flag = MPI_Cart_rank(udata->comm_c, nbcoords, &(udata->ipW)); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Cart_rank = " << flag << endl; + return -1; + } + } + + // East neighbor + if (udata->HaveNbrE) + { + nbcoords[0] = coords[0] + 1; + nbcoords[1] = coords[1]; + flag = MPI_Cart_rank(udata->comm_c, nbcoords, &(udata->ipE)); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Cart_rank = " << flag << endl; + return -1; + } + } + + // South neighbor + if (udata->HaveNbrS) + { + nbcoords[0] = coords[0]; + nbcoords[1] = coords[1] - 1; + flag = MPI_Cart_rank(udata->comm_c, nbcoords, &(udata->ipS)); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Cart_rank = " << flag << endl; + return -1; + } + } + + // North neighbor + if (udata->HaveNbrN) + { + nbcoords[0] = coords[0]; + nbcoords[1] = coords[1] + 1; + flag = MPI_Cart_rank(udata->comm_c, nbcoords, &(udata->ipN)); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Cart_rank = " << flag << endl; + return -1; + } + } + + // Return success + return 0; +} + +// ----------------------------------------------------------------------------- +// Functions called by the integrator +// ----------------------------------------------------------------------------- + +// f routine to compute the ODE RHS function f(t,y). +static int f(sunrealtype t, N_Vector u, N_Vector f, void* user_data) +{ + int flag; + sunindextype i, j; + + // Start timer + double t1 = MPI_Wtime(); + + // Access problem data + UserData* udata = (UserData*)user_data; + + // Open exchange receives + flag = PostRecv(udata); + if (check_flag(&flag, "PostRecv", 1)) { return -1; } + + // Send exchange data + flag = SendData(u, udata); + if (check_flag(&flag, "SendData", 1)) { return -1; } + + // Shortcuts to local number of nodes + sunindextype nx_loc = udata->nx_loc; + sunindextype ny_loc = udata->ny_loc; + + // Determine iteration range excluding the overall domain boundary + sunindextype istart = (udata->HaveNbrW) ? 0 : 1; + sunindextype iend = (udata->HaveNbrE) ? nx_loc : nx_loc - 1; + sunindextype jstart = (udata->HaveNbrS) ? 0 : 1; + sunindextype jend = (udata->HaveNbrN) ? ny_loc : ny_loc - 1; + + // Constants for computing diffusion term + sunrealtype cx = udata->kx / (udata->dx * udata->dx); + sunrealtype cy = udata->ky / (udata->dy * udata->dy); + sunrealtype cc = -TWO * (cx + cy); + + // Access data arrays + sunrealtype* uarray = N_VGetArrayPointer(u); + if (check_flag((void*)uarray, "N_VGetArrayPointer", 0)) { return -1; } + + sunrealtype* farray = N_VGetArrayPointer(f); + if (check_flag((void*)farray, "N_VGetArrayPointer", 0)) { return -1; } + + // Initialize rhs vector to zero (handles boundary conditions) + N_VConst(ZERO, f); + + // Iterate over subdomain and compute rhs forcing term + if (udata->forcing) + { + sunrealtype x, y; + sunrealtype sin_sqr_x, sin_sqr_y; + sunrealtype cos_sqr_x, cos_sqr_y; + + sunrealtype bx = (udata->kx) * TWO * PI * PI; + sunrealtype by = (udata->ky) * TWO * PI * PI; + + sunrealtype sin_t_cos_t = sin(PI * t) * cos(PI * t); + sunrealtype cos_sqr_t = cos(PI * t) * cos(PI * t); + + for (j = jstart; j < jend; j++) + { + for (i = istart; i < iend; i++) + { + x = (udata->is + i) * udata->dx; + y = (udata->js + j) * udata->dy; + + sin_sqr_x = sin(PI * x) * sin(PI * x); + sin_sqr_y = sin(PI * y) * sin(PI * y); + + cos_sqr_x = cos(PI * x) * cos(PI * x); + cos_sqr_y = cos(PI * y) * cos(PI * y); + + farray[IDX(i, j, nx_loc)] = + -TWO * PI * sin_sqr_x * sin_sqr_y * sin_t_cos_t - + bx * (cos_sqr_x - sin_sqr_x) * sin_sqr_y * cos_sqr_t - + by * (cos_sqr_y - sin_sqr_y) * sin_sqr_x * cos_sqr_t; + } + } + } + + // Iterate over subdomain interior and add rhs diffusion term + for (j = 1; j < ny_loc - 1; j++) + { + for (i = 1; i < nx_loc - 1; i++) + { + farray[IDX(i, j, nx_loc)] += + cc * uarray[IDX(i, j, nx_loc)] + + cx * (uarray[IDX(i - 1, j, nx_loc)] + uarray[IDX(i + 1, j, nx_loc)]) + + cy * (uarray[IDX(i, j - 1, nx_loc)] + uarray[IDX(i, j + 1, nx_loc)]); + } + } + + // Wait for exchange receives + flag = WaitRecv(udata); + if (check_flag(&flag, "WaitRecv", 1)) { return -1; } + + // Iterate over subdomain boundaries and add rhs diffusion term + sunrealtype* Warray = udata->Wrecv; + sunrealtype* Earray = udata->Erecv; + sunrealtype* Sarray = udata->Srecv; + sunrealtype* Narray = udata->Nrecv; + + // West face (updates south-west and north-west corners if necessary) + if (udata->HaveNbrW) + { + i = 0; + if (udata->HaveNbrS) // South-West corner + { + j = 0; + farray[IDX(i, j, nx_loc)] += + cc * uarray[IDX(i, j, nx_loc)] + + cx * (Warray[j] + uarray[IDX(i + 1, j, nx_loc)]) + + cy * (Sarray[i] + uarray[IDX(i, j + 1, nx_loc)]); + } + + for (j = 1; j < ny_loc - 1; j++) + { + farray[IDX(i, j, nx_loc)] += + cc * uarray[IDX(i, j, nx_loc)] + + cx * (Warray[j] + uarray[IDX(i + 1, j, nx_loc)]) + + cy * (uarray[IDX(i, j - 1, nx_loc)] + uarray[IDX(i, j + 1, nx_loc)]); + } + + if (udata->HaveNbrN) // North-West corner + { + j = ny_loc - 1; + farray[IDX(i, j, nx_loc)] += + cc * uarray[IDX(i, j, nx_loc)] + + cx * (Warray[j] + uarray[IDX(i + 1, j, nx_loc)]) + + cy * (uarray[IDX(i, j - 1, nx_loc)] + Narray[i]); + } + } + + // East face (updates south-east and north-east corners if necessary) + if (udata->HaveNbrE) + { + i = nx_loc - 1; + if (udata->HaveNbrS) // South-East corner + { + j = 0; + farray[IDX(i, j, nx_loc)] += + cc * uarray[IDX(i, j, nx_loc)] + + cx * (uarray[IDX(i - 1, j, nx_loc)] + Earray[j]) + + cy * (Sarray[i] + uarray[IDX(i, j + 1, nx_loc)]); + } + + for (j = 1; j < ny_loc - 1; j++) + { + farray[IDX(i, j, nx_loc)] += + cc * uarray[IDX(i, j, nx_loc)] + + cx * (uarray[IDX(i - 1, j, nx_loc)] + Earray[j]) + + cy * (uarray[IDX(i, j - 1, nx_loc)] + uarray[IDX(i, j + 1, nx_loc)]); + } + + if (udata->HaveNbrN) // North-East corner + { + j = ny_loc - 1; + farray[IDX(i, j, nx_loc)] += + cc * uarray[IDX(i, j, nx_loc)] + + cx * (uarray[IDX(i - 1, j, nx_loc)] + Earray[j]) + + cy * (uarray[IDX(i, j - 1, nx_loc)] + Narray[i]); + } + } + + // South face (excludes corners) + if (udata->HaveNbrS) + { + j = 0; + for (i = 1; i < nx_loc - 1; i++) + { + farray[IDX(i, j, nx_loc)] += + cc * uarray[IDX(i, j, nx_loc)] + + cx * (uarray[IDX(i - 1, j, nx_loc)] + uarray[IDX(i + 1, j, nx_loc)]) + + cy * (Sarray[i] + uarray[IDX(i, j + 1, nx_loc)]); + } + } + + // North face (excludes corners) + if (udata->HaveNbrN) + { + j = udata->ny_loc - 1; + for (i = 1; i < nx_loc - 1; i++) + { + farray[IDX(i, j, nx_loc)] += + cc * uarray[IDX(i, j, nx_loc)] + + cx * (uarray[IDX(i - 1, j, nx_loc)] + uarray[IDX(i + 1, j, nx_loc)]) + + cy * (uarray[IDX(i, j - 1, nx_loc)] + Narray[i]); + } + } + + // Stop timer + double t2 = MPI_Wtime(); + + // Update timer + udata->rhstime += t2 - t1; + + // Return success + return 0; +} + +// ----------------------------------------------------------------------------- +// RHS helper functions +// ----------------------------------------------------------------------------- + +// Post exchange receives +static int PostRecv(UserData* udata) +{ + int flag; + + // Start timer + double t1 = MPI_Wtime(); + + // Open Irecv buffers + if (udata->HaveNbrW) + { + flag = MPI_Irecv(udata->Wrecv, (int)udata->ny_loc, MPI_SUNREALTYPE, + udata->ipW, MPI_ANY_TAG, udata->comm_c, &(udata->reqRW)); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Irecv = " << flag << endl; + return -1; + } + } + + if (udata->HaveNbrE) + { + flag = MPI_Irecv(udata->Erecv, (int)udata->ny_loc, MPI_SUNREALTYPE, + udata->ipE, MPI_ANY_TAG, udata->comm_c, &(udata->reqRE)); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Irecv = " << flag << endl; + return -1; + } + } + + if (udata->HaveNbrS) + { + flag = MPI_Irecv(udata->Srecv, (int)udata->nx_loc, MPI_SUNREALTYPE, + udata->ipS, MPI_ANY_TAG, udata->comm_c, &(udata->reqRS)); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Irecv = " << flag << endl; + return -1; + } + } + + if (udata->HaveNbrN) + { + flag = MPI_Irecv(udata->Nrecv, (int)udata->nx_loc, MPI_SUNREALTYPE, + udata->ipN, MPI_ANY_TAG, udata->comm_c, &(udata->reqRN)); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Irecv = " << flag << endl; + return -1; + } + } + + // Stop timer + double t2 = MPI_Wtime(); + + // Update timer + udata->exchangetime += t2 - t1; + + // Return success + return 0; +} + +// Send exchange data +static int SendData(N_Vector y, UserData* udata) +{ + int flag, i; + sunindextype ny_loc = udata->ny_loc; + sunindextype nx_loc = udata->nx_loc; + + // Start timer + double t1 = MPI_Wtime(); + + // Access data array + sunrealtype* Y = N_VGetArrayPointer(y); + if (check_flag((void*)Y, "N_VGetArrayPointer", 0)) { return -1; } + + // Send data + if (udata->HaveNbrW) + { + for (i = 0; i < ny_loc; i++) { udata->Wsend[i] = Y[IDX(0, i, nx_loc)]; } + flag = MPI_Isend(udata->Wsend, (int)udata->ny_loc, MPI_SUNREALTYPE, + udata->ipW, 0, udata->comm_c, &(udata->reqSW)); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Isend = " << flag << endl; + return -1; + } + } + + if (udata->HaveNbrE) + { + for (i = 0; i < ny_loc; i++) + { + udata->Esend[i] = Y[IDX(nx_loc - 1, i, nx_loc)]; + } + flag = MPI_Isend(udata->Esend, (int)udata->ny_loc, MPI_SUNREALTYPE, + udata->ipE, 1, udata->comm_c, &(udata->reqSE)); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Isend = " << flag << endl; + return -1; + } + } + + if (udata->HaveNbrS) + { + for (i = 0; i < nx_loc; i++) { udata->Ssend[i] = Y[IDX(i, 0, nx_loc)]; } + flag = MPI_Isend(udata->Ssend, (int)udata->nx_loc, MPI_SUNREALTYPE, + udata->ipS, 2, udata->comm_c, &(udata->reqSS)); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Isend = " << flag << endl; + return -1; + } + } + + if (udata->HaveNbrN) + { + for (i = 0; i < nx_loc; i++) + { + udata->Nsend[i] = Y[IDX(i, ny_loc - 1, nx_loc)]; + } + flag = MPI_Isend(udata->Nsend, (int)udata->nx_loc, MPI_SUNREALTYPE, + udata->ipN, 3, udata->comm_c, &(udata->reqSN)); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Isend = " << flag << endl; + return -1; + } + } + + // Stop timer + double t2 = MPI_Wtime(); + + // Update timer + udata->exchangetime += t2 - t1; + + // Return success + return 0; +} + +// Wait for exchange data +static int WaitRecv(UserData* udata) +{ + // Local variables + int flag; + MPI_Status stat; + + // Start timer + double t1 = MPI_Wtime(); + + // Wait for messages to finish + if (udata->HaveNbrW) + { + flag = MPI_Wait(&(udata->reqRW), &stat); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Wait = " << flag << endl; + return -1; + } + flag = MPI_Wait(&(udata->reqSW), &stat); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Wait = " << flag << endl; + return -1; + } + } + + if (udata->HaveNbrE) + { + flag = MPI_Wait(&(udata->reqRE), &stat); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Wait = " << flag << endl; + return -1; + } + flag = MPI_Wait(&(udata->reqSE), &stat); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Wait = " << flag << endl; + return -1; + } + } + + if (udata->HaveNbrS) + { + flag = MPI_Wait(&(udata->reqRS), &stat); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Wait = " << flag << endl; + return -1; + } + flag = MPI_Wait(&(udata->reqSS), &stat); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Wait = " << flag << endl; + return -1; + } + } + + if (udata->HaveNbrN) + { + flag = MPI_Wait(&(udata->reqRN), &stat); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Wait = " << flag << endl; + return -1; + } + flag = MPI_Wait(&(udata->reqSN), &stat); + if (flag != MPI_SUCCESS) + { + cerr << "Error in MPI_Wait = " << flag << endl; + return -1; + } + } + + // Stop timer + double t2 = MPI_Wtime(); + + // Update timer + udata->exchangetime += t2 - t1; + + // Return success + return 0; +} + +// Spectral radius estimation routine +static int eig(sunrealtype t, N_Vector y, N_Vector fn, sunrealtype* lambdaR, + sunrealtype* lambdaI, void* user_data, N_Vector temp1, + N_Vector temp2, N_Vector temp3) +{ + // Access problem data + UserData* udata = (UserData*)user_data; + + // Fill in spectral radius value + *lambdaR = -SUN_RCONST(8.0) * max(udata->kx / udata->dx / udata->dx, + udata->ky / udata->dy / udata->dy); + *lambdaI = SUN_RCONST(0.0); + + // return with success + return 0; +} + +// ----------------------------------------------------------------------------- +// UserData and input functions +// ----------------------------------------------------------------------------- + +// Initialize memory allocated within Userdata +static int InitUserData(UserData* udata) +{ + // Diffusion coefficient + udata->kx = SUN_RCONST(10.0); + udata->ky = SUN_RCONST(10.0); + + // Enable forcing + udata->forcing = true; + + // Final time + udata->tf = ONE; + + // Upper bounds in x and y directions + udata->xu = ONE; + udata->yu = ONE; + + // Global number of nodes in the x and y directions + udata->nx = 64; + udata->ny = 64; + udata->nodes = udata->nx * udata->ny; + + // Mesh spacing in the x and y directions + udata->dx = udata->xu / (udata->nx - 1); + udata->dy = udata->yu / (udata->ny - 1); + + // Locals number of nodes in the x and y directions (set in SetupDecomp) + udata->nx_loc = 0; + udata->ny_loc = 0; + udata->nodes_loc = 0; + + // Global indices of this subdomain (set in SetupDecomp) + udata->is = 0; + udata->ie = 0; + udata->js = 0; + udata->je = 0; + + // MPI variables (set in SetupDecomp) + udata->comm_c = MPI_COMM_NULL; + + udata->nprocs_w = 1; + udata->npx = 1; + udata->npy = 1; + + udata->myid_c = 0; + + // Flags denoting neighbors (set in SetupDecomp) + udata->HaveNbrW = true; + udata->HaveNbrE = true; + udata->HaveNbrS = true; + udata->HaveNbrN = true; + + // Exchange receive buffers (allocated in SetupDecomp) + udata->Erecv = NULL; + udata->Wrecv = NULL; + udata->Nrecv = NULL; + udata->Srecv = NULL; + + // Exchange send buffers (allocated in SetupDecomp) + udata->Esend = NULL; + udata->Wsend = NULL; + udata->Nsend = NULL; + udata->Ssend = NULL; + + // Neighbors IDs (set in SetupDecomp) + udata->ipW = -1; + udata->ipE = -1; + udata->ipS = -1; + udata->ipN = -1; + + // Integrator settings + udata->rtol = SUN_RCONST(1.e-5); // relative tolerance + udata->atol = SUN_RCONST(1.e-10); // absolute tolerance + udata->hfixed = ZERO; // using adaptive step sizes + udata->controller = 0; // PID controller + udata->maxsteps = 0; // use default + udata->diagnostics = false; // output diagnostics + + // LSRKStep options + udata->method = ARKODE_LSRK_RKC_2; // RKC + udata->eigfrequency = 25; // update eigenvalue at least every 20 steps + udata->stage_max_limit = 1000; // allow up to 1000 stages/step + udata->eigsafety = SUN_RCONST(1.01); // 1% safety factor + + // Output variables + udata->output = 1; // 0 = no output, 1 = stats output, 2 = output to disk + udata->nout = 20; // Number of output times + udata->e = NULL; + + // Timing variables + udata->timing = false; + udata->evolvetime = 0.0; + udata->rhstime = 0.0; + udata->exchangetime = 0.0; + + // Return success + return 0; +} + +// Free memory allocated within Userdata +static int FreeUserData(UserData* udata) +{ + // Free exchange buffers + if (udata->Wrecv != NULL) { delete[] udata->Wrecv; } + if (udata->Wsend != NULL) { delete[] udata->Wsend; } + if (udata->Erecv != NULL) { delete[] udata->Erecv; } + if (udata->Esend != NULL) { delete[] udata->Esend; } + if (udata->Srecv != NULL) { delete[] udata->Srecv; } + if (udata->Ssend != NULL) { delete[] udata->Ssend; } + if (udata->Nrecv != NULL) { delete[] udata->Nrecv; } + if (udata->Nsend != NULL) { delete[] udata->Nsend; } + + // Free MPI Cartesian communicator + if (udata->comm_c != MPI_COMM_NULL) { MPI_Comm_free(&(udata->comm_c)); } + + // Free error vector + if (udata->e) + { + N_VDestroy(udata->e); + udata->e = NULL; + } + + // Return success + return 0; +} + +// Read command line inputs +static int ReadInputs(int* argc, char*** argv, UserData* udata, bool outproc) +{ + // Check for input args + int arg_idx = 1; + + while (arg_idx < (*argc)) + { + string arg = (*argv)[arg_idx++]; + + // Mesh points + if (arg == "--mesh") + { + udata->nx = stoi((*argv)[arg_idx++]); + udata->ny = stoi((*argv)[arg_idx++]); + } + // MPI processes + else if (arg == "--np") + { + udata->npx = stoi((*argv)[arg_idx++]); + udata->npy = stoi((*argv)[arg_idx++]); + } + // Domain upper bounds + else if (arg == "--domain") + { + udata->xu = stoi((*argv)[arg_idx++]); + udata->yu = stoi((*argv)[arg_idx++]); + } + // Diffusion parameters + else if (arg == "--k") + { + udata->kx = stod((*argv)[arg_idx++]); + udata->ky = stod((*argv)[arg_idx++]); + } + // Disable forcing + else if (arg == "--noforcing") { udata->forcing = false; } + // Temporal domain settings + else if (arg == "--tf") { udata->tf = stod((*argv)[arg_idx++]); } + // Integrator settings + else if (arg == "--rtol") { udata->rtol = stod((*argv)[arg_idx++]); } + else if (arg == "--atol") { udata->atol = stod((*argv)[arg_idx++]); } + else if (arg == "--fixedstep") { udata->hfixed = stod((*argv)[arg_idx++]); } + else if (arg == "--controller") + { + udata->controller = stoi((*argv)[arg_idx++]); + } + else if (arg == "--diagnostics") { udata->diagnostics = true; } + else if (arg == "--method") + { + udata->method = (ARKODE_LSRKMethodType)stoi((*argv)[arg_idx++]); + } + else if (arg == "--eigfrequency") + { + udata->eigfrequency = stoi((*argv)[arg_idx++]); + } + else if (arg == "--stage_max_limit") + { + udata->stage_max_limit = stoi((*argv)[arg_idx++]); + } + else if (arg == "--eigsafety") + { + udata->eigsafety = stod((*argv)[arg_idx++]); + } + // Output settings + else if (arg == "--output") { udata->output = stoi((*argv)[arg_idx++]); } + else if (arg == "--nout") { udata->nout = stoi((*argv)[arg_idx++]); } + else if (arg == "--maxsteps") + { + udata->maxsteps = stoi((*argv)[arg_idx++]); + } + else if (arg == "--timing") { udata->timing = true; } + // Help + else if (arg == "--help") + { + if (outproc) { InputHelp(); } + return -1; + } + // Unknown input + else + { + if (outproc) + { + cerr << "ERROR: Invalid input " << arg << endl; + InputHelp(); + } + return -1; + } + } + + // Recompute total number of nodes + udata->nodes = udata->nx * udata->ny; + + // Recompute x and y mesh spacing + udata->dx = (udata->xu) / (udata->nx - 1); + udata->dy = (udata->yu) / (udata->ny - 1); + + // Return success + return 0; +} + +// ----------------------------------------------------------------------------- +// Output and utility functions +// ----------------------------------------------------------------------------- + +// Compute the exact solution +static int Solution(sunrealtype t, N_Vector u, UserData* udata) +{ + sunrealtype x, y; + sunrealtype cos_sqr_t; + sunrealtype sin_sqr_x, sin_sqr_y; + + // Constants for computing solution + cos_sqr_t = cos(PI * t) * cos(PI * t); + + // Initialize u to zero (handles boundary conditions) + N_VConst(ZERO, u); + + // Iterative over domain interior + sunindextype istart = (udata->HaveNbrW) ? 0 : 1; + sunindextype iend = (udata->HaveNbrE) ? udata->nx_loc : udata->nx_loc - 1; + + sunindextype jstart = (udata->HaveNbrS) ? 0 : 1; + sunindextype jend = (udata->HaveNbrN) ? udata->ny_loc : udata->ny_loc - 1; + + sunrealtype* uarray = N_VGetArrayPointer(u); + if (check_flag((void*)uarray, "N_VGetArrayPointer", 0)) { return -1; } + + for (sunindextype j = jstart; j < jend; j++) + { + for (sunindextype i = istart; i < iend; i++) + { + x = (udata->is + i) * udata->dx; + y = (udata->js + j) * udata->dy; + + sin_sqr_x = sin(PI * x) * sin(PI * x); + sin_sqr_y = sin(PI * y) * sin(PI * y); + + uarray[IDX(i, j, udata->nx_loc)] = sin_sqr_x * sin_sqr_y * cos_sqr_t; + } + } + + return 0; +} + +// Compute the solution error +static int SolutionError(sunrealtype t, N_Vector u, N_Vector e, UserData* udata) +{ + // Compute true solution + int flag = Solution(t, e, udata); + if (flag != 0) { return -1; } + + // Compute absolute error + N_VLinearSum(ONE, u, -ONE, e, e); + N_VAbs(e, e); + + return 0; +} + +// Print command line options +static void InputHelp() +{ + cout << endl; + cout << "Command line options:" << endl; + cout << " --mesh : mesh points in the x and y directions" + << endl; + cout << " --np : number of MPI processes in the x and y " + "directions" + << endl; + cout + << " --domain : domain upper bound in the x and y direction" + << endl; + cout << " --k : diffusion coefficients" << endl; + cout << " --noforcing : disable forcing term" << endl; + cout << " --tf