Date: 2025-03-29T05:58:51+00:00

Actual source code: ex1.c

      1: static char help[] = "Basic equation for generator stability analysis.\n";

      3: /*F

      5: \begin{eqnarray}
      6:                  \frac{2 H}{\omega_s}\frac{d \omega}{dt} & = & P_m - \frac{EV}{X} \sin(\theta) \\
      7:                  \frac{d \theta}{dt} = \omega - \omega_s
      8: \end{eqnarray}

     10: F*/

     12: /*
     13:    Include "petscts.h" so that we can use TS solvers.  Note that this
     14:    file automatically includes:
     15:      petscsys.h       - base PETSc routines   petscvec.h - vectors
     16:      petscmat.h - matrices
     17:      petscis.h     - index sets            petscksp.h - Krylov subspace methods
     18:      petscviewer.h - viewers               petscpc.h  - preconditioners
     19:      petscksp.h   - linear solvers
     20: */

     22: #include <petscts.h>

     24: typedef struct {
     25:   PetscScalar H, omega_s, E, V, X;
     26:   PetscRandom rand;
     27: } AppCtx;

     29: /*
     30:      Defines the ODE passed to the ODE solver
     31: */
     32: static PetscErrorCode IFunction(TS ts, PetscReal t, Vec U, Vec Udot, Vec F, AppCtx *ctx)
     33: {
     34:   PetscScalar       *f, r;
     35:   const PetscScalar *u, *udot;
     36:   static PetscScalar R = .4;

     38:   PetscFunctionBegin;
     39:   PetscCall(PetscRandomGetValue(ctx->rand, &r));
     40:   if (r > .9) R = .5;
     41:   if (r < .1) R = .4;
     42:   R = .4;
     43:   /*  The next three lines allow us to access the entries of the vectors directly */
     44:   PetscCall(VecGetArrayRead(U, &u));
     45:   PetscCall(VecGetArrayRead(Udot, &udot));
     46:   PetscCall(VecGetArray(F, &f));
     47:   f[0] = 2.0 * ctx->H * udot[0] / ctx->omega_s + ctx->E * ctx->V * PetscSinScalar(u[1]) / ctx->X - R;
     48:   f[1] = udot[1] - u[0] + ctx->omega_s;

     50:   PetscCall(VecRestoreArrayRead(U, &u));
     51:   PetscCall(VecRestoreArrayRead(Udot, &udot));
     52:   PetscCall(VecRestoreArray(F, &f));
     53:   PetscFunctionReturn(PETSC_SUCCESS);
     54: }

     56: /*
     57:      Defines the Jacobian of the ODE passed to the ODE solver. See TSSetIJacobian() for the meaning of a and the Jacobian.
     58: */
     59: static PetscErrorCode IJacobian(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal a, Mat A, Mat B, AppCtx *ctx)
     60: {
     61:   PetscInt           rowcol[] = {0, 1};
     62:   PetscScalar        J[2][2];
     63:   const PetscScalar *u, *udot;

     65:   PetscFunctionBegin;
     66:   PetscCall(VecGetArrayRead(U, &u));
     67:   PetscCall(VecGetArrayRead(Udot, &udot));
     68:   J[0][0] = 2.0 * ctx->H * a / ctx->omega_s;
     69:   J[0][1] = -ctx->E * ctx->V * PetscCosScalar(u[1]) / ctx->X;
     70:   J[1][0] = -1.0;
     71:   J[1][1] = a;
     72:   PetscCall(MatSetValues(B, 2, rowcol, 2, rowcol, &J[0][0], INSERT_VALUES));
     73:   PetscCall(VecRestoreArrayRead(U, &u));
     74:   PetscCall(VecRestoreArrayRead(Udot, &udot));

     76:   PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
     77:   PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
     78:   if (A != B) {
     79:     PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
     80:     PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
     81:   }
     82:   PetscFunctionReturn(PETSC_SUCCESS);
     83: }

     85: int main(int argc, char **argv)
     86: {
     87:   TS           ts; /* ODE integrator */
     88:   Vec          U;  /* solution will be stored here */
     89:   Mat          A;  /* Jacobian matrix */
     90:   PetscMPIInt  size;
     91:   PetscInt     n = 2;
     92:   AppCtx       ctx;
     93:   PetscScalar *u;

     95:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     96:      Initialize program
     97:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     98:   PetscFunctionBeginUser;
     99:   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
    100:   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
    101:   PetscCheck(size == 1, PETSC_COMM_WORLD, PETSC_ERR_WRONG_MPI_SIZE, "Only for sequential runs");

    103:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    104:     Create necessary matrix and vectors
    105:     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    106:   PetscCall(MatCreate(PETSC_COMM_WORLD, &A));
    107:   PetscCall(MatSetSizes(A, n, n, PETSC_DETERMINE, PETSC_DETERMINE));
    108:   PetscCall(MatSetFromOptions(A));
    109:   PetscCall(MatSetUp(A));

    111:   PetscCall(MatCreateVecs(A, &U, NULL));

    113:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    114:     Set runtime options
    115:     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    116:   PetscOptionsBegin(PETSC_COMM_WORLD, NULL, "Reaction options", "");
    117:   {
    118:     ctx.omega_s = 1.0;
    119:     PetscCall(PetscOptionsScalar("-omega_s", "", "", ctx.omega_s, &ctx.omega_s, NULL));
    120:     ctx.H = 1.0;
    121:     PetscCall(PetscOptionsScalar("-H", "", "", ctx.H, &ctx.H, NULL));
    122:     ctx.E = 1.0;
    123:     PetscCall(PetscOptionsScalar("-E", "", "", ctx.E, &ctx.E, NULL));
    124:     ctx.V = 1.0;
    125:     PetscCall(PetscOptionsScalar("-V", "", "", ctx.V, &ctx.V, NULL));
    126:     ctx.X = 1.0;
    127:     PetscCall(PetscOptionsScalar("-X", "", "", ctx.X, &ctx.X, NULL));

    129:     PetscCall(VecGetArray(U, &u));
    130:     u[0] = 1;
    131:     u[1] = .7;
    132:     PetscCall(VecRestoreArray(U, &u));
    133:     PetscCall(PetscOptionsGetVec(NULL, NULL, "-initial", U, NULL));
    134:   }
    135:   PetscOptionsEnd();

    137:   PetscCall(PetscRandomCreate(PETSC_COMM_WORLD, &ctx.rand));
    138:   PetscCall(PetscRandomSetFromOptions(ctx.rand));

    140:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    141:      Create timestepping solver context
    142:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    143:   PetscCall(TSCreate(PETSC_COMM_WORLD, &ts));
    144:   PetscCall(TSSetProblemType(ts, TS_NONLINEAR));
    145:   PetscCall(TSSetType(ts, TSROSW));
    146:   PetscCall(TSSetIFunction(ts, NULL, (TSIFunctionFn *)IFunction, &ctx));
    147:   PetscCall(TSSetIJacobian(ts, A, A, (TSIJacobianFn *)IJacobian, &ctx));

    149:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    150:      Set initial conditions
    151:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    152:   PetscCall(TSSetSolution(ts, U));

    154:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    155:      Set solver options
    156:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    157:   PetscCall(TSSetMaxTime(ts, 2000.0));
    158:   PetscCall(TSSetExactFinalTime(ts, TS_EXACTFINALTIME_MATCHSTEP));
    159:   PetscCall(TSSetTimeStep(ts, .001));
    160:   PetscCall(TSSetFromOptions(ts));

    162:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    163:      Solve nonlinear system
    164:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    165:   PetscCall(TSSolve(ts, U));

    167:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    168:      Free work space.  All PETSc objects should be destroyed when they are no longer needed.
    169:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
    170:   PetscCall(MatDestroy(&A));
    171:   PetscCall(VecDestroy(&U));
    172:   PetscCall(TSDestroy(&ts));
    173:   PetscCall(PetscRandomDestroy(&ctx.rand));
    174:   PetscCall(PetscFinalize());
    175:   return 0;
    176: }

    178: /*TEST

    180:    build:
    181:      requires: !complex !single

    183:    test:
    184:       args: -ksp_gmres_cgs_refinement_type refine_always -snes_type newtonls -ts_max_steps 10

    186:    test:
    187:       suffix: 2
    188:       args: -ts_max_steps 10

    190: TEST*/