25 #define __FUNCT__ "SolvePETSc" 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++) {
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++) {
708 HyPar* solver = &(sim[ns].solver);
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++) {
771 sim[ns].solver.rom_diff_norms[0]
772 = sim[ns].solver.rom_diff_norms[1]
773 = sim[ns].solver.rom_diff_norms[2]
781 for (
int ns = 0; ns < nsims; ns++) {
786 strcpy(sim[ns].solver.ConservationCheck,
"no");
797 double cur_time = start_iter * dt;
800 for (
int iter = start_iter; iter < n_iter; iter++) {
802 if ( ( (iter+1)%sim[0].solver.file_op_iter == 0)
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++) {
824 if (sim[ns].solver.PhysicsOutput) {
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 *)
int SolvePETSc(void *s, int nsims, int rank, int nproc)
Integrate in time with PETSc.
#define _ROM_MODE_PREDICT_
PetscErrorCode PetscPreStage(TS, PetscReal)
Some basic definitions and macros.
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_
Function declarations for file I/O functions.
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)