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);
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++) {
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,
259 MatSetBlockSize(B,sim[0].solver.nvars);
266 MatCreateSNESMF(snes,&A);
268 MatCreateAIJ( MPI_COMM_WORLD,
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,
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++) {
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,
526 MatSetBlockSize(B,sim[0].solver.nvars);
533 MatCreateSNESMF(snes,&A);
535 MatCreateAIJ( MPI_COMM_WORLD,
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,
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++) {
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++) {
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);
int CalculateError(void *s, void *m)
PetscErrorCode PetscTimeError(TS)
PetscErrorCode PetscIJacobianIMEX(TS, PetscReal, Vec, Vec, PetscReal, Mat, Mat, void *)
int PetscJacobianMatNonzeroEntriesImpl(Mat, int, void *)
PetscErrorCode PetscJacobianFunction_JFNK(Mat, Vec, Vec)
int TransferVecFromPETSc(double *const, const Vec, void *, const int, const int)
PetscErrorCode PetscJacobianFunctionIMEX_JFNK(Mat, Vec, Vec)
int PetscGlobalDOF(void *)
#define _ROM_MODE_INITIAL_GUESS_
PetscErrorCode PetscJacobianFunction_Linear(Mat, Vec, Vec)
int(* PhysicsOutput)(void *, void *, double)
std::vector< int * > points
PetscErrorCode PetscIJacobian(TS, PetscReal, Vec, Vec, PetscReal, Mat, Mat, void *)
int OutputROMSolution(void *s, int nsims, double a_time)
void ResetFilenameIndex(char *f, int len)
std::vector< double > stage_times
std::vector< double > op_times_arr
int WriteArray(int, int, int *, int *, int, double *, double *, void *, void *, char *)
#define _MAX_STRING_SIZE_
char ConservationCheck[_MAX_STRING_SIZE_]
std::string precon_matrix_type
Class implementing interface with libROM.
int CalculateROMDiff(void *s, void *m)
int TransferVecToPETSc(const double *const, Vec, void *, const int, const int)
std::vector< double * > globalDOF
int(* KFunction)(double *, double *, void *, int, int)
int OutputSolution(void *, int, double)
Structure containing the variables for time-integration with PETSc.
#define _ROM_MODE_PREDICT_
int PetscCreatePointList(void *)
PetscErrorCode PetscPreTimeStep(TS)
PetscErrorCode PetscRHSFunctionIMEX(TS, PetscReal, Vec, Vec, void *)
Structure defining a simulation.
PetscErrorCode PetscRHSFunctionExpl(TS, PetscReal, Vec, Vec, void *)
PetscErrorCode PetscPreStage(TS, PetscReal)
PetscErrorCode PetscPostTimeStep(TS)
PetscErrorCode PetscJacobianFunctionIMEX_Linear(Mat, Vec, Vec)
PetscErrorCode PetscSetInitialGuessROM(SNES, Vec, void *)
Structure of MPI-related variables.
PetscErrorCode PetscIFunctionImpl(TS, PetscReal, Vec, Vec, Vec, void *)
Structure containing all solver-specific variables and functions.
PetscErrorCode PetscPostStage(TS, PetscReal, PetscInt, Vec *)
PetscErrorCode PetscIFunctionIMEX(TS, PetscReal, Vec, Vec, Vec, void *)
int PetscRegisterTIMethods(int)