• CVODE入门


    1、安装

    cvode是sundials软件包的一部分。在windows+visualstudio下可以用vcpkg安装使用。

    git clone https://github.com/microsoft/vcpkg

    然后运行目录中的Bootstrap_vcpkg.bat。

    然后进入vcpkg目录中,vcpkg install sundials:x64-windows,这样安装64位dll。

    然后管理员身份运行cmd,vcpkg integrate install。

    2 使用

    新建项目后,在项目属性中可以看到vcpkg选项,证明安装好了。

    3 示例程序

    程序的主要步骤

    1、初始化多线程环境(可选)
    2、创建sundials上下文对象
    SUNContext_Create()
    3、设置问题的大小???
    4、设置初值向量
    如果已有数据存储在ydata中,可以调用y0 = N_VMake_***(..., ydata)
    否则,调用N_VNew_***(...)创建新的向量
    然后用ydata = N_VGetArrayPointer(y0)设置单独数据
    5、创建CVODE对象
    CVodeCreate()返回一个内存结构的指针
    6、初始化CVODE求解器
    CVodeInit(),定义方程组信息,分配内部的内存,初始化。
    7、设置积分误差
    CVodeSStolerances() or CVodeSVtolerances() 设置相对误差或者绝对误差
    8、创建矩阵对象

    matrix_var = SUNDenseMatrix(x, x, context_var);

    9、创建求解器

    ls = SUNxxx_xxx(y, matrix_var, context_var)

    10、把矩阵加入求解器

    CVodeSetLinearSolver(mem, ls, matrix_var);

    11、设置用户定义的雅克比矩阵

    CVodeSetJacFn(mem, Jac), jac是用户定义函数
    13、时间步长增加
    ier = CVode(cvode_mem, tout, yout, tret itask)
    14、释放解向量内存
    15、释放求解器内存
    CVodeFree()
    16、释放线性求解器和矩阵的内存
    SUNLinSolFree()
    SUNMatDestroy()
    17、释放SUNContext对象
     

    其他

    Ith和IJth是自定义函数,方便函数形式符合数学公式的形式,即下标序号从1开始,而不是c语言的从0开始。
    函数f是ode表达式的直接转写,怎么写详细见https://sundials.readthedocs.io/en/latest/cvode/Usage/index.html#user-supplied-functions。函数g定义了两个数学函数g0和g1,用于求特定值时的参数(比如y1=1,此时求其他的y,可选)。Jac为Jacobian矩阵,该矩阵初始值为0,所以可以只设置非0值。

    CVodePrintAllStats输出所有统计信息

    1. /* -----------------------------------------------------------------
    2. * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh and
    3. * Radu Serban @ LLNL
    4. * -----------------------------------------------------------------
    5. * SUNDIALS Copyright Start
    6. * Copyright (c) 2002-2022, Lawrence Livermore National Security
    7. * and Southern Methodist University.
    8. * All rights reserved.
    9. *
    10. * See the top-level LICENSE and NOTICE files for details.
    11. *
    12. * SPDX-License-Identifier: BSD-3-Clause
    13. * SUNDIALS Copyright End
    14. * -----------------------------------------------------------------
    15. * Example problem:
    16. *
    17. * The following is a simple example problem, with the coding
    18. * needed for its solution by CVODE. The problem is from
    19. * chemical kinetics, and consists of the following three rate
    20. * equations:
    21. * dy1/dt = -.04*y1 + 1.e4*y2*y3
    22. * dy2/dt = .04*y1 - 1.e4*y2*y3 - 3.e7*(y2)^2
    23. * dy3/dt = 3.e7*(y2)^2
    24. * on the interval from t = 0.0 to t = 4.e10, with initial
    25. * conditions: y1 = 1.0, y2 = y3 = 0. The problem is stiff.
    26. * While integrating the system, we also use the rootfinding
    27. * feature to find the points at which y1 = 1e-4 or at which
    28. * y3 = 0.01. This program solves the problem with the BDF method,
    29. * Newton iteration with the dense linear solver, and a
    30. * user-supplied Jacobian routine.
    31. * It uses a scalar relative tolerance and a vector absolute
    32. * tolerance. Output is printed in decades from t = .4 to t = 4.e10.
    33. * Run statistics (optional outputs) are printed at the end.
    34. * -----------------------------------------------------------------*/
    35. #include
    36. //#include
    37. #include /* prototypes for CVODE fcts., consts. */
    38. #include /* access to serial N_Vector */
    39. #include /* access to dense SUNMatrix */
    40. #include /* access to dense SUNLinearSolver */
    41. #if defined(SUNDIALS_EXTENDED_PRECISION)
    42. #define GSYM "Lg"
    43. #define ESYM "Le"
    44. #define FSYM "Lf"
    45. #else
    46. #define GSYM "g"
    47. #define ESYM "e"
    48. #define FSYM "f"
    49. #endif
    50. /* User-defined vector and matrix accessor macros: Ith, IJth */
    51. /* These macros are defined in order to write code which exactly matches
    52. the mathematical problem description given above.
    53. Ith(v,i) references the ith component of the vector v, where i is in
    54. the range [1..NEQ] and NEQ is defined below. The Ith macro is defined
    55. using the N_VIth macro in nvector.h. N_VIth numbers the components of
    56. a vector starting from 0.
    57. IJth(A,i,j) references the (i,j)th element of the dense matrix A, where
    58. i and j are in the range [1..NEQ]. The IJth macro is defined using the
    59. SM_ELEMENT_D macro. SM_ELEMENT_D numbers rows and columns of
    60. a dense matrix starting from 0. */
    61. #define Ith(v,i) NV_Ith_S(v,i-1) /* i-th vector component i=1..NEQ */
    62. #define IJth(A,i,j) SM_ELEMENT_D(A,i-1,j-1) /* (i,j)-th matrix component i,j=1..NEQ */
    63. /* Problem Constants */
    64. #define NEQ 3 /* number of equations */
    65. #define Y1 RCONST(1.0) /* initial y components */
    66. #define Y2 RCONST(0.0)
    67. #define Y3 RCONST(0.0)
    68. #define RTOL RCONST(1.0e-4) /* scalar relative tolerance */
    69. #define ATOL1 RCONST(1.0e-8) /* vector absolute tolerance components */
    70. #define ATOL2 RCONST(1.0e-14)
    71. #define ATOL3 RCONST(1.0e-6)
    72. #define T0 RCONST(0.0) /* initial time */
    73. #define T1 RCONST(0.4) /* first output time */
    74. #define TMULT RCONST(10.0) /* output time factor */
    75. #define NOUT 12 /* number of output times */
    76. #define ZERO RCONST(0.0)
    77. /* Functions Called by the Solver */
    78. static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data);
    79. static int g(realtype t, N_Vector y, realtype *gout, void *user_data);
    80. static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
    81. void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3);
    82. /* Private functions to output results */
    83. static void PrintOutput(realtype t, realtype y1, realtype y2, realtype y3);
    84. static void PrintRootInfo(int root_f1, int root_f2);
    85. /* Private function to check function return values */
    86. static int check_retval(void *returnvalue, const char *funcname, int opt);
    87. /* Private function to check computed solution */
    88. static int check_ans(N_Vector y, realtype t, realtype rtol, N_Vector atol);
    89. /*
    90. *-------------------------------
    91. * Main Program
    92. *-------------------------------
    93. */
    94. int main()
    95. {
    96. SUNContext sunctx;
    97. realtype t, tout;
    98. N_Vector y;
    99. N_Vector abstol;
    100. SUNMatrix A;
    101. SUNLinearSolver LS;
    102. void *cvode_mem;
    103. int retval, iout;
    104. int retvalr;
    105. int rootsfound[2];
    106. FILE* FID;
    107. y = NULL;
    108. abstol = NULL;
    109. A = NULL;
    110. LS = NULL;
    111. cvode_mem = NULL;
    112. /* Create the SUNDIALS context */
    113. retval = SUNContext_Create(NULL, &sunctx);
    114. if (check_retval(&retval, "SUNContext_Create", 1)) return(1);
    115. /* Initial conditions */
    116. y = N_VNew_Serial(NEQ, sunctx);
    117. if (check_retval((void *)y, "N_VNew_Serial", 0)) return(1);
    118. /* Initialize y */
    119. Ith(y,1) = Y1;
    120. Ith(y,2) = Y2;
    121. Ith(y,3) = Y3;
    122. /* Set the vector absolute tolerance */
    123. abstol = N_VNew_Serial(NEQ, sunctx);
    124. if (check_retval((void *)abstol, "N_VNew_Serial", 0)) return(1);
    125. Ith(abstol,1) = ATOL1;
    126. Ith(abstol,2) = ATOL2;
    127. Ith(abstol,3) = ATOL3;
    128. /* Call CVodeCreate to create the solver memory and specify the
    129. * Backward Differentiation Formula */
    130. cvode_mem = CVodeCreate(CV_BDF, sunctx);
    131. if (check_retval((void *)cvode_mem, "CVodeCreate", 0)) return(1);
    132. /* Call CVodeInit to initialize the integrator memory and specify the
    133. * user's right hand side function in y'=f(t,y), the initial time T0, and
    134. * the initial dependent variable vector y. */
    135. retval = CVodeInit(cvode_mem, f, T0, y);
    136. if (check_retval(&retval, "CVodeInit", 1)) return(1);
    137. /* Call CVodeSVtolerances to specify the scalar relative tolerance
    138. * and vector absolute tolerances */
    139. retval = CVodeSVtolerances(cvode_mem, RTOL, abstol);
    140. if (check_retval(&retval, "CVodeSVtolerances", 1)) return(1);
    141. /* Call CVodeRootInit to specify the root function g with 2 components */
    142. //retval = CVodeRootInit(cvode_mem, 2, g);
    143. //if (check_retval(&retval, "CVodeRootInit", 1)) return(1);
    144. /* Create dense SUNMatrix for use in linear solves */
    145. A = SUNDenseMatrix(3, 3, sunctx);
    146. if (check_retval((void *)A, "SUNDenseMatrix", 0)) return(1);
    147. /* Create dense SUNLinearSolver object for use by CVode */
    148. LS = SUNLinSol_Dense(y, A, sunctx);
    149. if (check_retval((void *)LS, "SUNLinSol_Dense", 0)) return(1);
    150. /* Attach the matrix and linear solver */
    151. retval = CVodeSetLinearSolver(cvode_mem, LS, A);
    152. if (check_retval(&retval, "CVodeSetLinearSolver", 1)) return(1);
    153. /* Set the user-supplied Jacobian routine Jac */
    154. retval = CVodeSetJacFn(cvode_mem, Jac);
    155. if (check_retval(&retval, "CVodeSetJacFn", 1)) return(1);
    156. /* In loop, call CVode, print results, and test for error.
    157. Break out of loop when NOUT preset output times have been reached. */
    158. printf(" \n3-species kinetics problem\n\n");
    159. FILE* vstream;
    160. /* Open file for printing statistics */
    161. //FID = fopen_s(vstream, "cvRoberts_dns_stats.csv", "w");
    162. errno_t ee = fopen_s(&vstream, "cvRoberts_dns_stats.csv", "w");
    163. iout = 0; tout = T1;
    164. while(1) {
    165. retval = CVode(cvode_mem, tout, y, &t, CV_NORMAL);
    166. PrintOutput(t, Ith(y,1), Ith(y,2), Ith(y,3));
    167. if (retval == CV_ROOT_RETURN) {
    168. retvalr = CVodeGetRootInfo(cvode_mem, rootsfound);
    169. if (check_retval(&retvalr, "CVodeGetRootInfo", 1)) return(1);
    170. PrintRootInfo(rootsfound[0],rootsfound[1]);
    171. }
    172. if (check_retval(&retval, "CVode", 1)) break;
    173. if (retval == CV_SUCCESS) {
    174. iout++;
    175. tout *= TMULT;
    176. }
    177. retval = CVodePrintAllStats(cvode_mem, vstream, SUN_OUTPUTFORMAT_CSV);
    178. if (iout == NOUT) break;
    179. }
    180. fclose(vstream);
    181. /* Print final statistics to the screen */
    182. printf("\nFinal Statistics:\n");
    183. retval = CVodePrintAllStats(cvode_mem, stdout, SUN_OUTPUTFORMAT_TABLE);
    184. /* check the solution error */
    185. retval = check_ans(y, t, RTOL, abstol);
    186. /* Free memory */
    187. N_VDestroy(y); /* Free y vector */
    188. N_VDestroy(abstol); /* Free abstol vector */
    189. CVodeFree(&cvode_mem); /* Free CVODE memory */
    190. SUNLinSolFree(LS); /* Free the linear solver memory */
    191. SUNMatDestroy(A); /* Free the matrix memory */
    192. SUNContext_Free(&sunctx); /* Free the SUNDIALS context */
    193. return(retval);
    194. }
    195. /*
    196. *-------------------------------
    197. * Functions called by the solver
    198. *-------------------------------
    199. */
    200. /*
    201. * f routine. Compute function f(t,y).
    202. */
    203. static int f(realtype t, N_Vector y, N_Vector ydot, void *user_data)
    204. {
    205. realtype y1, y2, y3, yd1, yd3;
    206. y1 = Ith(y,1); y2 = Ith(y,2); y3 = Ith(y,3);
    207. yd1 = Ith(ydot,1) = RCONST(-0.04)*y1 + RCONST(1.0e4)*y2*y3;
    208. yd3 = Ith(ydot,3) = RCONST(3.0e7)*y2*y2;
    209. Ith(ydot,2) = -yd1 - yd3;
    210. return(0);
    211. }
    212. /*
    213. * g routine. Compute functions g_i(t,y) for i = 0,1.
    214. */
    215. static int g(realtype t, N_Vector y, realtype *gout, void *user_data)
    216. {
    217. realtype y1, y3;
    218. y1 = Ith(y,1); y3 = Ith(y,3);
    219. gout[0] = y1 - RCONST(0.0001);
    220. gout[1] = y3 - RCONST(0.01);
    221. return(0);
    222. }
    223. /*
    224. * Jacobian routine. Compute J(t,y) = df/dy. *
    225. */
    226. static int Jac(realtype t, N_Vector y, N_Vector fy, SUNMatrix J,
    227. void *user_data, N_Vector tmp1, N_Vector tmp2, N_Vector tmp3)
    228. {
    229. realtype y2, y3;
    230. y2 = Ith(y,2); y3 = Ith(y,3);
    231. IJth(J,1,1) = RCONST(-0.04);
    232. IJth(J,1,2) = RCONST(1.0e4)*y3;
    233. IJth(J,1,3) = RCONST(1.0e4)*y2;
    234. IJth(J,2,1) = RCONST(0.04);
    235. IJth(J,2,2) = RCONST(-1.0e4)*y3-RCONST(6.0e7)*y2;
    236. IJth(J,2,3) = RCONST(-1.0e4)*y2;
    237. IJth(J,3,1) = ZERO;
    238. IJth(J,3,2) = RCONST(6.0e7)*y2;
    239. IJth(J,3,3) = ZERO;
    240. return(0);
    241. }
    242. /*
    243. *-------------------------------
    244. * Private helper functions
    245. *-------------------------------
    246. */
    247. static void PrintOutput(realtype t, realtype y1, realtype y2, realtype y3)
    248. {
    249. #if defined(SUNDIALS_EXTENDED_PRECISION)
    250. printf("At t = %0.4Le y =%14.6Le %14.6Le %14.6Le\n", t, y1, y2, y3);
    251. #elif defined(SUNDIALS_DOUBLE_PRECISION)
    252. printf("At t = %0.4e y =%14.6e %14.6e %14.6e\n", t, y1, y2, y3);
    253. #else
    254. printf("At t = %0.4e y =%14.6e %14.6e %14.6e\n", t, y1, y2, y3);
    255. #endif
    256. return;
    257. }
    258. static void PrintRootInfo(int root_f1, int root_f2)
    259. {
    260. printf(" rootsfound[] = %3d %3d\n", root_f1, root_f2);
    261. return;
    262. }
    263. /*
    264. * Check function return value...
    265. * opt == 0 means SUNDIALS function allocates memory so check if
    266. * returned NULL pointer
    267. * opt == 1 means SUNDIALS function returns an integer value so check if
    268. * retval < 0
    269. * opt == 2 means function allocates memory so check if returned
    270. * NULL pointer
    271. */
    272. static int check_retval(void *returnvalue, const char *funcname, int opt)
    273. {
    274. int *retval;
    275. /* Check if SUNDIALS function returned NULL pointer - no memory allocated */
    276. if (opt == 0 && returnvalue == NULL) {
    277. fprintf(stderr, "\nSUNDIALS_ERROR: %s() failed - returned NULL pointer\n\n",
    278. funcname);
    279. return(1); }
    280. /* Check if retval < 0 */
    281. else if (opt == 1) {
    282. retval = (int *) returnvalue;
    283. if (*retval < 0) {
    284. fprintf(stderr, "\nSUNDIALS_ERROR: %s() failed with retval = %d\n\n",
    285. funcname, *retval);
    286. return(1); }}
    287. /* Check if function returned NULL pointer - no memory allocated */
    288. else if (opt == 2 && returnvalue == NULL) {
    289. fprintf(stderr, "\nMEMORY_ERROR: %s() failed - returned NULL pointer\n\n",
    290. funcname);
    291. return(1); }
    292. return(0);
    293. }
    294. /* compare the solution at the final time 4e10s to a reference solution computed
    295. using a relative tolerance of 1e-8 and absoltue tolerance of 1e-14 */
    296. static int check_ans(N_Vector y, realtype t, realtype rtol, N_Vector atol)
    297. {
    298. int passfail=0; /* answer pass (0) or fail (1) flag */
    299. N_Vector ref; /* reference solution vector */
    300. N_Vector ewt; /* error weight vector */
    301. realtype err; /* wrms error */
    302. realtype ONE=RCONST(1.0);
    303. /* create reference solution and error weight vectors */
    304. ref = N_VClone(y);
    305. ewt = N_VClone(y);
    306. /* set the reference solution data */
    307. NV_Ith_S(ref,0) = RCONST(5.2083495894337328e-08);
    308. NV_Ith_S(ref,1) = RCONST(2.0833399429795671e-13);
    309. NV_Ith_S(ref,2) = RCONST(9.9999994791629776e-01);
    310. /* compute the error weight vector, loosen atol */
    311. N_VAbs(ref, ewt);
    312. N_VLinearSum(rtol, ewt, RCONST(10.0), atol, ewt);
    313. if (N_VMin(ewt) <= ZERO) {
    314. fprintf(stderr, "\nSUNDIALS_ERROR: check_ans failed - ewt <= 0\n\n");
    315. return(-1);
    316. }
    317. N_VInv(ewt, ewt);
    318. /* compute the solution error */
    319. N_VLinearSum(ONE, y, -ONE, ref, ref);
    320. err = N_VWrmsNorm(ref, ewt);
    321. /* is the solution within the tolerances? */
    322. passfail = (err < ONE) ? 0 : 1;
    323. if (passfail) {
    324. fprintf(stdout, "\nSUNDIALS_WARNING: check_ans error=%"GSYM"\n\n", err);
    325. }
    326. /* Free vectors */
    327. N_VDestroy(ref);
    328. N_VDestroy(ewt);
    329. return(passfail);
    330. }

  • 相关阅读:
    一键自动化博客发布工具,用过的人都说好(腾讯云篇)
    2023-09-14 mysql-Item_subselect-分析
    【C++进阶】:哈希
    数据治理:误区梳理篇
    SpringBoot基础入门
    接口自动化测试小结
    Qt扫盲-QPen 理论使用总结
    基于flowable的upp(统一流程平台)运行性能优化(2)
    Spread.NET 16.0[Winform|WPF|ASP.NET]
    某电商网站的数据库设计(3)
  • 原文地址:https://blog.csdn.net/novanova2009/article/details/126798087