HyPar  1.0
Finite-Difference Hyperbolic-Parabolic PDE Solver on Cartesian Grids
SolvePETSc.cpp File Reference

Integrate in time using PETSc. More...

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <basic.h>
#include <io_cpp.h>
#include <petscinterface.h>
#include <simulation_object.h>
#include <librom_interface.h>

Go to the source code of this file.

Macros

#define __FUNCT__   "SolvePETSc"
 

Functions

int CalculateError (void *, void *)
 
int OutputSolution (void *, int, double)
 
void ResetFilenameIndex (char *, int)
 
int CalculateROMDiff (void *, void *)
 
int OutputROMSolution (void *, int, double)
 
int SolvePETSc (void *s, int nsims, int rank, int nproc)
 Integrate in time with PETSc. More...
 

Detailed Description

Integrate in time using PETSc.

Author
Debojyoti Ghosh

Integrate the spatially discretized system in time using PETSc's TS module.
(https://petsc.org/release/docs/manualpages/TS/index.html)

Definition in file SolvePETSc.cpp.

Macro Definition Documentation

◆ __FUNCT__

#define __FUNCT__   "SolvePETSc"

Definition at line 25 of file SolvePETSc.cpp.

Function Documentation

◆ CalculateError()

int CalculateError ( void *  s,
void *  m 
)

Calculate the error in the final solution

Calculates the error in the solution if the exact solution is available. If the exact solution is not available, the errors are reported as zero. The exact solution should be provided in the file "exact.inp" in the same format as the initial solution.

Parameters
sSolver object of type HyPar
mMPI object of type MPIVariables

Definition at line 25 of file CalculateError.c.

29 {
30  HyPar *solver = (HyPar*) s;
31  MPIVariables *mpi = (MPIVariables*) m;
32  int exact_flag = 0, i, size;
33  double sum = 0, global_sum = 0;
34  double *uex = NULL;
36 
37  size = solver->nvars;
38  for (i = 0; i < solver->ndims; i++)
39  size *= (solver->dim_local[i]+2*solver->ghosts);
40  uex = (double*) calloc (size, sizeof(double));
41 
42  char fname_root[_MAX_STRING_SIZE_] = "exact";
43  if (solver->nsims > 1) {
44  char index[_MAX_STRING_SIZE_];
45  GetStringFromInteger(solver->my_idx, index, (int)log10(solver->nsims)+1);
46  strcat(fname_root, "_");
47  strcat(fname_root, index);
48  }
49 
50  static const double tolerance = 1e-15;
51  IERR ExactSolution( solver,
52  mpi,
53  uex,
54  fname_root,
55  &exact_flag ); CHECKERR(ierr);
56 
57  if (!exact_flag) {
58 
59  /* No exact solution */
60  IERR TimeError(solver,mpi,NULL); CHECKERR(ierr);
61  solver->error[0] = solver->error[1] = solver->error[2] = -1;
62 
63  } else {
64 
65  IERR TimeError(solver,mpi,uex); CHECKERR(ierr);
66 
67  /* calculate solution norms (for relative error) */
68  double solution_norm[3] = {0.0,0.0,0.0};
69  /* L1 */
70  sum = ArraySumAbsnD (solver->nvars,solver->ndims,solver->dim_local,
71  solver->ghosts,solver->index,uex);
72  global_sum = 0; MPISum_double(&global_sum,&sum,1,&mpi->world);
73  solution_norm[0] = global_sum/((double)solver->npoints_global);
74  /* L2 */
75  sum = ArraySumSquarenD(solver->nvars,solver->ndims,solver->dim_local,
76  solver->ghosts,solver->index,uex);
77  global_sum = 0; MPISum_double(&global_sum,&sum,1,&mpi->world);
78  solution_norm[1] = sqrt(global_sum/((double)solver->npoints_global));
79  /* Linf */
80  sum = ArrayMaxnD (solver->nvars,solver->ndims,solver->dim_local,
81  solver->ghosts,solver->index,uex);
82  global_sum = 0; MPIMax_double(&global_sum,&sum,1,&mpi->world);
83  solution_norm[2] = global_sum;
84 
85  /* compute error = difference between exact and numerical solution */
86  _ArrayAXPY_(solver->u,-1.0,uex,size);
87 
88  /* calculate L1 norm of error */
89  sum = ArraySumAbsnD (solver->nvars,solver->ndims,solver->dim_local,
90  solver->ghosts,solver->index,uex);
91  global_sum = 0; MPISum_double(&global_sum,&sum,1,&mpi->world);
92  solver->error[0] = global_sum/((double)solver->npoints_global);
93 
94  /* calculate L2 norm of error */
95  sum = ArraySumSquarenD(solver->nvars,solver->ndims,solver->dim_local,
96  solver->ghosts,solver->index,uex);
97  global_sum = 0; MPISum_double(&global_sum,&sum,1,&mpi->world);
98  solver->error[1] = sqrt(global_sum/((double)solver->npoints_global));
99 
100  /* calculate Linf norm of error */
101  sum = ArrayMaxnD (solver->nvars,solver->ndims,solver->dim_local,
102  solver->ghosts,solver->index,uex);
103  global_sum = 0; MPIMax_double(&global_sum,&sum,1,&mpi->world);
104  solver->error[2] = global_sum;
105 
106  /*
107  decide whether to normalize and report relative errors,
108  or report absolute errors.
109  */
110  if ( (solution_norm[0] > tolerance)
111  && (solution_norm[1] > tolerance)
112  && (solution_norm[2] > tolerance) ) {
113  solver->error[0] /= solution_norm[0];
114  solver->error[1] /= solution_norm[1];
115  solver->error[2] /= solution_norm[2];
116  }
117  }
118 
119  free(uex);
120  return(0);
121 }
int nvars
Definition: hypar.h:29
#define IERR
Definition: basic.h:16
#define CHECKERR(ierr)
Definition: basic.h:18
int MPISum_double(double *, double *, int, void *)
Definition: MPISum.c:39
int nsims
Definition: hypar.h:64
double error[3]
Definition: hypar.h:371
long sum(const std::vector< int > &a_iv)
Definition: std_vec_ops.h:18
double * u
Definition: hypar.h:116
int ndims
Definition: hypar.h:26
int ExactSolution(void *, void *, double *, char *, int *)
Definition: ExactSolution.c:16
INLINE double ArraySumAbsnD(int, int, int *, int, int *, double *)
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
#define _MAX_STRING_SIZE_
Definition: basic.h:14
int MPIMax_double(double *, double *, int, void *)
Definition: MPIMax.c:38
#define _ArrayAXPY_(x, a, y, size)
int npoints_global
Definition: hypar.h:40
MPI_Comm world
int * index
Definition: hypar.h:102
void GetStringFromInteger(int, char *, int)
int my_idx
Definition: hypar.h:61
int * dim_local
Definition: hypar.h:37
INLINE double ArrayMaxnD(int, int, int *, int, int *, double *)
int ghosts
Definition: hypar.h:52
Structure of MPI-related variables.
#define _DECLARE_IERR_
Definition: basic.h:17
INLINE double ArraySumSquarenD(int, int, int *, int, int *, double *)
int TimeError(void *, void *, double *)
Definition: TimeError.c:27

◆ OutputSolution()

int OutputSolution ( void *  s,
int  nsims,
double  a_time 
)

Write solutions to file

Write out the solution to file

Parameters
sArray of simulation objects of type SimulationObject
nsimsNumber of simulation objects
a_timeCurrent simulation time

Definition at line 27 of file OutputSolution.cpp.

30 {
31  SimulationObject* simobj = (SimulationObject*) s;
32  int ns;
34 
35  for (ns = 0; ns < nsims; ns++) {
36 
37  HyPar* solver = &(simobj[ns].solver);
38  MPIVariables* mpi = &(simobj[ns].mpi);
39 
40  if ((!solver->WriteOutput) && (strcmp(solver->plot_solution,"yes"))) continue;
41 
42  /* time integration module may have auxiliary arrays to write out, so get them */
43  int NSolutions = 0;
44  IERR TimeGetAuxSolutions(&NSolutions,NULL,solver,-1,ns); CHECKERR(ierr);
45  if (NSolutions > 10) NSolutions = 10;
46 
47  int nu;
48  char fname_root[_MAX_STRING_SIZE_];
49  char aux_fname_root[_MAX_STRING_SIZE_];
50  strcpy(fname_root, solver->op_fname_root);
51  strcpy(aux_fname_root, solver->aux_op_fname_root);
52 
53  if (nsims > 1) {
54  char index[_MAX_STRING_SIZE_];
55  GetStringFromInteger(ns, index, (int)log10(nsims)+1);
56  strcat(fname_root, "_");
57  strcat(fname_root, index);
58  strcat(aux_fname_root, "_");
59  strcat(aux_fname_root, index);
60  }
61 
62  for (nu=0; nu<NSolutions; nu++) {
63 
64  double *uaux = NULL;
65  IERR TimeGetAuxSolutions(&NSolutions,&uaux,solver,nu,ns); CHECKERR(ierr);
66 
67  IERR WriteArray( solver->ndims,
68  solver->nvars,
69  solver->dim_global,
70  solver->dim_local,
71  solver->ghosts,
72  solver->x,
73  uaux,
74  solver,
75  mpi,
76  aux_fname_root ); CHECKERR(ierr);
77 
78  aux_fname_root[2]++;
79  }
80 
81 #if defined(HAVE_CUDA)
82  if (solver->use_gpu) {
83  /* Copy values from GPU memory to CPU memory for writing. */
84  gpuMemcpy(solver->x, solver->gpu_x, sizeof(double)*solver->size_x, gpuMemcpyDeviceToHost);
85 
86 #ifdef CUDA_VAR_ORDERDING_AOS
87  gpuMemcpy( solver->u,
88  solver->gpu_u,
89  sizeof(double)*solver->ndof_cells_wghosts,
91 #else
92  double *h_u = (double *) malloc(sizeof(double)*solver->ndof_cells_wghosts);
93  gpuMemcpy(h_u, solver->gpu_u, sizeof(double)*solver->ndof_cells_wghosts, gpuMemcpyDeviceToHost);
94  for (int i=0; i<solver->npoints_local_wghosts; i++) {
95  for (int v=0; v<solver->nvars; v++) {
96  solver->u[i*solver->nvars+v] = h_u[i+v*solver->npoints_local_wghosts];
97  }
98  }
99  free(h_u);
100 #endif
101  }
102 #endif
103 
104  WriteArray( solver->ndims,
105  solver->nvars,
106  solver->dim_global,
107  solver->dim_local,
108  solver->ghosts,
109  solver->x,
110  solver->u,
111  solver,
112  mpi,
113  fname_root );
114 
115  if (!strcmp(solver->plot_solution, "yes")) {
116  PlotArray( solver->ndims,
117  solver->nvars,
118  solver->dim_global,
119  solver->dim_local,
120  solver->ghosts,
121  solver->x,
122  solver->u,
123  a_time,
124  solver,
125  mpi,
126  fname_root );
127  }
128 
129  /* increment the index string, if required */
130  if ((!strcmp(solver->output_mode,"serial")) && (!strcmp(solver->op_overwrite,"no"))) {
132  }
133 
134  }
135 
136  return(0);
137 }
char plot_solution[_MAX_STRING_SIZE_]
Definition: hypar.h:194
int nvars
Definition: hypar.h:29
#define IERR
Definition: basic.h:16
char * filename_index
Definition: hypar.h:197
#define CHECKERR(ierr)
Definition: basic.h:18
Structure defining a simulation.
int PlotArray(int, int, int *, int *, int, double *, double *, double, void *, void *, char *)
Definition: PlotArray.c:31
int TimeGetAuxSolutions(int *, double **, void *, int, int)
double * u
Definition: hypar.h:116
char output_mode[_MAX_STRING_SIZE_]
Definition: hypar.h:183
double * x
Definition: hypar.h:107
int size_x
Definition: hypar.h:48
double * gpu_x
Definition: hypar.h:457
char aux_op_fname_root[_MAX_STRING_SIZE_]
Definition: hypar.h:208
int ndims
Definition: hypar.h:26
int ndof_cells_wghosts
Definition: hypar.h:47
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
#define _MAX_STRING_SIZE_
Definition: basic.h:14
double * gpu_u
Definition: hypar.h:459
char op_overwrite[_MAX_STRING_SIZE_]
Definition: hypar.h:191
int WriteArray(int, int, int *, int *, int, double *, double *, void *, void *, char *)
Definition: WriteArray.c:27
void GetStringFromInteger(int, char *, int)
int index_length
Definition: hypar.h:199
char op_fname_root[_MAX_STRING_SIZE_]
Definition: hypar.h:206
int * dim_local
Definition: hypar.h:37
void gpuMemcpy(void *, const void *, size_t, enum gpuMemcpyKind)
void IncrementFilenameIndex(char *, int)
int(* WriteOutput)(int, int, int *, double *, double *, char *, int *)
Definition: hypar.h:211
int ghosts
Definition: hypar.h:52
Structure of MPI-related variables.
int use_gpu
Definition: hypar.h:449
int npoints_local_wghosts
Definition: hypar.h:42
#define _DECLARE_IERR_
Definition: basic.h:17
int * dim_global
Definition: hypar.h:33

◆ ResetFilenameIndex()

void ResetFilenameIndex ( char *  f,
int  len 
)

Reset filename index

Resets the index to "0000..." of a desired length.

Parameters
fCharacter string representing the integer
lenLength of the string

Definition at line 64 of file IncrementFilename.c.

66 {
67  if (!f) return;
68  int i;
69  for (i = 0; i < len; i++) {
70  f[i] = '0';
71  }
72  return;
73 }

◆ CalculateROMDiff()

int CalculateROMDiff ( void *  s,
void *  m 
)

Calculate the diff of PDE and ROM solutions

Calculates the L1, L2, & Linf norms of the diff between the PDE solution and the predicted solution by libROM. error in the solution if the exact solution is

Parameters
sSolver object of type HyPar
mMPI object of type MPIVariables

Definition at line 24 of file CalculateROMDiff.c.

26 {
27  HyPar* solver = (HyPar*) s;
28  MPIVariables* mpi = (MPIVariables*) m;
29  double sum = 0, global_sum = 0;
30 
31  static const double tolerance = 1e-15;
32 
33  int size = solver->npoints_local_wghosts * solver->nvars;
34  double* u_diff = (double*) calloc (size, sizeof(double));
35 
36  /* calculate solution norms (for relative error) */
37  double solution_norm[3] = {0.0,0.0,0.0};
38  /* L1 */
39  sum = ArraySumAbsnD ( solver->nvars,
40  solver->ndims,
41  solver->dim_local,
42  solver->ghosts,
43  solver->index,
44  solver->u );
45  global_sum = 0; MPISum_double(&global_sum,&sum,1,&mpi->world);
46  solution_norm[0] = global_sum/((double)solver->npoints_global);
47  /* L2 */
48  sum = ArraySumSquarenD ( solver->nvars,
49  solver->ndims,
50  solver->dim_local,
51  solver->ghosts,
52  solver->index,
53  solver->u );
54  global_sum = 0; MPISum_double(&global_sum,&sum,1,&mpi->world);
55  solution_norm[1] = sqrt(global_sum/((double)solver->npoints_global));
56  /* Linf */
57  sum = ArrayMaxnD ( solver->nvars,
58  solver->ndims,
59  solver->dim_local,
60  solver->ghosts,
61  solver->index
62  ,solver->u );
63  global_sum = 0; MPIMax_double(&global_sum,&sum,1,&mpi->world);
64  solution_norm[2] = global_sum;
65 
66  /* set u_diff to PDE solution */
67  _ArrayCopy1D_(solver->u, u_diff, size);
68  /* subtract the ROM solutions */
69  _ArrayAXPY_(solver->u_rom_predicted, -1.0, u_diff, size);
70 
71  /* calculate L1 norm of error */
72  sum = ArraySumAbsnD ( solver->nvars,
73  solver->ndims,
74  solver->dim_local,
75  solver->ghosts,
76  solver->index,
77  u_diff );
78  global_sum = 0; MPISum_double(&global_sum,&sum,1,&mpi->world);
79  solver->rom_diff_norms[0] = global_sum/((double)solver->npoints_global);
80 
81  /* calculate L2 norm of error */
82  sum = ArraySumSquarenD ( solver->nvars,
83  solver->ndims,
84  solver->dim_local,
85  solver->ghosts,
86  solver->index,
87  u_diff );
88  global_sum = 0; MPISum_double(&global_sum,&sum,1,&mpi->world);
89  solver->rom_diff_norms[1] = sqrt(global_sum/((double)solver->npoints_global));
90 
91  /* calculate Linf norm of error */
92  sum = ArrayMaxnD ( solver->nvars,
93  solver->ndims,
94  solver->dim_local,
95  solver->ghosts,
96  solver->index,
97  u_diff );
98  global_sum = 0; MPIMax_double(&global_sum,&sum,1,&mpi->world);
99  solver->rom_diff_norms[2] = global_sum;
100 
101  /* decide whether to normalize and report relative diff norms,
102  or report absolute diff norms. */
103  if ( (solution_norm[0] > tolerance)
104  && (solution_norm[1] > tolerance)
105  && (solution_norm[2] > tolerance) ) {
106  solver->rom_diff_norms[0] /= solution_norm[0];
107  solver->rom_diff_norms[1] /= solution_norm[1];
108  solver->rom_diff_norms[2] /= solution_norm[2];
109  }
110 
111  free(u_diff);
112  return 0;
113 }
int nvars
Definition: hypar.h:29
int MPISum_double(double *, double *, int, void *)
Definition: MPISum.c:39
long sum(const std::vector< int > &a_iv)
Definition: std_vec_ops.h:18
double * u
Definition: hypar.h:116
int ndims
Definition: hypar.h:26
INLINE double ArraySumAbsnD(int, int, int *, int, int *, double *)
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
int MPIMax_double(double *, double *, int, void *)
Definition: MPIMax.c:38
#define _ArrayAXPY_(x, a, y, size)
int npoints_global
Definition: hypar.h:40
MPI_Comm world
int * index
Definition: hypar.h:102
int * dim_local
Definition: hypar.h:37
double rom_diff_norms[3]
Definition: hypar.h:405
INLINE double ArrayMaxnD(int, int, int *, int, int *, double *)
int ghosts
Definition: hypar.h:52
Structure of MPI-related variables.
int npoints_local_wghosts
Definition: hypar.h:42
double * u_rom_predicted
Definition: hypar.h:403
INLINE double ArraySumSquarenD(int, int, int *, int, int *, double *)
#define _ArrayCopy1D_(x, y, size)

◆ OutputROMSolution()

int OutputROMSolution ( void *  s,
int  nsims,
double  a_time 
)

Write ROM solutions to file

Write out the ROM solution to file

Parameters
sArray of simulation objects of type SimulationObject
nsimsNumber of simulation objects
a_timeCurrent simulation time

Definition at line 24 of file OutputROMSolution.cpp.

27 {
28  SimulationObject* simobj = (SimulationObject*) s;
29  int ns;
30 
31  for (ns = 0; ns < nsims; ns++) {
32 
33  HyPar* solver = &(simobj[ns].solver);
34  MPIVariables* mpi = &(simobj[ns].mpi);
35 
36  if ((!solver->WriteOutput) && (strcmp(solver->plot_solution,"yes"))) continue;
37 
38  char fname_root[_MAX_STRING_SIZE_];
39  strcpy(fname_root, solver->op_rom_fname_root);
40 
41  if (nsims > 1) {
42  char index[_MAX_STRING_SIZE_];
43  GetStringFromInteger(ns, index, (int)log10(nsims)+1);
44  strcat(fname_root, "_");
45  strcat(fname_root, index);
46  }
47 
48  WriteArray( solver->ndims,
49  solver->nvars,
50  solver->dim_global,
51  solver->dim_local,
52  solver->ghosts,
53  solver->x,
54  solver->u_rom_predicted,
55  solver,
56  mpi,
57  fname_root );
58 
59  if (!strcmp(solver->plot_solution, "yes")) {
60  PlotArray( solver->ndims,
61  solver->nvars,
62  solver->dim_global,
63  solver->dim_local,
64  solver->ghosts,
65  solver->x,
66  solver->u,
67  a_time,
68  solver,
69  mpi,
70  fname_root );
71  }
72 
73  /* increment the index string, if required */
74  if ((!strcmp(solver->output_mode,"serial")) && (!strcmp(solver->op_overwrite,"no"))) {
76  }
77 
78  }
79 
80  return 0;
81 }
char plot_solution[_MAX_STRING_SIZE_]
Definition: hypar.h:194
int nvars
Definition: hypar.h:29
char * filename_index
Definition: hypar.h:197
Structure defining a simulation.
int PlotArray(int, int, int *, int *, int, double *, double *, double, void *, void *, char *)
Definition: PlotArray.c:31
char op_rom_fname_root[_MAX_STRING_SIZE_]
Definition: hypar.h:407
double * u
Definition: hypar.h:116
char output_mode[_MAX_STRING_SIZE_]
Definition: hypar.h:183
double * x
Definition: hypar.h:107
void IncrementFilenameIndex(char *, int)
int ndims
Definition: hypar.h:26
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
#define _MAX_STRING_SIZE_
Definition: basic.h:14
char op_overwrite[_MAX_STRING_SIZE_]
Definition: hypar.h:191
int WriteArray(int, int, int *, int *, int, double *, double *, void *, void *, char *)
Definition: WriteArray.c:27
void GetStringFromInteger(int, char *, int)
int index_length
Definition: hypar.h:199
int * dim_local
Definition: hypar.h:37
int(* WriteOutput)(int, int, int *, double *, double *, char *, int *)
Definition: hypar.h:211
int ghosts
Definition: hypar.h:52
Structure of MPI-related variables.
double * u_rom_predicted
Definition: hypar.h:403
int * dim_global
Definition: hypar.h:33

◆ SolvePETSc()

int SolvePETSc ( void *  s,
int  nsims,
int  rank,
int  nproc 
)

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).

Parameters
sArray of simulation objects of type SimulationObject
nsimsnumber of simulation objects
rankMPI rank of this process
nprocNumber of MPI processes

Definition at line 50 of file SolvePETSc.cpp.

54 {
56 
57  DM dm; /* data management object */
58  TS ts; /* time integration object */
59  Vec Y,Z; /* PETSc solution vectors */
60  Mat A, B; /* Jacobian and preconditioning matrices */
61  MatFDColoring fdcoloring; /* coloring for sparse Jacobian computation */
62  TSType time_scheme; /* time integration method */
63  TSProblemType ptype; /* problem type - nonlinear or linear */
64 
65  int flag_mat_a = 0,
66  flag_mat_b = 0,
67  flag_fdcoloring = 0,
68  iAuxSize = 0, i;
69 
70  PetscFunctionBegin;
71 
72  /* Register custom time-integration methods, if specified */
74  if(!rank) printf("Setting up PETSc time integration... \n");
75 
76  /* create and set a PETSc context */
77  PETScContext context;
78 
79  context.rank = rank;
80  context.nproc = nproc;
81 
82  context.simobj = sim;
83  context.nsims = nsims;
84 
85  /* default: everything explicit */
86  context.flag_hyperbolic = _EXPLICIT_;
87  context.flag_hyperbolic_f = _EXPLICIT_;
88  context.flag_hyperbolic_df = _EXPLICIT_;
89  context.flag_parabolic = _EXPLICIT_;
90  context.flag_source = _EXPLICIT_;
91 
92  context.tic = 0;
93  context.flag_is_linear = 0;
94  context.globalDOF.clear();
95  context.points.clear();
96  context.ti_runtime = 0.0;
97  context.waqt = 0.0;
98  context.dt = sim[0].solver.dt;
99  context.stage_times.clear();
100  context.stage_index = 0;
101 
102 #ifdef with_librom
103  if (!rank) printf("Setting up libROM interface.\n");
104  context.rom_interface = new libROMInterface( sim,
105  nsims,
106  rank,
107  nproc,
108  sim[0].solver.dt );
109  context.rom_mode = ((libROMInterface*)context.rom_interface)->mode();
110  context.op_times_arr.clear();
111 #endif
112 
113 #ifdef with_librom
114  if ( (context.rom_mode == _ROM_MODE_TRAIN_)
115  || (context.rom_mode == _ROM_MODE_INITIAL_GUESS_ )
116  || (context.rom_mode == _ROM_MODE_NONE_ ) ) {
117 
118  if (context.rom_mode == _ROM_MODE_INITIAL_GUESS_) {
119  ((libROMInterface*)context.rom_interface)->loadROM();
120  ((libROMInterface*)context.rom_interface)->projectInitialSolution(sim);
121  }
122 #endif
123  PetscCreatePointList(&context);
124 
125  /* create and initialize PETSc solution vector and other parameters */
126  /* PETSc solution vector does not have ghost points */
127  VecCreate(MPI_COMM_WORLD,&Y);
128  VecSetSizes(Y,context.ndofs,PETSC_DECIDE);
129  VecSetUp(Y);
130 
131  /* copy initial solution to PETSc's vector */
132  for (int ns = 0; ns < nsims; ns++) {
133  TransferVecToPETSc( sim[ns].solver.u,
134  Y,
135  &context,
136  ns,
137  context.offsets[ns] );
138  }
139 
140  /* Create the global DOF mapping for all the grid points */
141  PetscGlobalDOF(&context);
142 
143  /* Define and initialize the time-integration object */
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);
151 
152  /* set default time step adaptivity to none */
153  TSAdapt adapt;
154  TSAdaptType adapt_type = TSADAPTNONE;
155  TSGetAdapt(ts,&adapt);
156  TSAdaptSetType(adapt,adapt_type);
157 
158  /* set options from input */
159  TSSetFromOptions(ts);
160 
161  /* create DM */
162  DMShellCreate(MPI_COMM_WORLD, &dm);
163  DMShellSetGlobalVector(dm, Y);
164  TSSetDM(ts, dm);
165 
166 #ifdef with_librom
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");
170  }
171 #endif
172 
173  /* Define the right and left -hand side functions for each time-integration scheme */
174  TSGetType(ts,&time_scheme);
175  TSGetProblemType(ts,&ptype);
176 
177  if (!strcmp(time_scheme,TSARKIMEX)) {
178 
179  /* implicit - explicit time integration */
180 
181  TSSetRHSFunction(ts,nullptr,PetscRHSFunctionIMEX,&context);
182  TSSetIFunction (ts,nullptr,PetscIFunctionIMEX, &context);
183 
184  SNES snes;
185  KSP ksp;
186  PC pc;
187  SNESType snestype;
188  TSGetSNES(ts,&snes);
189  SNESGetType(snes,&snestype);
190 
191 #ifdef with_librom
192  if (context.rom_mode == _ROM_MODE_INITIAL_GUESS_) {
193  SNESSetComputeInitialGuess(snes, PetscSetInitialGuessROM, &context);
194  }
195 #endif
196 
197  context.flag_use_precon = 0;
198  PetscOptionsGetBool( nullptr,nullptr,
199  "-with_pc",
200  (PetscBool*)(&context.flag_use_precon),
201  nullptr );
202 
203  char precon_mat_type_c_st[_MAX_STRING_SIZE_] = "default";
204  PetscOptionsGetString( nullptr,
205  nullptr,
206  "-pc_matrix_type",
207  precon_mat_type_c_st,
209  nullptr );
210  context.precon_matrix_type = std::string(precon_mat_type_c_st);
211 
212  if (context.flag_use_precon) {
213 
214  if (context.precon_matrix_type == "default") {
215 
216  /* Matrix-free representation of the Jacobian */
217  flag_mat_a = 1;
218  MatCreateShell( MPI_COMM_WORLD,
219  context.ndofs,
220  context.ndofs,
221  PETSC_DETERMINE,
222  PETSC_DETERMINE,
223  &context,
224  &A);
225  if ((!strcmp(snestype,SNESKSPONLY)) || (ptype == TS_LINEAR)) {
226  /* linear problem */
227  context.flag_is_linear = 1;
228  MatShellSetOperation(A,MATOP_MULT,(void (*)(void))PetscJacobianFunctionIMEX_Linear);
229  SNESSetType(snes,SNESKSPONLY);
230  } else {
231  /* nonlinear problem */
232  context.flag_is_linear = 0;
233  context.jfnk_eps = 1e-7;
234  PetscOptionsGetReal(NULL,NULL,"-jfnk_epsilon",&context.jfnk_eps,NULL);
235  MatShellSetOperation(A,MATOP_MULT,(void (*)(void))PetscJacobianFunctionIMEX_JFNK);
236  }
237  MatSetUp(A);
238  /* check if Jacobian of the physical model is defined */
239  for (int ns = 0; ns < nsims; ns++) {
240  if ((!sim[ns].solver.JFunction) && (!sim[ns].solver.KFunction)) {
241  if (!rank) {
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");
245  }
246  PetscFunctionReturn(1);
247  }
248  }
249  /* Set up preconditioner matrix */
250  flag_mat_b = 1;
251  MatCreateAIJ( MPI_COMM_WORLD,
252  context.ndofs,
253  context.ndofs,
254  PETSC_DETERMINE,
255  PETSC_DETERMINE,
256  (sim[0].solver.ndims*2+1)*sim[0].solver.nvars, NULL,
257  2*sim[0].solver.ndims*sim[0].solver.nvars, NULL,
258  &B );
259  MatSetBlockSize(B,sim[0].solver.nvars);
260  /* Set the IJacobian function for TS */
261  TSSetIJacobian(ts,A,B,PetscIJacobianIMEX,&context);
262 
263  } else if (context.precon_matrix_type == "fd") {
264 
265  flag_mat_a = 1;
266  MatCreateSNESMF(snes,&A);
267  flag_mat_b = 1;
268  MatCreateAIJ( MPI_COMM_WORLD,
269  context.ndofs,
270  context.ndofs,
271  PETSC_DETERMINE,
272  PETSC_DETERMINE,
273  (sim[0].solver.ndims*2+1)*sim[0].solver.nvars, NULL,
274  2*sim[0].solver.ndims*sim[0].solver.nvars, NULL,
275  &B);
276  MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);
277  /* Set the Jacobian function for SNES */
278  SNESSetJacobian(snes, A, B, SNESComputeJacobianDefault, NULL);
279 
280  } else if (context.precon_matrix_type == "colored_fd") {
281 
282  int stencil_width = 1;
283  PetscOptionsGetInt( NULL,
284  NULL,
285  "-pc_matrix_colored_fd_stencil_width",
286  &stencil_width,
287  NULL );
288 
289  flag_mat_a = 1;
290  MatCreateSNESMF(snes,&A);
291  flag_mat_b = 1;
292  MatCreateAIJ( MPI_COMM_WORLD,
293  context.ndofs,
294  context.ndofs,
295  PETSC_DETERMINE,
296  PETSC_DETERMINE,
297  (sim[0].solver.ndims*2+1)*sim[0].solver.nvars, NULL,
298  2*sim[0].solver.ndims*sim[0].solver.nvars, NULL,
299  &B);
300  MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);
301  if (!rank) {
302  printf("PETSc: Setting Jacobian non-zero pattern (stencil width %d).\n",
303  stencil_width );
304  }
305  PetscJacobianMatNonzeroEntriesImpl(B, stencil_width, &context);
306 
307  /* Set the Jacobian function for SNES */
308  SNESSetJacobian(snes, A, B, SNESComputeJacobianDefaultColor, NULL);
309 
310  } else {
311 
312  if (!rank) {
313  fprintf( stderr,"Invalid input for \"-pc_matrix_type\": %s.\n",
314  context.precon_matrix_type.c_str());
315  }
316  PetscFunctionReturn(0);
317 
318  }
319 
320  /* set PC side to right */
321  SNESGetKSP(snes,&ksp);
322  KSPSetPCSide(ksp, PC_RIGHT);
323 
324  } else {
325 
326  /* Matrix-free representation of the Jacobian */
327  flag_mat_a = 1;
328  MatCreateShell( MPI_COMM_WORLD,
329  context.ndofs,
330  context.ndofs,
331  PETSC_DETERMINE,
332  PETSC_DETERMINE,
333  &context,
334  &A);
335  if ((!strcmp(snestype,SNESKSPONLY)) || (ptype == TS_LINEAR)) {
336  /* linear problem */
337  context.flag_is_linear = 1;
338  MatShellSetOperation(A,MATOP_MULT,(void (*)(void))PetscJacobianFunctionIMEX_Linear);
339  SNESSetType(snes,SNESKSPONLY);
340  } else {
341  /* nonlinear problem */
342  context.flag_is_linear = 0;
343  context.jfnk_eps = 1e-7;
344  PetscOptionsGetReal(NULL,NULL,"-jfnk_epsilon",&context.jfnk_eps,NULL);
345  MatShellSetOperation(A,MATOP_MULT,(void (*)(void))PetscJacobianFunctionIMEX_JFNK);
346  }
347  MatSetUp(A);
348  /* Set the RHSJacobian function for TS */
349  TSSetIJacobian(ts,A,A,PetscIJacobianIMEX,&context);
350  /* Set PC (preconditioner) to none */
351  SNESGetKSP(snes,&ksp);
352  KSPGetPC(ksp,&pc);
353  PCSetType(pc,PCNONE);
354  }
355 
356  /* read the implicit/explicit flags for each of the terms for IMEX schemes */
357  /* default -> hyperbolic - explicit, parabolic and source - implicit */
358  PetscBool flag = PETSC_FALSE;
359 
360  context.flag_hyperbolic = _EXPLICIT_;
361  context.flag_hyperbolic_f = _EXPLICIT_;
362  context.flag_hyperbolic_df = _IMPLICIT_;
363  context.flag_parabolic = _IMPLICIT_;
364  context.flag_source = _IMPLICIT_;
365 
366  if (!strcmp(sim[0].solver.SplitHyperbolicFlux,"yes")) {
367 
368  flag = PETSC_FALSE;
369  PetscOptionsGetBool(nullptr,nullptr,"-hyperbolic_f_explicit",&flag,nullptr);
370  if (flag == PETSC_TRUE) context.flag_hyperbolic_f = _EXPLICIT_;
371  flag = PETSC_FALSE;
372  PetscOptionsGetBool(nullptr,nullptr,"-hyperbolic_f_implicit",&flag,nullptr);
373  if (flag == PETSC_TRUE) context.flag_hyperbolic_f = _IMPLICIT_;
374 
375  flag = PETSC_FALSE;
376  PetscOptionsGetBool(nullptr,nullptr,"-hyperbolic_df_explicit",&flag,nullptr);
377  if (flag == PETSC_TRUE) context.flag_hyperbolic_df = _EXPLICIT_;
378  flag = PETSC_FALSE;
379  PetscOptionsGetBool(nullptr,nullptr,"-hyperbolic_df_implicit",&flag,nullptr);
380  if (flag == PETSC_TRUE) context.flag_hyperbolic_df = _IMPLICIT_;
381 
382  } else {
383 
384  flag = PETSC_FALSE;
385  PetscOptionsGetBool(nullptr,nullptr,"-hyperbolic_explicit",&flag,nullptr);
386  if (flag == PETSC_TRUE) context.flag_hyperbolic = _EXPLICIT_;
387  flag = PETSC_FALSE;
388  PetscOptionsGetBool(nullptr,nullptr,"-hyperbolic_implicit",&flag,nullptr);
389  if (flag == PETSC_TRUE) context.flag_hyperbolic = _IMPLICIT_;
390 
391  }
392 
393  flag = PETSC_FALSE;
394  PetscOptionsGetBool(nullptr,nullptr,"-parabolic_explicit",&flag,nullptr);
395  if (flag == PETSC_TRUE) context.flag_parabolic = _EXPLICIT_;
396  flag = PETSC_FALSE;
397  PetscOptionsGetBool(nullptr,nullptr,"-parabolic_implicit",&flag,nullptr);
398  if (flag == PETSC_TRUE) context.flag_parabolic = _IMPLICIT_;
399 
400  flag = PETSC_FALSE;
401  PetscOptionsGetBool(nullptr,nullptr,"-source_explicit",&flag,nullptr);
402  if (flag == PETSC_TRUE) context.flag_source = _EXPLICIT_;
403  flag = PETSC_FALSE;
404  PetscOptionsGetBool(nullptr,nullptr,"-source_implicit",&flag,nullptr);
405  if (flag == PETSC_TRUE) context.flag_source = _IMPLICIT_;
406 
407  flag = PETSC_FALSE;
408  PetscOptionsGetBool(nullptr,nullptr,"-ts_arkimex_fully_implicit",&flag,nullptr);
409  if (flag == PETSC_TRUE) {
410  context.flag_hyperbolic_f = _IMPLICIT_;
411  context.flag_hyperbolic_df = _IMPLICIT_;
412  context.flag_hyperbolic = _IMPLICIT_;
413  context.flag_parabolic = _IMPLICIT_;
414  context.flag_source = _IMPLICIT_;
415  }
416 
417  /* print out a summary of the treatment of each term */
418  if (!rank) {
419  printf("Implicit-Explicit time-integration:-\n");
420  if (!strcmp(sim[0].solver.SplitHyperbolicFlux,"yes")) {
421  if (context.flag_hyperbolic_f == _EXPLICIT_) printf("Hyperbolic (f-df) term: Explicit\n");
422  else printf("Hyperbolic (f-df) term: Implicit\n");
423  if (context.flag_hyperbolic_df == _EXPLICIT_) printf("Hyperbolic (df) term: Explicit\n");
424  else printf("Hyperbolic (df) term: Implicit\n");
425  } else {
426  if (context.flag_hyperbolic == _EXPLICIT_) printf("Hyperbolic term: Explicit\n");
427  else printf("Hyperbolic term: Implicit\n");
428  }
429  if (context.flag_parabolic == _EXPLICIT_) printf("Parabolic term: Explicit\n");
430  else printf("Parabolic term: Implicit\n");
431  if (context.flag_source == _EXPLICIT_) printf("Source term: Explicit\n");
432  else printf("Source term: Implicit\n");
433  }
434 
435  } else if ( (!strcmp(time_scheme,TSEULER))
436  || (!strcmp(time_scheme,TSRK ))
437  || (!strcmp(time_scheme,TSSSP )) ) {
438 
439  /* Explicit time integration */
440  TSSetRHSFunction(ts,nullptr,PetscRHSFunctionExpl,&context);
441 
442  } else if ( (!strcmp(time_scheme,TSCN))
443  || (!strcmp(time_scheme,TSBEULER )) ) {
444 
445 
446  /* Implicit time integration */
447 
448  TSSetIFunction(ts,nullptr,PetscIFunctionImpl,&context);
449 
450  SNES snes;
451  KSP ksp;
452  PC pc;
453  SNESType snestype;
454  TSGetSNES(ts,&snes);
455  SNESGetType(snes,&snestype);
456 
457 #ifdef with_librom
458  if (context.rom_mode == _ROM_MODE_INITIAL_GUESS_) {
459  SNESSetComputeInitialGuess(snes, PetscSetInitialGuessROM, &context);
460  }
461 #endif
462 
463  context.flag_use_precon = 0;
464  PetscOptionsGetBool( nullptr,
465  nullptr,
466  "-with_pc",
467  (PetscBool*)(&context.flag_use_precon),
468  nullptr );
469 
470  char precon_mat_type_c_st[_MAX_STRING_SIZE_] = "default";
471  PetscOptionsGetString( nullptr,
472  nullptr,
473  "-pc_matrix_type",
474  precon_mat_type_c_st,
476  nullptr );
477  context.precon_matrix_type = std::string(precon_mat_type_c_st);
478 
479  if (context.flag_use_precon) {
480 
481  if (context.precon_matrix_type == "default") {
482 
483  /* Matrix-free representation of the Jacobian */
484  flag_mat_a = 1;
485  MatCreateShell( MPI_COMM_WORLD,
486  context.ndofs,
487  context.ndofs,
488  PETSC_DETERMINE,
489  PETSC_DETERMINE,
490  &context,
491  &A);
492  if ((!strcmp(snestype,SNESKSPONLY)) || (ptype == TS_LINEAR)) {
493  /* linear problem */
494  context.flag_is_linear = 1;
495  MatShellSetOperation(A,MATOP_MULT,(void (*)(void))PetscJacobianFunction_Linear);
496  SNESSetType(snes,SNESKSPONLY);
497  } else {
498  /* nonlinear problem */
499  context.flag_is_linear = 0;
500  context.jfnk_eps = 1e-7;
501  PetscOptionsGetReal(NULL,NULL,"-jfnk_epsilon",&context.jfnk_eps,NULL);
502  MatShellSetOperation(A,MATOP_MULT,(void (*)(void))PetscJacobianFunction_JFNK);
503  }
504  MatSetUp(A);
505  /* check if Jacobian of the physical model is defined */
506  for (int ns = 0; ns < nsims; ns++) {
507  if ((!sim[ns].solver.JFunction) && (!sim[ns].solver.KFunction)) {
508  if (!rank) {
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");
512  }
513  PetscFunctionReturn(1);
514  }
515  }
516  /* Set up preconditioner matrix */
517  flag_mat_b = 1;
518  MatCreateAIJ( MPI_COMM_WORLD,
519  context.ndofs,
520  context.ndofs,
521  PETSC_DETERMINE,
522  PETSC_DETERMINE,
523  (sim[0].solver.ndims*2+1)*sim[0].solver.nvars, NULL,
524  2*sim[0].solver.ndims*sim[0].solver.nvars, NULL,
525  &B );
526  MatSetBlockSize(B,sim[0].solver.nvars);
527  /* Set the IJacobian function for TS */
528  TSSetIJacobian(ts,A,B,PetscIJacobian,&context);
529 
530  } else if (context.precon_matrix_type == "fd") {
531 
532  flag_mat_a = 1;
533  MatCreateSNESMF(snes,&A);
534  flag_mat_b = 1;
535  MatCreateAIJ( MPI_COMM_WORLD,
536  context.ndofs,
537  context.ndofs,
538  PETSC_DETERMINE,
539  PETSC_DETERMINE,
540  (sim[0].solver.ndims*2+1)*sim[0].solver.nvars, NULL,
541  2*sim[0].solver.ndims*sim[0].solver.nvars, NULL,
542  &B);
543  MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);
544  /* Set the Jacobian function for SNES */
545  SNESSetJacobian(snes, A, B, SNESComputeJacobianDefault, NULL);
546 
547  } else if (context.precon_matrix_type == "colored_fd") {
548 
549  int stencil_width = 1;
550  PetscOptionsGetInt( NULL,
551  NULL,
552  "-pc_matrix_colored_fd_stencil_width",
553  &stencil_width,
554  NULL );
555 
556  flag_mat_a = 1;
557  MatCreateSNESMF(snes,&A);
558  flag_mat_b = 1;
559  MatCreateAIJ( MPI_COMM_WORLD,
560  context.ndofs,
561  context.ndofs,
562  PETSC_DETERMINE,
563  PETSC_DETERMINE,
564  (sim[0].solver.ndims*2+1)*sim[0].solver.nvars, NULL,
565  2*sim[0].solver.ndims*sim[0].solver.nvars, NULL,
566  &B);
567  MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);
568  if (!rank) {
569  printf("PETSc: Setting Jacobian non-zero pattern (stencil width %d).\n",
570  stencil_width );
571  }
572  PetscJacobianMatNonzeroEntriesImpl(B, stencil_width, &context);
573 
574  /* Set the Jacobian function for SNES */
575  SNESSetJacobian(snes, A, B, SNESComputeJacobianDefaultColor, NULL);
576 
577  } else {
578 
579  if (!rank) {
580  fprintf( stderr,"Invalid input for \"-pc_matrix_type\": %s.\n",
581  context.precon_matrix_type.c_str());
582  }
583  PetscFunctionReturn(0);
584 
585  }
586 
587  /* set PC side to right */
588  SNESGetKSP(snes,&ksp);
589  KSPSetPCSide(ksp, PC_RIGHT);
590 
591  } else {
592 
593  /* Matrix-free representation of the Jacobian */
594  flag_mat_a = 1;
595  MatCreateShell( MPI_COMM_WORLD,
596  context.ndofs,
597  context.ndofs,
598  PETSC_DETERMINE,
599  PETSC_DETERMINE,
600  &context,
601  &A);
602  if ((!strcmp(snestype,SNESKSPONLY)) || (ptype == TS_LINEAR)) {
603  /* linear problem */
604  context.flag_is_linear = 1;
605  MatShellSetOperation(A,MATOP_MULT,(void (*)(void))PetscJacobianFunction_Linear);
606  SNESSetType(snes,SNESKSPONLY);
607  } else {
608  /* nonlinear problem */
609  context.flag_is_linear = 0;
610  context.jfnk_eps = 1e-7;
611  PetscOptionsGetReal(NULL,NULL,"-jfnk_epsilon",&context.jfnk_eps,NULL);
612  MatShellSetOperation(A,MATOP_MULT,(void (*)(void))PetscJacobianFunction_JFNK);
613  }
614  MatSetUp(A);
615  /* Set the RHSJacobian function for TS */
616  TSSetIJacobian(ts,A,A,PetscIJacobian,&context);
617  /* Set PC (preconditioner) to none */
618  SNESGetKSP(snes,&ksp);
619  KSPGetPC(ksp,&pc);
620  PCSetType(pc,PCNONE);
621  }
622 
623  } else {
624 
625  if (!rank) {
626  fprintf(stderr, "Time integration type %s is not yet supported.\n", time_scheme);
627  }
628  PetscFunctionReturn(0);
629 
630  }
631 
632  /* Set pre/post-stage and post-timestep function */
633  TSSetPreStep (ts,PetscPreTimeStep );
634  TSSetPreStage(ts,PetscPreStage );
635  TSSetPostStage(ts,PetscPostStage );
636  TSSetPostStep(ts,PetscPostTimeStep);
637  /* Set solution vector for TS */
638  TSSetSolution(ts,Y);
639  /* Set it all up */
640  TSSetUp(ts);
641  /* Set application context */
642  TSSetApplicationContext(ts,&context);
643 
644  if (!rank) {
645  if (context.flag_is_linear) printf("SolvePETSc(): Problem type is linear.\n");
646  else printf("SolvePETSc(): Problem type is nonlinear.\n");
647  }
648 
649  if (!rank) printf("** Starting PETSc time integration **\n");
650  context.ti_runtime = 0.0;
651  TSSolve(ts,Y);
652  if (!rank) {
653  printf("** Completed PETSc time integration (Final time: %f), total wctime: %f (seconds) **\n",
654  context.waqt, context.ti_runtime );
655  }
656 
657  /* Get the number of time steps */
658  for (int ns = 0; ns < nsims; ns++) {
659  TSGetStepNumber(ts,&(sim[ns].solver.n_iter));
660  }
661 
662  /* get and write to file any auxiliary solutions */
663  char aux_fname_root[4] = "ts0";
664  TSGetSolutionComponents(ts,&iAuxSize,NULL);
665  if (iAuxSize) {
666  if (iAuxSize > 10) iAuxSize = 10;
667  if (!rank) printf("Number of auxiliary solutions from time integration: %d\n",iAuxSize);
668  VecDuplicate(Y,&Z);
669  for (i=0; i<iAuxSize; i++) {
670  TSGetSolutionComponents(ts,&i,&Z);
671  for (int ns = 0; ns < nsims; ns++) {
672  TransferVecFromPETSc(sim[ns].solver.u,Z,&context,ns,context.offsets[ns]);
673  WriteArray( sim[ns].solver.ndims,
674  sim[ns].solver.nvars,
675  sim[ns].solver.dim_global,
676  sim[ns].solver.dim_local,
677  sim[ns].solver.ghosts,
678  sim[ns].solver.x,
679  sim[ns].solver.u,
680  &(sim[ns].solver),
681  &(sim[ns].mpi),
682  aux_fname_root );
683  }
684  aux_fname_root[2]++;
685  }
686  VecDestroy(&Z);
687  }
688 
689  /* if available, get error estimates */
690  PetscTimeError(ts);
691 
692  /* copy final solution from PETSc's vector */
693  for (int ns = 0; ns < nsims; ns++) {
694  TransferVecFromPETSc(sim[ns].solver.u,Y,&context,ns,context.offsets[ns]);
695  }
696 
697  /* clean up */
698  VecDestroy(&Y);
699  if (flag_mat_a) { MatDestroy(&A); }
700  if (flag_mat_b) { MatDestroy(&B); }
701  if (flag_fdcoloring) { MatFDColoringDestroy(&fdcoloring); }
702  TSDestroy(&ts);
703  DMDestroy(&dm);
704 
705  /* write a final solution file, if last iteration did not write one */
706  if (context.tic) {
707  for (int ns = 0; ns < nsims; ns++) {
708  HyPar* solver = &(sim[ns].solver);
709  MPIVariables* mpi = &(sim[ns].mpi);
710  if (solver->PhysicsOutput) {
711  solver->PhysicsOutput(solver,mpi, context.waqt);
712  }
713  CalculateError(solver,mpi);
714  }
715  OutputSolution(sim, nsims, context.waqt);
716  }
717  /* calculate error if exact solution has been provided */
718  for (int ns = 0; ns < nsims; ns++) {
719  CalculateError(&(sim[ns].solver), &(sim[ns].mpi));
720  }
721 
722  PetscCleanup(&context);
723 
724 #ifdef with_librom
725  context.op_times_arr.push_back(context.waqt);
726 
727  for (int ns = 0; ns < nsims; ns++) {
728  ResetFilenameIndex( sim[ns].solver.filename_index,
729  sim[ns].solver.index_length );
730  }
731 
732  if (((libROMInterface*)context.rom_interface)->mode() == _ROM_MODE_TRAIN_) {
733 
734  ((libROMInterface*)context.rom_interface)->train();
735  if (!rank) printf("libROM: total training wallclock time: %f (seconds).\n",
736  ((libROMInterface*)context.rom_interface)->trainWallclockTime() );
737 
738  double total_rom_predict_time = 0;
739  for (int iter = 0; iter < context.op_times_arr.size(); iter++) {
740 
741  double waqt = context.op_times_arr[iter];
742 
743  ((libROMInterface*)context.rom_interface)->predict(sim, waqt);
744  if (!rank) printf( "libROM: Predicted solution at time %1.4e using ROM, wallclock time: %f.\n",
745  waqt, ((libROMInterface*)context.rom_interface)->predictWallclockTime() );
746  total_rom_predict_time += ((libROMInterface*)context.rom_interface)->predictWallclockTime();
747 
748  /* calculate diff between ROM and PDE solutions */
749  if (iter == (context.op_times_arr.size()-1)) {
750  if (!rank) printf("libROM: Calculating diff between PDE and ROM solutions.\n");
751  for (int ns = 0; ns < nsims; ns++) {
752  CalculateROMDiff( &(sim[ns].solver),
753  &(sim[ns].mpi) );
754  }
755  }
756  /* write the ROM solution to file */
757  OutputROMSolution(sim, nsims, waqt);
758 
759  }
760 
761  if (!rank) {
762  printf( "libROM: total prediction/query wallclock time: %f (seconds).\n",
763  total_rom_predict_time );
764  }
765 
766  ((libROMInterface*)context.rom_interface)->saveROM();
767 
768  } else {
769 
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]
774  = -1;
775  }
776 
777  }
778 
779  } else if (context.rom_mode == _ROM_MODE_PREDICT_) {
780 
781  for (int ns = 0; ns < nsims; ns++) {
782  sim[ns].solver.rom_diff_norms[0]
783  = sim[ns].solver.rom_diff_norms[1]
784  = sim[ns].solver.rom_diff_norms[2]
785  = -1;
786  strcpy(sim[ns].solver.ConservationCheck,"no");
787  }
788 
789  ((libROMInterface*)context.rom_interface)->loadROM();
790  ((libROMInterface*)context.rom_interface)->projectInitialSolution(sim);
791 
792  {
793  int start_iter = sim[0].solver.restart_iter;
794  int n_iter = sim[0].solver.n_iter;
795  double dt = sim[0].solver.dt;
796 
797  double cur_time = start_iter * dt;
798  context.op_times_arr.push_back(cur_time);
799 
800  for (int iter = start_iter; iter < n_iter; iter++) {
801  cur_time += dt;
802  if ( ( (iter+1)%sim[0].solver.file_op_iter == 0)
803  && ( (iter+1) < n_iter) ) {
804  context.op_times_arr.push_back(cur_time);
805  }
806  }
807 
808  double t_final = n_iter*dt;
809  context.op_times_arr.push_back(t_final);
810  }
811 
812  double total_rom_predict_time = 0;
813  for (int iter = 0; iter < context.op_times_arr.size(); iter++) {
814 
815  double waqt = context.op_times_arr[iter];
816 
817  ((libROMInterface*)context.rom_interface)->predict(sim, waqt);
818  if (!rank) printf( "libROM: Predicted solution at time %1.4e using ROM, wallclock time: %f.\n",
819  waqt, ((libROMInterface*)context.rom_interface)->predictWallclockTime() );
820  total_rom_predict_time += ((libROMInterface*)context.rom_interface)->predictWallclockTime();
821 
822  /* write the solution to file */
823  for (int ns = 0; ns < nsims; ns++) {
824  if (sim[ns].solver.PhysicsOutput) {
825  sim[ns].solver.PhysicsOutput( &(sim[ns].solver),
826  &(sim[ns].mpi),
827  waqt );
828  }
829  }
830  OutputSolution(sim, nsims, waqt);
831 
832  }
833 
834  /* calculate error if exact solution has been provided */
835  for (int ns = 0; ns < nsims; ns++) {
836  CalculateError(&(sim[ns].solver),
837  &(sim[ns].mpi) );
838  }
839 
840  if (!rank) {
841  printf( "libROM: total prediction/query wallclock time: %f (seconds).\n",
842  total_rom_predict_time );
843  }
844 
845  }
846 
847  delete ((libROMInterface*)context.rom_interface);
848 #endif
849 
850  PetscFunctionReturn(0);
851 }
std::vector< int * > points
int(* PhysicsOutput)(void *, void *, double)
Definition: hypar.h:347
int TransferVecToPETSc(const double *const, Vec, void *, const int, const int)
PetscErrorCode PetscPostTimeStep(TS)
PetscErrorCode PetscPreTimeStep(TS)
char * filename_index
Definition: hypar.h:197
int CalculateROMDiff(void *, void *)
#define _ROM_MODE_INITIAL_GUESS_
Structure defining a simulation.
int CalculateError(void *, void *)
std::vector< double > stage_times
#define _IMPLICIT_
int PetscJacobianMatNonzeroEntriesImpl(Mat, int, void *)
int PetscCleanup(void *)
int n_iter
Definition: hypar.h:55
#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 *)
int restart_iter
Definition: hypar.h:58
PetscErrorCode PetscRHSFunctionExpl(TS, PetscReal, Vec, Vec, void *)
void ResetFilenameIndex(char *, int)
#define _ROM_MODE_NONE_
Structure containing all solver-specific variables and functions.
Definition: hypar.h:23
#define _MAX_STRING_SIZE_
Definition: basic.h:14
char ConservationCheck[_MAX_STRING_SIZE_]
Definition: hypar.h:376
#define _ROM_MODE_TRAIN_
int WriteArray(int, int, int *, int *, int, double *, double *, void *, void *, char *)
Definition: WriteArray.c:27
std::vector< double > op_times_arr
int PetscRegisterTIMethods(int)
Structure containing the variables for time-integration with PETSc.
double dt
Definition: hypar.h:67
double rom_diff_norms[3]
Definition: hypar.h:405
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)
Definition: PetscError.cpp:20
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)
int file_op_iter
Definition: hypar.h:171
PetscErrorCode PetscIFunctionImpl(TS, PetscReal, Vec, Vec, Vec, void *)
#define _EXPLICIT_
PetscErrorCode PetscJacobianFunction_Linear(Mat, Vec, Vec)