xref: /libCEED/examples/fluids/src/setupts.c (revision 3d8e882215d238700cdceb37404f76ca7fa24eaa)
1*3d8e8822SJeremy L Thompson // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors.
2*3d8e8822SJeremy L Thompson // All Rights Reserved. See the top-level LICENSE and NOTICE files for details.
377841947SLeila Ghaffari //
4*3d8e8822SJeremy L Thompson // SPDX-License-Identifier: BSD-2-Clause
577841947SLeila Ghaffari //
6*3d8e8822SJeremy L Thompson // This file is part of CEED:  http://github.com/ceed
777841947SLeila Ghaffari 
877841947SLeila Ghaffari /// @file
977841947SLeila Ghaffari /// Time-stepping functions for Navier-Stokes example using PETSc
1077841947SLeila Ghaffari 
1177841947SLeila Ghaffari #include "../navierstokes.h"
1277841947SLeila Ghaffari #include "../qfunctions/mass.h"
1377841947SLeila Ghaffari 
1477841947SLeila Ghaffari // Compute mass matrix for explicit scheme
1577841947SLeila Ghaffari PetscErrorCode ComputeLumpedMassMatrix(Ceed ceed, DM dm, CeedData ceed_data,
1677841947SLeila Ghaffari                                        Vec M) {
1777841947SLeila Ghaffari   Vec            M_loc;
1877841947SLeila Ghaffari   CeedQFunction  qf_mass;
1977841947SLeila Ghaffari   CeedOperator   op_mass;
2077841947SLeila Ghaffari   CeedVector     m_ceed, ones_vec;
2177841947SLeila Ghaffari   CeedInt        num_comp_q, q_data_size;
2277841947SLeila Ghaffari   PetscErrorCode ierr;
2377841947SLeila Ghaffari   PetscFunctionBeginUser;
2477841947SLeila Ghaffari 
2577841947SLeila Ghaffari   // CEED Restriction
2677841947SLeila Ghaffari   CeedElemRestrictionGetNumComponents(ceed_data->elem_restr_q, &num_comp_q);
2777841947SLeila Ghaffari   CeedElemRestrictionGetNumComponents(ceed_data->elem_restr_qd_i, &q_data_size);
2877841947SLeila Ghaffari   CeedElemRestrictionCreateVector(ceed_data->elem_restr_q, &m_ceed, NULL);
2977841947SLeila Ghaffari   CeedElemRestrictionCreateVector(ceed_data->elem_restr_q, &ones_vec, NULL);
3077841947SLeila Ghaffari   CeedVectorSetValue(ones_vec, 1.0);
3177841947SLeila Ghaffari 
3277841947SLeila Ghaffari   // CEED QFunction
3377841947SLeila Ghaffari   CeedQFunctionCreateInterior(ceed, 1, Mass, Mass_loc, &qf_mass);
3477841947SLeila Ghaffari   CeedQFunctionAddInput(qf_mass, "q", num_comp_q, CEED_EVAL_INTERP);
35a61c78d6SJeremy L Thompson   CeedQFunctionAddInput(qf_mass, "qdata", q_data_size, CEED_EVAL_NONE);
3677841947SLeila Ghaffari   CeedQFunctionAddOutput(qf_mass, "v", num_comp_q, CEED_EVAL_INTERP);
3777841947SLeila Ghaffari 
3877841947SLeila Ghaffari   // CEED Operator
3977841947SLeila Ghaffari   CeedOperatorCreate(ceed, qf_mass, NULL, NULL, &op_mass);
4077841947SLeila Ghaffari   CeedOperatorSetField(op_mass, "q", ceed_data->elem_restr_q, ceed_data->basis_q,
4177841947SLeila Ghaffari                        CEED_VECTOR_ACTIVE);
42a61c78d6SJeremy L Thompson   CeedOperatorSetField(op_mass, "qdata", ceed_data->elem_restr_qd_i,
4377841947SLeila Ghaffari                        CEED_BASIS_COLLOCATED, ceed_data->q_data);
4477841947SLeila Ghaffari   CeedOperatorSetField(op_mass, "v", ceed_data->elem_restr_q, ceed_data->basis_q,
4577841947SLeila Ghaffari                        CEED_VECTOR_ACTIVE);
4677841947SLeila Ghaffari 
4777841947SLeila Ghaffari   // Place PETSc vector in CEED vector
4877841947SLeila Ghaffari   CeedScalar *m;
4977841947SLeila Ghaffari   PetscMemType m_mem_type;
5077841947SLeila Ghaffari   ierr = DMGetLocalVector(dm, &M_loc); CHKERRQ(ierr);
5177841947SLeila Ghaffari   ierr = VecGetArrayAndMemType(M_loc, (PetscScalar **)&m, &m_mem_type);
5277841947SLeila Ghaffari   CHKERRQ(ierr);
5377841947SLeila Ghaffari   CeedVectorSetArray(m_ceed, MemTypeP2C(m_mem_type), CEED_USE_POINTER, m);
5477841947SLeila Ghaffari 
5577841947SLeila Ghaffari   // Apply CEED Operator
5677841947SLeila Ghaffari   CeedOperatorApply(op_mass, ones_vec, m_ceed, CEED_REQUEST_IMMEDIATE);
5777841947SLeila Ghaffari 
5877841947SLeila Ghaffari   // Restore vectors
5977841947SLeila Ghaffari   CeedVectorTakeArray(m_ceed, MemTypeP2C(m_mem_type), NULL);
6077841947SLeila Ghaffari   ierr = VecRestoreArrayReadAndMemType(M_loc, (const PetscScalar **)&m);
6177841947SLeila Ghaffari   CHKERRQ(ierr);
6277841947SLeila Ghaffari 
6377841947SLeila Ghaffari   // Local-to-Global
6477841947SLeila Ghaffari   ierr = VecZeroEntries(M); CHKERRQ(ierr);
6577841947SLeila Ghaffari   ierr = DMLocalToGlobal(dm, M_loc, ADD_VALUES, M); CHKERRQ(ierr);
6677841947SLeila Ghaffari   ierr = DMRestoreLocalVector(dm, &M_loc); CHKERRQ(ierr);
6777841947SLeila Ghaffari 
6877841947SLeila Ghaffari   // Invert diagonally lumped mass vector for RHS function
6977841947SLeila Ghaffari   ierr = VecReciprocal(M); CHKERRQ(ierr);
7077841947SLeila Ghaffari 
7177841947SLeila Ghaffari   // Cleanup
7277841947SLeila Ghaffari   CeedVectorDestroy(&ones_vec);
7377841947SLeila Ghaffari   CeedVectorDestroy(&m_ceed);
7477841947SLeila Ghaffari   CeedQFunctionDestroy(&qf_mass);
7577841947SLeila Ghaffari   CeedOperatorDestroy(&op_mass);
7677841947SLeila Ghaffari 
7777841947SLeila Ghaffari   PetscFunctionReturn(0);
7877841947SLeila Ghaffari }
7977841947SLeila Ghaffari 
8077841947SLeila Ghaffari // RHS (Explicit time-stepper) function setup
8177841947SLeila Ghaffari //   This is the RHS of the ODE, given as u_t = G(t,u)
8277841947SLeila Ghaffari //   This function takes in a state vector Q and writes into G
8377841947SLeila Ghaffari PetscErrorCode RHS_NS(TS ts, PetscReal t, Vec Q, Vec G, void *user_data) {
8477841947SLeila Ghaffari 
8577841947SLeila Ghaffari   User           user = *(User *)user_data;
8677841947SLeila Ghaffari   PetscScalar    *q, *g;
8777841947SLeila Ghaffari   Vec            Q_loc, G_loc;
8877841947SLeila Ghaffari   PetscMemType   q_mem_type, g_mem_type;
8977841947SLeila Ghaffari   PetscErrorCode ierr;
9077841947SLeila Ghaffari   PetscFunctionBeginUser;
9177841947SLeila Ghaffari 
9277841947SLeila Ghaffari   // Update EulerContext
9377841947SLeila Ghaffari   if (user->phys->has_curr_time) user->phys->euler_ctx->curr_time = t;
9477841947SLeila Ghaffari 
9577841947SLeila Ghaffari   // Get local vectors
9677841947SLeila Ghaffari   ierr = DMGetLocalVector(user->dm, &Q_loc); CHKERRQ(ierr);
9777841947SLeila Ghaffari   ierr = DMGetLocalVector(user->dm, &G_loc); CHKERRQ(ierr);
9877841947SLeila Ghaffari 
9977841947SLeila Ghaffari   // Global-to-local
10077841947SLeila Ghaffari   ierr = VecZeroEntries(Q_loc); CHKERRQ(ierr);
10177841947SLeila Ghaffari   ierr = DMGlobalToLocal(user->dm, Q, INSERT_VALUES, Q_loc); CHKERRQ(ierr);
10277841947SLeila Ghaffari   ierr = DMPlexInsertBoundaryValues(user->dm, PETSC_TRUE, Q_loc, 0.0,
10377841947SLeila Ghaffari                                     NULL, NULL, NULL); CHKERRQ(ierr);
10477841947SLeila Ghaffari   ierr = VecZeroEntries(G_loc); CHKERRQ(ierr);
10577841947SLeila Ghaffari 
10677841947SLeila Ghaffari   // Place PETSc vectors in CEED vectors
10777841947SLeila Ghaffari   ierr = VecGetArrayReadAndMemType(Q_loc, (const PetscScalar **)&q, &q_mem_type);
10877841947SLeila Ghaffari   CHKERRQ(ierr);
10977841947SLeila Ghaffari   ierr = VecGetArrayAndMemType(G_loc, &g, &g_mem_type); CHKERRQ(ierr);
11077841947SLeila Ghaffari   CeedVectorSetArray(user->q_ceed, MemTypeP2C(q_mem_type), CEED_USE_POINTER, q);
11177841947SLeila Ghaffari   CeedVectorSetArray(user->g_ceed, MemTypeP2C(g_mem_type), CEED_USE_POINTER, g);
11277841947SLeila Ghaffari 
11377841947SLeila Ghaffari   // Apply CEED operator
11477841947SLeila Ghaffari   CeedOperatorApply(user->op_rhs, user->q_ceed, user->g_ceed,
11577841947SLeila Ghaffari                     CEED_REQUEST_IMMEDIATE);
11677841947SLeila Ghaffari 
11777841947SLeila Ghaffari   // Restore vectors
11877841947SLeila Ghaffari   CeedVectorTakeArray(user->q_ceed, MemTypeP2C(q_mem_type), NULL);
11977841947SLeila Ghaffari   CeedVectorTakeArray(user->g_ceed, MemTypeP2C(g_mem_type), NULL);
12077841947SLeila Ghaffari   ierr = VecRestoreArrayReadAndMemType(Q_loc, (const PetscScalar **)&q);
12177841947SLeila Ghaffari   CHKERRQ(ierr);
12277841947SLeila Ghaffari   ierr = VecRestoreArrayAndMemType(G_loc, &g); CHKERRQ(ierr);
12377841947SLeila Ghaffari 
12477841947SLeila Ghaffari   // Local-to-Global
12577841947SLeila Ghaffari   ierr = VecZeroEntries(G); CHKERRQ(ierr);
12677841947SLeila Ghaffari   ierr = DMLocalToGlobal(user->dm, G_loc, ADD_VALUES, G); CHKERRQ(ierr);
12777841947SLeila Ghaffari 
12877841947SLeila Ghaffari   // Inverse of the lumped mass matrix (M is Minv)
12977841947SLeila Ghaffari   ierr = VecPointwiseMult(G, G, user->M); CHKERRQ(ierr);
13077841947SLeila Ghaffari 
13177841947SLeila Ghaffari   // Restore vectors
13277841947SLeila Ghaffari   ierr = DMRestoreLocalVector(user->dm, &Q_loc); CHKERRQ(ierr);
13377841947SLeila Ghaffari   ierr = DMRestoreLocalVector(user->dm, &G_loc); CHKERRQ(ierr);
13477841947SLeila Ghaffari 
13577841947SLeila Ghaffari   PetscFunctionReturn(0);
13677841947SLeila Ghaffari }
13777841947SLeila Ghaffari 
13877841947SLeila Ghaffari // Implicit time-stepper function setup
13977841947SLeila Ghaffari PetscErrorCode IFunction_NS(TS ts, PetscReal t, Vec Q, Vec Q_dot, Vec G,
14077841947SLeila Ghaffari                             void *user_data) {
14177841947SLeila Ghaffari   User              user = *(User *)user_data;
14277841947SLeila Ghaffari   const PetscScalar *q, *q_dot;
14377841947SLeila Ghaffari   PetscScalar       *g;
14477841947SLeila Ghaffari   Vec               Q_loc, Q_dot_loc, G_loc;
14577841947SLeila Ghaffari   PetscMemType      q_mem_type, q_dot_mem_type, g_mem_type;
14677841947SLeila Ghaffari   PetscErrorCode    ierr;
14777841947SLeila Ghaffari   PetscFunctionBeginUser;
14877841947SLeila Ghaffari 
14977841947SLeila Ghaffari   // Update EulerContext
15077841947SLeila Ghaffari   if (user->phys->has_curr_time) user->phys->euler_ctx->curr_time = t;
15177841947SLeila Ghaffari 
15277841947SLeila Ghaffari   // Get local vectors
15377841947SLeila Ghaffari   ierr = DMGetLocalVector(user->dm, &Q_loc); CHKERRQ(ierr);
15477841947SLeila Ghaffari   ierr = DMGetLocalVector(user->dm, &Q_dot_loc); CHKERRQ(ierr);
15577841947SLeila Ghaffari   ierr = DMGetLocalVector(user->dm, &G_loc); CHKERRQ(ierr);
15677841947SLeila Ghaffari 
15777841947SLeila Ghaffari   // Global-to-local
15877841947SLeila Ghaffari   ierr = VecZeroEntries(Q_loc); CHKERRQ(ierr);
15977841947SLeila Ghaffari   ierr = DMGlobalToLocal(user->dm, Q, INSERT_VALUES, Q_loc); CHKERRQ(ierr);
16077841947SLeila Ghaffari   ierr = DMPlexInsertBoundaryValues(user->dm, PETSC_TRUE, Q_loc, 0.0,
16177841947SLeila Ghaffari                                     NULL, NULL, NULL); CHKERRQ(ierr);
16277841947SLeila Ghaffari   ierr = VecZeroEntries(Q_dot_loc); CHKERRQ(ierr);
16377841947SLeila Ghaffari   ierr = DMGlobalToLocal(user->dm, Q_dot, INSERT_VALUES, Q_dot_loc);
16477841947SLeila Ghaffari   CHKERRQ(ierr);
16577841947SLeila Ghaffari   ierr = VecZeroEntries(G_loc); CHKERRQ(ierr);
16677841947SLeila Ghaffari 
16777841947SLeila Ghaffari   // Place PETSc vectors in CEED vectors
16877841947SLeila Ghaffari   ierr = VecGetArrayReadAndMemType(Q_loc, &q, &q_mem_type); CHKERRQ(ierr);
16977841947SLeila Ghaffari   ierr = VecGetArrayReadAndMemType(Q_dot_loc, &q_dot, &q_dot_mem_type);
17077841947SLeila Ghaffari   CHKERRQ(ierr);
17177841947SLeila Ghaffari   ierr = VecGetArrayAndMemType(G_loc, &g, &g_mem_type); CHKERRQ(ierr);
17277841947SLeila Ghaffari   CeedVectorSetArray(user->q_ceed, MemTypeP2C(q_mem_type), CEED_USE_POINTER,
17377841947SLeila Ghaffari                      (PetscScalar *)q);
17477841947SLeila Ghaffari   CeedVectorSetArray(user->q_dot_ceed, MemTypeP2C(q_dot_mem_type),
175e6225c47SLeila Ghaffari                      CEED_USE_POINTER, (PetscScalar *)q_dot);
17677841947SLeila Ghaffari   CeedVectorSetArray(user->g_ceed, MemTypeP2C(g_mem_type), CEED_USE_POINTER, g);
17777841947SLeila Ghaffari 
17877841947SLeila Ghaffari   // Apply CEED operator
17977841947SLeila Ghaffari   CeedOperatorApply(user->op_ifunction, user->q_ceed, user->g_ceed,
18077841947SLeila Ghaffari                     CEED_REQUEST_IMMEDIATE);
18177841947SLeila Ghaffari 
18277841947SLeila Ghaffari   // Restore vectors
18377841947SLeila Ghaffari   CeedVectorTakeArray(user->q_ceed, MemTypeP2C(q_mem_type), NULL);
18477841947SLeila Ghaffari   CeedVectorTakeArray(user->q_dot_ceed, MemTypeP2C(q_dot_mem_type), NULL);
18577841947SLeila Ghaffari   CeedVectorTakeArray(user->g_ceed, MemTypeP2C(g_mem_type), NULL);
18677841947SLeila Ghaffari   ierr = VecRestoreArrayReadAndMemType(Q_loc, &q); CHKERRQ(ierr);
18777841947SLeila Ghaffari   ierr = VecRestoreArrayReadAndMemType(Q_dot_loc, &q_dot); CHKERRQ(ierr);
18877841947SLeila Ghaffari   ierr = VecRestoreArrayAndMemType(G_loc, &g); CHKERRQ(ierr);
18977841947SLeila Ghaffari 
19077841947SLeila Ghaffari   // Local-to-Global
19177841947SLeila Ghaffari   ierr = VecZeroEntries(G); CHKERRQ(ierr);
19277841947SLeila Ghaffari   ierr = DMLocalToGlobal(user->dm, G_loc, ADD_VALUES, G); CHKERRQ(ierr);
19377841947SLeila Ghaffari 
19477841947SLeila Ghaffari   // Restore vectors
19577841947SLeila Ghaffari   ierr = DMRestoreLocalVector(user->dm, &Q_loc); CHKERRQ(ierr);
19677841947SLeila Ghaffari   ierr = DMRestoreLocalVector(user->dm, &Q_dot_loc); CHKERRQ(ierr);
19777841947SLeila Ghaffari   ierr = DMRestoreLocalVector(user->dm, &G_loc); CHKERRQ(ierr);
19877841947SLeila Ghaffari 
19977841947SLeila Ghaffari   PetscFunctionReturn(0);
20077841947SLeila Ghaffari }
20177841947SLeila Ghaffari 
20277841947SLeila Ghaffari // User provided TS Monitor
20377841947SLeila Ghaffari PetscErrorCode TSMonitor_NS(TS ts, PetscInt step_no, PetscReal time,
20477841947SLeila Ghaffari                             Vec Q, void *ctx) {
20577841947SLeila Ghaffari   User           user = ctx;
20677841947SLeila Ghaffari   Vec            Q_loc;
20777841947SLeila Ghaffari   char           file_path[PETSC_MAX_PATH_LEN];
20877841947SLeila Ghaffari   PetscViewer    viewer;
20977841947SLeila Ghaffari   PetscErrorCode ierr;
21077841947SLeila Ghaffari   PetscFunctionBeginUser;
21177841947SLeila Ghaffari 
21277841947SLeila Ghaffari   // Print every 'output_freq' steps
21377841947SLeila Ghaffari   if (step_no % user->app_ctx->output_freq != 0)
21477841947SLeila Ghaffari     PetscFunctionReturn(0);
21577841947SLeila Ghaffari 
21677841947SLeila Ghaffari   // Set up output
21777841947SLeila Ghaffari   ierr = DMGetLocalVector(user->dm, &Q_loc); CHKERRQ(ierr);
21877841947SLeila Ghaffari   ierr = PetscObjectSetName((PetscObject)Q_loc, "StateVec"); CHKERRQ(ierr);
21977841947SLeila Ghaffari   ierr = VecZeroEntries(Q_loc); CHKERRQ(ierr);
22077841947SLeila Ghaffari   ierr = DMGlobalToLocal(user->dm, Q, INSERT_VALUES, Q_loc); CHKERRQ(ierr);
22177841947SLeila Ghaffari 
22277841947SLeila Ghaffari   // Output
22377841947SLeila Ghaffari   ierr = PetscSNPrintf(file_path, sizeof file_path, "%s/ns-%03D.vtu",
22477841947SLeila Ghaffari                        user->app_ctx->output_dir, step_no + user->app_ctx->cont_steps);
22577841947SLeila Ghaffari   CHKERRQ(ierr);
22677841947SLeila Ghaffari   ierr = PetscViewerVTKOpen(PetscObjectComm((PetscObject)Q), file_path,
22777841947SLeila Ghaffari                             FILE_MODE_WRITE, &viewer); CHKERRQ(ierr);
22877841947SLeila Ghaffari   ierr = VecView(Q_loc, viewer); CHKERRQ(ierr);
22977841947SLeila Ghaffari   ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
23077841947SLeila Ghaffari   if (user->dm_viz) {
23177841947SLeila Ghaffari     Vec         Q_refined, Q_refined_loc;
23277841947SLeila Ghaffari     char        file_path_refined[PETSC_MAX_PATH_LEN];
23377841947SLeila Ghaffari     PetscViewer viewer_refined;
23477841947SLeila Ghaffari 
23577841947SLeila Ghaffari     ierr = DMGetGlobalVector(user->dm_viz, &Q_refined); CHKERRQ(ierr);
23677841947SLeila Ghaffari     ierr = DMGetLocalVector(user->dm_viz, &Q_refined_loc); CHKERRQ(ierr);
23777841947SLeila Ghaffari     ierr = PetscObjectSetName((PetscObject)Q_refined_loc, "Refined");
23877841947SLeila Ghaffari     CHKERRQ(ierr);
23977841947SLeila Ghaffari     ierr = MatInterpolate(user->interp_viz, Q, Q_refined); CHKERRQ(ierr);
24077841947SLeila Ghaffari     ierr = VecZeroEntries(Q_refined_loc); CHKERRQ(ierr);
24177841947SLeila Ghaffari     ierr = DMGlobalToLocal(user->dm_viz, Q_refined, INSERT_VALUES, Q_refined_loc);
24277841947SLeila Ghaffari     CHKERRQ(ierr);
24377841947SLeila Ghaffari     ierr = PetscSNPrintf(file_path_refined, sizeof file_path_refined,
244e6225c47SLeila Ghaffari                          "%s/nsrefined-%03D.vtu", user->app_ctx->output_dir,
245e6225c47SLeila Ghaffari                          step_no + user->app_ctx->cont_steps);
24677841947SLeila Ghaffari     CHKERRQ(ierr);
24777841947SLeila Ghaffari     ierr = PetscViewerVTKOpen(PetscObjectComm((PetscObject)Q_refined),
248e6225c47SLeila Ghaffari                               file_path_refined, FILE_MODE_WRITE, &viewer_refined); CHKERRQ(ierr);
24977841947SLeila Ghaffari     ierr = VecView(Q_refined_loc, viewer_refined); CHKERRQ(ierr);
25077841947SLeila Ghaffari     ierr = DMRestoreLocalVector(user->dm_viz, &Q_refined_loc); CHKERRQ(ierr);
25177841947SLeila Ghaffari     ierr = DMRestoreGlobalVector(user->dm_viz, &Q_refined); CHKERRQ(ierr);
25277841947SLeila Ghaffari     ierr = PetscViewerDestroy(&viewer_refined); CHKERRQ(ierr);
25377841947SLeila Ghaffari   }
25477841947SLeila Ghaffari   ierr = DMRestoreLocalVector(user->dm, &Q_loc); CHKERRQ(ierr);
25577841947SLeila Ghaffari 
25677841947SLeila Ghaffari   // Save data in a binary file for continuation of simulations
25777841947SLeila Ghaffari   ierr = PetscSNPrintf(file_path, sizeof file_path, "%s/ns-solution.bin",
25877841947SLeila Ghaffari                        user->app_ctx->output_dir); CHKERRQ(ierr);
25977841947SLeila Ghaffari   ierr = PetscViewerBinaryOpen(user->comm, file_path, FILE_MODE_WRITE, &viewer);
26077841947SLeila Ghaffari   CHKERRQ(ierr);
26177841947SLeila Ghaffari   ierr = VecView(Q, viewer); CHKERRQ(ierr);
26277841947SLeila Ghaffari   ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
26377841947SLeila Ghaffari 
26477841947SLeila Ghaffari   // Save time stamp
26577841947SLeila Ghaffari   // Dimensionalize time back
26677841947SLeila Ghaffari   time /= user->units->second;
26777841947SLeila Ghaffari   ierr = PetscSNPrintf(file_path, sizeof file_path, "%s/ns-time.bin",
26877841947SLeila Ghaffari                        user->app_ctx->output_dir); CHKERRQ(ierr);
26977841947SLeila Ghaffari   ierr = PetscViewerBinaryOpen(user->comm, file_path, FILE_MODE_WRITE, &viewer);
27077841947SLeila Ghaffari   CHKERRQ(ierr);
27177841947SLeila Ghaffari   #if PETSC_VERSION_GE(3,13,0)
27277841947SLeila Ghaffari   ierr = PetscViewerBinaryWrite(viewer, &time, 1, PETSC_REAL);
27377841947SLeila Ghaffari   #else
27477841947SLeila Ghaffari   ierr = PetscViewerBinaryWrite(viewer, &time, 1, PETSC_REAL, true);
27577841947SLeila Ghaffari   #endif
27677841947SLeila Ghaffari   CHKERRQ(ierr);
27777841947SLeila Ghaffari   ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
27877841947SLeila Ghaffari 
27977841947SLeila Ghaffari   PetscFunctionReturn(0);
28077841947SLeila Ghaffari }
28177841947SLeila Ghaffari 
28277841947SLeila Ghaffari // TS: Create, setup, and solve
28377841947SLeila Ghaffari PetscErrorCode TSSolve_NS(DM dm, User user, AppCtx app_ctx, Physics phys,
28477841947SLeila Ghaffari                           Vec *Q, PetscScalar *f_time, TS *ts) {
28577841947SLeila Ghaffari   MPI_Comm       comm = user->comm;
28677841947SLeila Ghaffari   TSAdapt        adapt;
28777841947SLeila Ghaffari   PetscScalar    final_time;
28877841947SLeila Ghaffari   PetscErrorCode ierr;
28977841947SLeila Ghaffari   PetscFunctionBeginUser;
29077841947SLeila Ghaffari 
29177841947SLeila Ghaffari   ierr = TSCreate(comm, ts); CHKERRQ(ierr);
29277841947SLeila Ghaffari   ierr = TSSetDM(*ts, dm); CHKERRQ(ierr);
29377841947SLeila Ghaffari   if (phys->implicit) {
29477841947SLeila Ghaffari     ierr = TSSetType(*ts, TSBDF); CHKERRQ(ierr);
29577841947SLeila Ghaffari     if (user->op_ifunction) {
29677841947SLeila Ghaffari       ierr = TSSetIFunction(*ts, NULL, IFunction_NS, &user); CHKERRQ(ierr);
29777841947SLeila Ghaffari     } else { // Implicit integrators can fall back to using an RHSFunction
29877841947SLeila Ghaffari       ierr = TSSetRHSFunction(*ts, NULL, RHS_NS, &user); CHKERRQ(ierr);
29977841947SLeila Ghaffari     }
30077841947SLeila Ghaffari   } else {
30177841947SLeila Ghaffari     if (!user->op_rhs) SETERRQ(comm, PETSC_ERR_ARG_NULL,
30277841947SLeila Ghaffari                                  "Problem does not provide RHSFunction");
30377841947SLeila Ghaffari     ierr = TSSetType(*ts, TSRK); CHKERRQ(ierr);
30477841947SLeila Ghaffari     ierr = TSRKSetType(*ts, TSRK5F); CHKERRQ(ierr);
30577841947SLeila Ghaffari     ierr = TSSetRHSFunction(*ts, NULL, RHS_NS, &user); CHKERRQ(ierr);
30677841947SLeila Ghaffari   }
30777841947SLeila Ghaffari   ierr = TSSetMaxTime(*ts, 500. * user->units->second); CHKERRQ(ierr);
30877841947SLeila Ghaffari   ierr = TSSetExactFinalTime(*ts, TS_EXACTFINALTIME_STEPOVER); CHKERRQ(ierr);
30977841947SLeila Ghaffari   ierr = TSSetTimeStep(*ts, 1.e-2 * user->units->second); CHKERRQ(ierr);
31077841947SLeila Ghaffari   if (app_ctx->test_mode) {ierr = TSSetMaxSteps(*ts, 10); CHKERRQ(ierr);}
31177841947SLeila Ghaffari   ierr = TSGetAdapt(*ts, &adapt); CHKERRQ(ierr);
31277841947SLeila Ghaffari   ierr = TSAdaptSetStepLimits(adapt,
31377841947SLeila Ghaffari                               1.e-12 * user->units->second,
31477841947SLeila Ghaffari                               1.e2 * user->units->second); CHKERRQ(ierr);
31577841947SLeila Ghaffari   ierr = TSSetFromOptions(*ts); CHKERRQ(ierr);
31677841947SLeila Ghaffari   if (!app_ctx->cont_steps) { // print initial condition
31777841947SLeila Ghaffari     if (!app_ctx->test_mode) {
31877841947SLeila Ghaffari       ierr = TSMonitor_NS(*ts, 0, 0., *Q, user); CHKERRQ(ierr);
31977841947SLeila Ghaffari     }
32077841947SLeila Ghaffari   } else { // continue from time of last output
32177841947SLeila Ghaffari     PetscReal   time;
32277841947SLeila Ghaffari     PetscInt    count;
32377841947SLeila Ghaffari     PetscViewer viewer;
32477841947SLeila Ghaffari     char        file_path[PETSC_MAX_PATH_LEN];
32577841947SLeila Ghaffari     ierr = PetscSNPrintf(file_path, sizeof file_path, "%s/ns-time.bin",
32677841947SLeila Ghaffari                          app_ctx->output_dir); CHKERRQ(ierr);
32777841947SLeila Ghaffari     ierr = PetscViewerBinaryOpen(comm, file_path, FILE_MODE_READ, &viewer);
32877841947SLeila Ghaffari     CHKERRQ(ierr);
32977841947SLeila Ghaffari     ierr = PetscViewerBinaryRead(viewer, &time, 1, &count, PETSC_REAL);
33077841947SLeila Ghaffari     CHKERRQ(ierr);
33177841947SLeila Ghaffari     ierr = PetscViewerDestroy(&viewer); CHKERRQ(ierr);
33277841947SLeila Ghaffari     ierr = TSSetTime(*ts, time * user->units->second); CHKERRQ(ierr);
33377841947SLeila Ghaffari   }
33477841947SLeila Ghaffari   if (!app_ctx->test_mode) {
33577841947SLeila Ghaffari     ierr = TSMonitorSet(*ts, TSMonitor_NS, user, NULL); CHKERRQ(ierr);
33677841947SLeila Ghaffari   }
33777841947SLeila Ghaffari 
33877841947SLeila Ghaffari   // Solve
33977841947SLeila Ghaffari   double start, cpu_time_used;
34077841947SLeila Ghaffari   start = MPI_Wtime();
34177841947SLeila Ghaffari   ierr = PetscBarrier((PetscObject) *ts); CHKERRQ(ierr);
34277841947SLeila Ghaffari   ierr = TSSolve(*ts, *Q); CHKERRQ(ierr);
34377841947SLeila Ghaffari   cpu_time_used = MPI_Wtime() - start;
34477841947SLeila Ghaffari   ierr = TSGetSolveTime(*ts, &final_time); CHKERRQ(ierr);
34577841947SLeila Ghaffari   *f_time = final_time;
34677841947SLeila Ghaffari   ierr = MPI_Allreduce(MPI_IN_PLACE, &cpu_time_used, 1, MPI_DOUBLE, MPI_MIN,
34777841947SLeila Ghaffari                        comm); CHKERRQ(ierr);
34877841947SLeila Ghaffari   if (!app_ctx->test_mode) {
34977841947SLeila Ghaffari     ierr = PetscPrintf(PETSC_COMM_WORLD,
35077841947SLeila Ghaffari                        "Time taken for solution (sec): %g\n",
35177841947SLeila Ghaffari                        (double)cpu_time_used); CHKERRQ(ierr);
35277841947SLeila Ghaffari   }
35377841947SLeila Ghaffari   PetscFunctionReturn(0);
35477841947SLeila Ghaffari }
355