| 929 | } |
| 930 | |
| 931 | PetscErrorCode PetscMonitor(TS ts, PetscInt UNUSED(step), PetscReal t, Vec X, void* ctx) { |
| 932 | PetscErrorCode ierr; |
| 933 | auto* s = static_cast<PetscSolver*>(ctx); |
| 934 | PetscReal tfinal, dt; |
| 935 | Vec interpolatedX; |
| 936 | const PetscScalar* x; |
| 937 | static int i = 0; |
| 938 | |
| 939 | PetscFunctionBegin; |
| 940 | ierr = TSGetTimeStep(ts, &dt); |
| 941 | CHKERRQ(ierr); |
| 942 | |
| 943 | #if PETSC_VERSION_GE(3, 8, 0) |
| 944 | ierr = TSGetMaxTime(ts, &tfinal); |
| 945 | CHKERRQ(ierr); |
| 946 | #else |
| 947 | ierr = TSGetDuration(ts, nullptr, &tfinal); |
| 948 | CHKERRQ(ierr); |
| 949 | #endif |
| 950 | |
| 951 | /* Duplicate the solution vector X into a work vector */ |
| 952 | ierr = VecDuplicate(X, &interpolatedX); |
| 953 | CHKERRQ(ierr); |
| 954 | while (s->next_output <= t && s->next_output <= tfinal) { |
| 955 | if (s->interpolate) { |
| 956 | ierr = TSInterpolate(ts, s->next_output, interpolatedX); |
| 957 | CHKERRQ(ierr); |
| 958 | } |
| 959 | |
| 960 | /* Place the interpolated values into the global variables */ |
| 961 | ierr = VecGetArrayRead(interpolatedX, &x); |
| 962 | CHKERRQ(ierr); |
| 963 | s->load_vars(const_cast<BoutReal*>(x)); |
| 964 | ierr = VecRestoreArrayRead(interpolatedX, &x); |
| 965 | CHKERRQ(ierr); |
| 966 | |
| 967 | if (s->call_monitors(simtime, i++, s->getNumberOutputSteps())) { |
| 968 | PetscFunctionReturn(1); |
| 969 | } |
| 970 | |
| 971 | s->next_output += s->getOutputTimestep(); |
| 972 | simtime = s->next_output; |
| 973 | } |
| 974 | |
| 975 | /* Done with vector, so destroy it */ |
| 976 | ierr = VecDestroy(&interpolatedX); |
| 977 | CHKERRQ(ierr); |
| 978 | |
| 979 | PetscFunctionReturn(0); |
| 980 | } |
| 981 | |
| 982 | PetscErrorCode PetscSNESMonitor(SNES snes, PetscInt its, PetscReal norm, void* ctx) { |
| 983 | PetscErrorCode ierr; |
nothing calls this directly
no test coverage detected