Integrate in time with PETSc.
This function integrates the semi-discrete ODE (obtained from discretizing the PDE in space) using the time-integration module of PETSc (https://petsc.org/release/docs/manualpages/TS/index.html). The time-integration context is set up using the parameters specified in the input file. However, they can also be specified using PETSc's command line inputs.
See PETSc's documentation and examples for more details on how to use its TS module. All functions and data types whose names start with Vec, Mat, PC, KSP, SNES, and TS are PETSc functions - refer to the PETSc documentation (usually googling with the function name shows the man page for that function on PETSc's website).
61 MatFDColoring fdcoloring;
74 if(!rank) printf(
"Setting up PETSc time integration... \n");
80 context.
nproc = nproc;
83 context.
nsims = nsims;
103 if (!rank) printf(
"Setting up libROM interface.\n");
127 VecCreate(MPI_COMM_WORLD,&Y);
128 VecSetSizes(Y,context.
ndofs,PETSC_DECIDE);
132 for (
int ns = 0; ns < nsims; ns++) {
144 TSCreate(MPI_COMM_WORLD,&ts);
145 TSSetMaxSteps(ts,sim[0].solver.n_iter);
146 TSSetMaxTime(ts,sim[0].solver.dt*sim[0].solver.n_iter);
147 TSSetTimeStep(ts,sim[0].solver.dt);
148 TSSetTime(ts,context.
waqt);
149 TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP);
150 TSSetType(ts,TSBEULER);
154 TSAdaptType adapt_type = TSADAPTNONE;
155 TSGetAdapt(ts,&adapt);
156 TSAdaptSetType(adapt,adapt_type);
159 TSSetFromOptions(ts);
162 DMShellCreate(MPI_COMM_WORLD, &dm);
163 DMShellSetGlobalVector(dm, Y);
167 TSAdaptGetType(adapt,&adapt_type);
168 if (strcmp(adapt_type, TSADAPTNONE)) {
169 if (!rank) printf(
"Warning: libROM interface not yet implemented for adaptive timestepping.\n");
174 TSGetType(ts,&time_scheme);
175 TSGetProblemType(ts,&ptype);
177 if (!strcmp(time_scheme,TSARKIMEX)) {
189 SNESGetType(snes,&snestype);
198 PetscOptionsGetBool(
nullptr,
nullptr,
204 PetscOptionsGetString(
nullptr,
207 precon_mat_type_c_st,
218 MatCreateShell( MPI_COMM_WORLD,
225 if ((!strcmp(snestype,SNESKSPONLY)) || (ptype == TS_LINEAR)) {
229 SNESSetType(snes,SNESKSPONLY);
234 PetscOptionsGetReal(NULL,NULL,
"-jfnk_epsilon",&context.
jfnk_eps,NULL);
239 for (
int ns = 0; ns < nsims; ns++) {
240 if ((!sim[ns].solver.JFunction) && (!sim[ns].solver.KFunction)) {
242 fprintf(stderr,
"Error in SolvePETSc(): solver->JFunction or solver->KFunction ");
243 fprintf(stderr,
"(point-wise Jacobians for hyperbolic or parabolic terms) must ");
244 fprintf(stderr,
"be defined for preconditioning.\n");
246 PetscFunctionReturn(1);
251 MatCreateAIJ( MPI_COMM_WORLD,
256 (sim[0].solver.ndims*2+1)*sim[0].solver.nvars, NULL,
257 2*sim[0].solver.ndims*sim[0].solver.nvars, NULL,
259 MatSetBlockSize(B,sim[0].solver.nvars);
266 MatCreateSNESMF(snes,&A);
268 MatCreateAIJ( MPI_COMM_WORLD,
273 (sim[0].solver.ndims*2+1)*sim[0].solver.nvars, NULL,
274 2*sim[0].solver.ndims*sim[0].solver.nvars, NULL,
276 MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);
278 SNESSetJacobian(snes, A, B, SNESComputeJacobianDefault, NULL);
282 int stencil_width = 1;
283 PetscOptionsGetInt( NULL,
285 "-pc_matrix_colored_fd_stencil_width",
290 MatCreateSNESMF(snes,&A);
292 MatCreateAIJ( MPI_COMM_WORLD,
297 (sim[0].solver.ndims*2+1)*sim[0].solver.nvars, NULL,
298 2*sim[0].solver.ndims*sim[0].solver.nvars, NULL,
300 MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);
302 printf(
"PETSc: Setting Jacobian non-zero pattern (stencil width %d).\n",
308 SNESSetJacobian(snes, A, B, SNESComputeJacobianDefaultColor, NULL);
313 fprintf( stderr,
"Invalid input for \"-pc_matrix_type\": %s.\n",
316 PetscFunctionReturn(0);
321 SNESGetKSP(snes,&ksp);
322 KSPSetPCSide(ksp, PC_RIGHT);
328 MatCreateShell( MPI_COMM_WORLD,
335 if ((!strcmp(snestype,SNESKSPONLY)) || (ptype == TS_LINEAR)) {
339 SNESSetType(snes,SNESKSPONLY);
344 PetscOptionsGetReal(NULL,NULL,
"-jfnk_epsilon",&context.
jfnk_eps,NULL);
351 SNESGetKSP(snes,&ksp);
353 PCSetType(pc,PCNONE);
358 PetscBool flag = PETSC_FALSE;
366 if (!strcmp(sim[0].solver.SplitHyperbolicFlux,
"yes")) {
369 PetscOptionsGetBool(
nullptr,
nullptr,
"-hyperbolic_f_explicit",&flag,
nullptr);
372 PetscOptionsGetBool(
nullptr,
nullptr,
"-hyperbolic_f_implicit",&flag,
nullptr);
376 PetscOptionsGetBool(
nullptr,
nullptr,
"-hyperbolic_df_explicit",&flag,
nullptr);
379 PetscOptionsGetBool(
nullptr,
nullptr,
"-hyperbolic_df_implicit",&flag,
nullptr);
385 PetscOptionsGetBool(
nullptr,
nullptr,
"-hyperbolic_explicit",&flag,
nullptr);
388 PetscOptionsGetBool(
nullptr,
nullptr,
"-hyperbolic_implicit",&flag,
nullptr);
394 PetscOptionsGetBool(
nullptr,
nullptr,
"-parabolic_explicit",&flag,
nullptr);
397 PetscOptionsGetBool(
nullptr,
nullptr,
"-parabolic_implicit",&flag,
nullptr);
401 PetscOptionsGetBool(
nullptr,
nullptr,
"-source_explicit",&flag,
nullptr);
404 PetscOptionsGetBool(
nullptr,
nullptr,
"-source_implicit",&flag,
nullptr);
408 PetscOptionsGetBool(
nullptr,
nullptr,
"-ts_arkimex_fully_implicit",&flag,
nullptr);
409 if (flag == PETSC_TRUE) {
419 printf(
"Implicit-Explicit time-integration:-\n");
420 if (!strcmp(sim[0].solver.SplitHyperbolicFlux,
"yes")) {
422 else printf(
"Hyperbolic (f-df) term: Implicit\n");
424 else printf(
"Hyperbolic (df) term: Implicit\n");
427 else printf(
"Hyperbolic term: Implicit\n");
430 else printf(
"Parabolic term: Implicit\n");
432 else printf(
"Source term: Implicit\n");
435 }
else if ( (!strcmp(time_scheme,TSEULER))
436 || (!strcmp(time_scheme,TSRK ))
437 || (!strcmp(time_scheme,TSSSP )) ) {
442 }
else if ( (!strcmp(time_scheme,TSCN))
443 || (!strcmp(time_scheme,TSBEULER )) ) {
455 SNESGetType(snes,&snestype);
464 PetscOptionsGetBool(
nullptr,
471 PetscOptionsGetString(
nullptr,
474 precon_mat_type_c_st,
485 MatCreateShell( MPI_COMM_WORLD,
492 if ((!strcmp(snestype,SNESKSPONLY)) || (ptype == TS_LINEAR)) {
496 SNESSetType(snes,SNESKSPONLY);
501 PetscOptionsGetReal(NULL,NULL,
"-jfnk_epsilon",&context.
jfnk_eps,NULL);
506 for (
int ns = 0; ns < nsims; ns++) {
507 if ((!sim[ns].solver.JFunction) && (!sim[ns].solver.KFunction)) {
509 fprintf(stderr,
"Error in SolvePETSc(): solver->JFunction or solver->KFunction ");
510 fprintf(stderr,
"(point-wise Jacobians for hyperbolic or parabolic terms) must ");
511 fprintf(stderr,
"be defined for preconditioning.\n");
513 PetscFunctionReturn(1);
518 MatCreateAIJ( MPI_COMM_WORLD,
523 (sim[0].solver.ndims*2+1)*sim[0].solver.nvars, NULL,
524 2*sim[0].solver.ndims*sim[0].solver.nvars, NULL,
526 MatSetBlockSize(B,sim[0].solver.nvars);
533 MatCreateSNESMF(snes,&A);
535 MatCreateAIJ( MPI_COMM_WORLD,
540 (sim[0].solver.ndims*2+1)*sim[0].solver.nvars, NULL,
541 2*sim[0].solver.ndims*sim[0].solver.nvars, NULL,
543 MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);
545 SNESSetJacobian(snes, A, B, SNESComputeJacobianDefault, NULL);
549 int stencil_width = 1;
550 PetscOptionsGetInt( NULL,
552 "-pc_matrix_colored_fd_stencil_width",
557 MatCreateSNESMF(snes,&A);
559 MatCreateAIJ( MPI_COMM_WORLD,
564 (sim[0].solver.ndims*2+1)*sim[0].solver.nvars, NULL,
565 2*sim[0].solver.ndims*sim[0].solver.nvars, NULL,
567 MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);
569 printf(
"PETSc: Setting Jacobian non-zero pattern (stencil width %d).\n",
575 SNESSetJacobian(snes, A, B, SNESComputeJacobianDefaultColor, NULL);
580 fprintf( stderr,
"Invalid input for \"-pc_matrix_type\": %s.\n",
583 PetscFunctionReturn(0);
588 SNESGetKSP(snes,&ksp);
589 KSPSetPCSide(ksp, PC_RIGHT);
595 MatCreateShell( MPI_COMM_WORLD,
602 if ((!strcmp(snestype,SNESKSPONLY)) || (ptype == TS_LINEAR)) {
606 SNESSetType(snes,SNESKSPONLY);
611 PetscOptionsGetReal(NULL,NULL,
"-jfnk_epsilon",&context.
jfnk_eps,NULL);
618 SNESGetKSP(snes,&ksp);
620 PCSetType(pc,PCNONE);
626 fprintf(stderr,
"Time integration type %s is not yet supported.\n", time_scheme);
628 PetscFunctionReturn(0);
642 TSSetApplicationContext(ts,&context);
645 if (context.
flag_is_linear) printf(
"SolvePETSc(): Problem type is linear.\n");
646 else printf(
"SolvePETSc(): Problem type is nonlinear.\n");
649 if (!rank) printf(
"** Starting PETSc time integration **\n");
653 printf(
"** Completed PETSc time integration (Final time: %f), total wctime: %f (seconds) **\n",
658 for (
int ns = 0; ns < nsims; ns++) {
659 TSGetStepNumber(ts,&(sim[ns].solver.n_iter));
663 char aux_fname_root[4] =
"ts0";
664 TSGetSolutionComponents(ts,&iAuxSize,NULL);
666 if (iAuxSize > 10) iAuxSize = 10;
667 if (!rank) printf(
"Number of auxiliary solutions from time integration: %d\n",iAuxSize);
669 for (i=0; i<iAuxSize; i++) {
670 TSGetSolutionComponents(ts,&i,&Z);
671 for (
int ns = 0; ns < nsims; ns++) {
674 sim[ns].solver.nvars,
675 sim[ns].solver.dim_global,
676 sim[ns].solver.dim_local,
677 sim[ns].solver.ghosts,
693 for (
int ns = 0; ns < nsims; ns++) {
699 if (flag_mat_a) { MatDestroy(&A); }
700 if (flag_mat_b) { MatDestroy(&B); }
701 if (flag_fdcoloring) { MatFDColoringDestroy(&fdcoloring); }
707 for (
int ns = 0; ns < nsims; ns++) {
718 for (
int ns = 0; ns < nsims; ns++) {
727 for (
int ns = 0; ns < nsims; ns++) {
729 sim[ns].solver.index_length );
735 if (!rank) printf(
"libROM: total training wallclock time: %f (seconds).\n",
738 double total_rom_predict_time = 0;
739 for (
int iter = 0; iter < context.
op_times_arr.size(); iter++) {
744 if (!rank) printf(
"libROM: Predicted solution at time %1.4e using ROM, wallclock time: %f.\n",
750 if (!rank) printf(
"libROM: Calculating diff between PDE and ROM solutions.\n");
751 for (
int ns = 0; ns < nsims; ns++) {
762 printf(
"libROM: total prediction/query wallclock time: %f (seconds).\n",
763 total_rom_predict_time );
770 for (
int ns = 0; ns < nsims; ns++) {
781 for (
int ns = 0; ns < nsims; ns++) {
797 double cur_time = start_iter * dt;
800 for (
int iter = start_iter; iter < n_iter; iter++) {
803 && ( (iter+1) < n_iter) ) {
808 double t_final = n_iter*dt;
812 double total_rom_predict_time = 0;
813 for (
int iter = 0; iter < context.
op_times_arr.size(); iter++) {
818 if (!rank) printf(
"libROM: Predicted solution at time %1.4e using ROM, wallclock time: %f.\n",
823 for (
int ns = 0; ns < nsims; ns++) {
835 for (
int ns = 0; ns < nsims; ns++) {
841 printf(
"libROM: total prediction/query wallclock time: %f (seconds).\n",
842 total_rom_predict_time );
850 PetscFunctionReturn(0);
std::vector< int * > points
int(* PhysicsOutput)(void *, void *, double)
int TransferVecToPETSc(const double *const, Vec, void *, const int, const int)
PetscErrorCode PetscPostTimeStep(TS)
PetscErrorCode PetscPreTimeStep(TS)
int CalculateROMDiff(void *, void *)
#define _ROM_MODE_INITIAL_GUESS_
Structure defining a simulation.
int CalculateError(void *, void *)
std::vector< double > stage_times
int PetscJacobianMatNonzeroEntriesImpl(Mat, int, void *)
#define _ROM_MODE_PREDICT_
PetscErrorCode PetscPreStage(TS, PetscReal)
int OutputSolution(void *, int, double)
PetscErrorCode PetscJacobianFunctionIMEX_Linear(Mat, Vec, Vec)
int OutputROMSolution(void *, int, double)
int PetscGlobalDOF(void *)
PetscErrorCode PetscRHSFunctionExpl(TS, PetscReal, Vec, Vec, void *)
void ResetFilenameIndex(char *, int)
Structure containing all solver-specific variables and functions.
#define _MAX_STRING_SIZE_
char ConservationCheck[_MAX_STRING_SIZE_]
int WriteArray(int, int, int *, int *, int, double *, double *, void *, void *, char *)
std::vector< double > op_times_arr
int PetscRegisterTIMethods(int)
Structure containing the variables for time-integration with PETSc.
PetscErrorCode PetscPostStage(TS, PetscReal, PetscInt, Vec *)
Class implementing interface with libROM.
PetscErrorCode PetscJacobianFunction_JFNK(Mat, Vec, Vec)
PetscErrorCode PetscSetInitialGuessROM(SNES, Vec, void *)
PetscErrorCode PetscIJacobian(TS, PetscReal, Vec, Vec, PetscReal, Mat, Mat, void *)
Structure of MPI-related variables.
PetscErrorCode PetscIJacobianIMEX(TS, PetscReal, Vec, Vec, PetscReal, Mat, Mat, void *)
std::vector< double * > globalDOF
PetscErrorCode PetscRHSFunctionIMEX(TS, PetscReal, Vec, Vec, void *)
PetscErrorCode PetscTimeError(TS)
std::string precon_matrix_type
int PetscCreatePointList(void *)
PetscErrorCode PetscIFunctionIMEX(TS, PetscReal, Vec, Vec, Vec, void *)
int TransferVecFromPETSc(double *const, const Vec, void *, const int, const int)
PetscErrorCode PetscJacobianFunctionIMEX_JFNK(Mat, Vec, Vec)
PetscErrorCode PetscIFunctionImpl(TS, PetscReal, Vec, Vec, Vec, void *)
PetscErrorCode PetscJacobianFunction_Linear(Mat, Vec, Vec)