#define c11 1.0 #define c12 0 #define c21 2.0 #define c22 1.0 static char help[] = "Solves the van der Pol equation.\n\ Input parameters include:\n"; /* Concepts: TS^forward sensitivity analysis for time-dependent nonlinear problems Concepts: TS^van der Pol equation DAE equivalent Processors: 1 */ /* ------------------------------------------------------------------------ This code demonstrates how to compute trajectory sensitivties w.r.t. the stiffness parameter mu. 1) Use two vectors s and sp for sensitivities w.r.t. intial values and paraeters respectively. This case requires the original Jacobian matrix and a JacobianP matrix for the only parameter mu. 2) Consider the intial values to be parameters as well. Then there are three parameters in total. The JacobianP matrix will be combined matrix of the Jacobian matrix and JacobianP matrix in the previous case. This choice can be selected by using command line option '-combined' ------------------------------------------------------------------------- */ #include #include typedef struct _n_User *User; struct _n_User { PetscReal mu; PetscReal next_output; PetscBool combined; /* Sensitivity analysis support */ PetscInt steps; PetscReal ftime; Mat Jac; /* Jacobian matrix */ Mat Jacp; /* JacobianP matrix */ Vec x; Mat sp; /* forward sensitivity variables */ }; /* * User-defined routines */ static PetscErrorCode IFunction(TS ts,PetscReal t,Vec X,Vec Xdot,Vec F,void *ctx) { PetscErrorCode ierr; User user = (User)ctx; const PetscScalar *x,*xdot; PetscScalar *f; PetscFunctionBeginUser; ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); ierr = VecGetArrayRead(Xdot,&xdot);CHKERRQ(ierr); ierr = VecGetArray(F,&f);CHKERRQ(ierr); f[0] = xdot[0] - x[1]; f[1] = c21*(xdot[0]-x[1]) + xdot[1] - user->mu*((1.0-x[0]*x[0])*x[1] - x[0]) ; ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); ierr = VecRestoreArrayRead(Xdot,&xdot);CHKERRQ(ierr); ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); PetscFunctionReturn(0); } static PetscErrorCode IJacobian(TS ts,PetscReal t,Vec X,Vec Xdot,PetscReal a,Mat A,Mat B,void *ctx) { PetscErrorCode ierr; User user = (User)ctx; PetscInt rowcol[] = {0,1}; PetscScalar J[2][2]; const PetscScalar *x; PetscFunctionBeginUser; ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); J[0][0] = a; J[0][1] = -1.0; J[1][0] = c21*a + user->mu*(1.0 + 2.0*x[0]*x[1]); J[1][1] = -c21 + a - user->mu*(1.0-x[0]*x[0]); ierr = MatSetValues(B,2,rowcol,2,rowcol,&J[0][0],INSERT_VALUES);CHKERRQ(ierr); ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); if (A != B) { ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); } PetscFunctionReturn(0); } static PetscErrorCode RHSJacobianP(TS ts,PetscReal t,Vec X,Mat A,void *ctx) { User user = (User)ctx; PetscInt row[] = {0,1},col[]={0}; PetscScalar J[2][1]; const PetscScalar *x; PetscErrorCode ierr; PetscFunctionBeginUser; if (user->combined) col[0] = 2; ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); J[0][0] = 0; J[1][0] = (1.-x[0]*x[0])*x[1]-x[0]; ierr = MatSetValues(A,2,row,1,col,&J[0][0],INSERT_VALUES);CHKERRQ(ierr); ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); PetscFunctionReturn(0); } /* Monitor timesteps and use interpolation to output at integer multiples of 0.1 */ static PetscErrorCode Monitor(TS ts,PetscInt step,PetscReal t,Vec X,void *ctx) { PetscErrorCode ierr; const PetscScalar *x; PetscReal tfinal, dt; User user = (User)ctx; Vec interpolatedX; PetscFunctionBeginUser; ierr = TSGetTimeStep(ts,&dt);CHKERRQ(ierr); ierr = TSGetMaxTime(ts,&tfinal);CHKERRQ(ierr); while (user->next_output <= t && user->next_output <= tfinal) { ierr = VecDuplicate(X,&interpolatedX);CHKERRQ(ierr); ierr = TSInterpolate(ts,user->next_output,interpolatedX);CHKERRQ(ierr); ierr = VecGetArrayRead(interpolatedX,&x);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"[%.1f] %D TS %.6f (dt = %.6f) X % 12.6e % 12.6e\n", user->next_output,step,(double)t,(double)dt,(double)PetscRealPart(x[0]), (double)PetscRealPart(x[1]));CHKERRQ(ierr); ierr = VecRestoreArrayRead(interpolatedX,&x);CHKERRQ(ierr); ierr = VecDestroy(&interpolatedX);CHKERRQ(ierr); user->next_output += 0.1; } PetscFunctionReturn(0); } int main(int argc,char **argv) { TS ts; PetscBool monitor = PETSC_FALSE; PetscScalar *x_ptr; PetscMPIInt size; struct _n_User user; PetscInt rows,cols; PetscErrorCode ierr; /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Initialize program - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = PetscInitialize(&argc,&argv,NULL,help);if (ierr) return ierr; ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRQ(ierr); if (size != 1) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_WRONG_MPI_SIZE,"This is a uniprocessor example only!"); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Set runtime options - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ user.next_output = 0.0; user.mu = 1.0e6; user.steps = 0; user.ftime = 0.5; user.combined = PETSC_FALSE; ierr = PetscOptionsGetBool(NULL,NULL,"-monitor",&monitor,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetReal(NULL,NULL,"-mu",&user.mu,NULL);CHKERRQ(ierr); ierr = PetscOptionsGetBool(NULL,NULL,"-combined",&user.combined,NULL);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create necessary matrix and vectors, solve same ODE on every process - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ rows = 2; cols = user.combined ? 3 : 1; ierr = MatCreate(PETSC_COMM_WORLD,&user.Jac);CHKERRQ(ierr); ierr = MatSetSizes(user.Jac,PETSC_DECIDE,PETSC_DECIDE,2,2);CHKERRQ(ierr); ierr = MatSetFromOptions(user.Jac);CHKERRQ(ierr); ierr = MatSetUp(user.Jac);CHKERRQ(ierr); ierr = MatCreateVecs(user.Jac,&user.x,NULL);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create timestepping solver context - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = TSCreate(PETSC_COMM_WORLD,&ts);CHKERRQ(ierr); ierr = TSSetType(ts,TSBEULER);CHKERRQ(ierr); ierr = TSSetIFunction(ts,NULL,IFunction,&user);CHKERRQ(ierr); ierr = TSSetIJacobian(ts,user.Jac,user.Jac,IJacobian,&user);CHKERRQ(ierr); ierr = TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP);CHKERRQ(ierr); ierr = TSSetMaxTime(ts,user.ftime);CHKERRQ(ierr); if (monitor) { ierr = TSMonitorSet(ts,Monitor,&user,NULL);CHKERRQ(ierr); } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Set initial conditions - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = VecGetArray(user.x,&x_ptr);CHKERRQ(ierr); x_ptr[0] = 2.0; x_ptr[1] = -0.66666654321; ierr = VecRestoreArray(user.x,&x_ptr);CHKERRQ(ierr); ierr = TSSetTimeStep(ts,1.0/1024.0);CHKERRQ(ierr); /* Set up forward sensitivity */ ierr = MatCreate(PETSC_COMM_WORLD,&user.Jacp);CHKERRQ(ierr); ierr = MatSetSizes(user.Jacp,PETSC_DECIDE,PETSC_DECIDE,rows,cols);CHKERRQ(ierr); ierr = MatSetFromOptions(user.Jacp);CHKERRQ(ierr); ierr = MatSetUp(user.Jacp);CHKERRQ(ierr); ierr = MatCreateDense(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,rows,cols,NULL,&user.sp);CHKERRQ(ierr); if (user.combined) { ierr = MatZeroEntries(user.sp);CHKERRQ(ierr); ierr = MatShift(user.sp,1.0);CHKERRQ(ierr); } else { ierr = MatZeroEntries(user.sp);CHKERRQ(ierr); } ierr = TSForwardSetSensitivities(ts,cols,user.sp);CHKERRQ(ierr); ierr = TSSetRHSJacobianP(ts,user.Jacp,RHSJacobianP,&user);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Set runtime options - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = TSSetFromOptions(ts);CHKERRQ(ierr); ierr = TSSolve(ts,user.x);CHKERRQ(ierr); ierr = TSGetSolveTime(ts,&user.ftime);CHKERRQ(ierr); ierr = TSGetStepNumber(ts,&user.steps);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"mu %g, steps %D, ftime %g\n",(double)user.mu,user.steps,(double)user.ftime);CHKERRQ(ierr); ierr = PetscPrintf(PETSC_COMM_WORLD,"\n ode solution \n");CHKERRQ(ierr); ierr = VecView(user.x,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); if (user.combined) { ierr = PetscPrintf(PETSC_COMM_WORLD,"\n forward sensitivity: d[y(tf) z(tf)]/d[y0 z0 mu]\n");CHKERRQ(ierr); } else { ierr = PetscPrintf(PETSC_COMM_WORLD,"\n forward sensitivity: d[y(tf) z(tf)]/d[mu]\n");CHKERRQ(ierr); } ierr = MatView(user.sp,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Free work space. All PETSc objects should be destroyed when they are no longer needed. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ ierr = MatDestroy(&user.Jac);CHKERRQ(ierr); ierr = MatDestroy(&user.sp);CHKERRQ(ierr); ierr = MatDestroy(&user.Jacp);CHKERRQ(ierr); ierr = VecDestroy(&user.x);CHKERRQ(ierr); ierr = TSDestroy(&ts);CHKERRQ(ierr); ierr = PetscFinalize(); return(ierr); } /*TEST test: args: -monitor 0 -ts_type theta -ts_theta_endpoint -ts_theta_theta 0.5 -combined requires: !complex !single test: suffix: 2 requires: !complex !single args: -monitor 0 -ts_type theta -ts_theta_endpoint -ts_theta_theta 0.5 TEST*/