1 static char help[] = "Parallel bouncing ball example formulated as a second-order system to test TS event feature.\n"; 2 3 /* 4 The dynamics of the bouncing ball with drag coefficient Cd is described by the ODE 5 6 u_tt = -9.8 - 1/2 Cd (u_t)^2 sign(u_t) 7 8 There are two events set in this example. The first one checks for the ball hitting the 9 ground (u = 0). Every time the ball hits the ground, its velocity u_t is attenuated by 10 a restitution coefficient Cr. The second event sets a limit on the number of ball bounces. 11 */ 12 13 #include <petscts.h> 14 15 typedef struct { 16 PetscReal Cd; /* drag coefficient */ 17 PetscReal Cr; /* restitution coefficient */ 18 PetscInt bounces; 19 PetscInt maxbounces; 20 } AppCtx; 21 22 static PetscErrorCode Event(TS ts,PetscReal t,Vec U,PetscScalar *fvalue,void *ctx) 23 { 24 AppCtx *app = (AppCtx*)ctx; 25 Vec V; 26 const PetscScalar *u,*v; 27 28 PetscFunctionBegin; 29 /* Event for ball height */ 30 PetscCall(TS2GetSolution(ts,&U,&V)); 31 PetscCall(VecGetArrayRead(U,&u)); 32 PetscCall(VecGetArrayRead(V,&v)); 33 fvalue[0] = u[0]; 34 /* Event for number of bounces */ 35 fvalue[1] = app->maxbounces - app->bounces; 36 PetscCall(VecRestoreArrayRead(U,&u)); 37 PetscCall(VecRestoreArrayRead(V,&v)); 38 PetscFunctionReturn(0); 39 } 40 41 static PetscErrorCode PostEvent(TS ts,PetscInt nevents,PetscInt event_list[],PetscReal t,Vec U,PetscBool forwardsolve,void* ctx) 42 { 43 AppCtx *app = (AppCtx*)ctx; 44 Vec V; 45 PetscScalar *u,*v; 46 PetscMPIInt rank; 47 48 PetscFunctionBegin; 49 if (!nevents) PetscFunctionReturn(0); 50 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank)); 51 if (event_list[0] == 0) { 52 PetscCall(PetscPrintf(PETSC_COMM_SELF,"Processor [%d]: Ball hit the ground at t = %5.2f seconds\n",rank,(double)t)); 53 /* Set new initial conditions with .9 attenuation */ 54 PetscCall(TS2GetSolution(ts,&U,&V)); 55 PetscCall(VecGetArray(U,&u)); 56 PetscCall(VecGetArray(V,&v)); 57 u[0] = 0.0; v[0] = -app->Cr*v[0]; 58 PetscCall(VecRestoreArray(U,&u)); 59 PetscCall(VecRestoreArray(V,&v)); 60 app->bounces++; 61 } else if (event_list[0] == 1) { 62 PetscCall(PetscPrintf(PETSC_COMM_SELF,"Processor [%d]: Ball bounced %" PetscInt_FMT " times\n",rank,app->bounces)); 63 } 64 PetscFunctionReturn(0); 65 } 66 67 static PetscErrorCode I2Function(TS ts,PetscReal t,Vec U,Vec V,Vec A,Vec F,void *ctx) 68 { 69 AppCtx *app = (AppCtx*)ctx; 70 const PetscScalar *u,*v,*a; 71 PetscScalar Res,*f; 72 73 PetscFunctionBegin; 74 PetscCall(VecGetArrayRead(U,&u)); 75 PetscCall(VecGetArrayRead(V,&v)); 76 PetscCall(VecGetArrayRead(A,&a)); 77 Res = a[0] + 9.8 + 0.5 * app->Cd * v[0]*v[0] * PetscSignReal(PetscRealPart(v[0])); 78 PetscCall(VecRestoreArrayRead(U,&u)); 79 PetscCall(VecRestoreArrayRead(V,&v)); 80 PetscCall(VecRestoreArrayRead(A,&a)); 81 82 PetscCall(VecGetArray(F,&f)); 83 f[0] = Res; 84 PetscCall(VecRestoreArray(F,&f)); 85 PetscFunctionReturn(0); 86 } 87 88 static PetscErrorCode I2Jacobian(TS ts,PetscReal t,Vec U,Vec V,Vec A,PetscReal shiftV,PetscReal shiftA,Mat J,Mat P,void *ctx) 89 { 90 AppCtx *app = (AppCtx*)ctx; 91 const PetscScalar *u,*v,*a; 92 PetscInt i; 93 PetscScalar Jac; 94 95 PetscFunctionBegin; 96 PetscCall(VecGetArrayRead(U,&u)); 97 PetscCall(VecGetArrayRead(V,&v)); 98 PetscCall(VecGetArrayRead(A,&a)); 99 Jac = shiftA + shiftV * app->Cd * v[0]; 100 PetscCall(VecRestoreArrayRead(U,&u)); 101 PetscCall(VecRestoreArrayRead(V,&v)); 102 PetscCall(VecRestoreArrayRead(A,&a)); 103 104 PetscCall(MatGetOwnershipRange(P,&i,NULL)); 105 PetscCall(MatSetValue(P,i,i,Jac,INSERT_VALUES)); 106 PetscCall(MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY)); 107 PetscCall(MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY)); 108 if (J != P) { 109 PetscCall(MatAssemblyBegin(P,MAT_FINAL_ASSEMBLY)); 110 PetscCall(MatAssemblyEnd(P,MAT_FINAL_ASSEMBLY)); 111 } 112 PetscFunctionReturn(0); 113 } 114 115 int main(int argc,char **argv) 116 { 117 TS ts; /* ODE integrator */ 118 Vec U,V; /* solution will be stored here */ 119 Vec F; /* residual vector */ 120 Mat J; /* Jacobian matrix */ 121 PetscMPIInt rank; 122 PetscScalar *u,*v; 123 AppCtx app; 124 PetscInt direction[2]; 125 PetscBool terminate[2]; 126 TSAdapt adapt; 127 128 PetscCall(PetscInitialize(&argc,&argv,NULL,help)); 129 PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank)); 130 131 app.Cd = 0.0; 132 app.Cr = 0.9; 133 app.bounces = 0; 134 app.maxbounces = 10; 135 PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"ex44 options",""); 136 PetscCall(PetscOptionsReal("-Cd","Drag coefficient","",app.Cd,&app.Cd,NULL)); 137 PetscCall(PetscOptionsReal("-Cr","Restitution coefficient","",app.Cr,&app.Cr,NULL)); 138 PetscCall(PetscOptionsInt("-maxbounces","Maximum number of bounces","",app.maxbounces,&app.maxbounces,NULL)); 139 PetscOptionsEnd(); 140 141 PetscCall(TSCreate(PETSC_COMM_WORLD,&ts)); 142 /*PetscCall(TSSetSaveTrajectory(ts));*/ 143 PetscCall(TSSetProblemType(ts,TS_NONLINEAR)); 144 PetscCall(TSSetType(ts,TSALPHA2)); 145 146 PetscCall(TSSetMaxTime(ts,PETSC_INFINITY)); 147 PetscCall(TSSetTimeStep(ts,0.1)); 148 PetscCall(TSSetExactFinalTime(ts,TS_EXACTFINALTIME_STEPOVER)); 149 PetscCall(TSGetAdapt(ts,&adapt)); 150 PetscCall(TSAdaptSetStepLimits(adapt,0.0,0.5)); 151 152 direction[0] = -1; terminate[0] = PETSC_FALSE; 153 direction[1] = -1; terminate[1] = PETSC_TRUE; 154 PetscCall(TSSetEventHandler(ts,2,direction,terminate,Event,PostEvent,&app)); 155 156 PetscCall(MatCreateAIJ(PETSC_COMM_WORLD,1,1,PETSC_DECIDE,PETSC_DECIDE,1,NULL,0,NULL,&J)); 157 PetscCall(MatSetFromOptions(J)); 158 PetscCall(MatSetUp(J)); 159 PetscCall(MatCreateVecs(J,NULL,&F)); 160 PetscCall(TSSetI2Function(ts,F,I2Function,&app)); 161 PetscCall(TSSetI2Jacobian(ts,J,J,I2Jacobian,&app)); 162 PetscCall(VecDestroy(&F)); 163 PetscCall(MatDestroy(&J)); 164 165 PetscCall(TSGetI2Jacobian(ts,&J,NULL,NULL,NULL)); 166 PetscCall(MatCreateVecs(J,&U,NULL)); 167 PetscCall(MatCreateVecs(J,&V,NULL)); 168 PetscCall(VecGetArray(U,&u)); 169 PetscCall(VecGetArray(V,&v)); 170 u[0] = 5.0*rank; v[0] = 20.0; 171 PetscCall(VecRestoreArray(U,&u)); 172 PetscCall(VecRestoreArray(V,&v)); 173 174 PetscCall(TS2SetSolution(ts,U,V)); 175 PetscCall(TSSetFromOptions(ts)); 176 PetscCall(TSSolve(ts,NULL)); 177 178 PetscCall(VecDestroy(&U)); 179 PetscCall(VecDestroy(&V)); 180 PetscCall(TSDestroy(&ts)); 181 182 PetscCall(PetscFinalize()); 183 return 0; 184 } 185 186 /*TEST 187 188 test: 189 suffix: a 190 args: -ts_alpha_radius {{1.0 0.5}} 191 output_file: output/ex44.out 192 193 test: 194 suffix: b 195 args: -ts_rtol 0 -ts_atol 1e-1 -ts_adapt_type basic 196 output_file: output/ex44.out 197 198 test: 199 suffix: 2 200 nsize: 2 201 args: -ts_rtol 0 -ts_atol 1e-1 -ts_adapt_type basic 202 output_file: output/ex44_2.out 203 filter: sort -b 204 filter_output: sort -b 205 206 test: 207 requires: !single 208 args: -ts_dt 0.25 -ts_adapt_type basic -ts_adapt_wnormtype INFINITY -ts_adapt_monitor 209 args: -ts_max_steps 1 -ts_max_reject {{0 1 2}separate_output} -ts_error_if_step_fails false 210 211 TEST*/ 212