1c4762a1bSJed Brown static const char help[] = "Integrate chemistry using TChem.\n"; 2c4762a1bSJed Brown 3c4762a1bSJed Brown #include <petscts.h> 4c4762a1bSJed Brown #include <petscdmda.h> 5c4762a1bSJed Brown 6c4762a1bSJed Brown #if defined(PETSC_HAVE_TCHEM) 7c4762a1bSJed Brown #if defined(MAX) 8c4762a1bSJed Brown #undef MAX 9c4762a1bSJed Brown #endif 10c4762a1bSJed Brown #if defined(MIN) 11c4762a1bSJed Brown #undef MIN 12c4762a1bSJed Brown #endif 13c4762a1bSJed Brown # include <TC_params.h> 14c4762a1bSJed Brown # include <TC_interface.h> 15c4762a1bSJed Brown #else 16c4762a1bSJed Brown # error TChem is required for this example. Reconfigure PETSc using --download-tchem. 17c4762a1bSJed Brown #endif 18c4762a1bSJed Brown /* 19c4762a1bSJed Brown 20c4762a1bSJed Brown This is an extension of extchem.c to solve the reaction equations independently in each cell of a one dimensional field 21c4762a1bSJed Brown 22c4762a1bSJed Brown Obtain the three files into this directory 23c4762a1bSJed Brown 24c4762a1bSJed Brown curl http://combustion.berkeley.edu/gri_mech/version30/files30/grimech30.dat > chem.inp 25c4762a1bSJed Brown curl http://combustion.berkeley.edu/gri_mech/version30/files30/thermo30.dat > therm.dat 26c4762a1bSJed Brown cp $PETSC_DIR/$PETSC_ARCH/externalpackages/tchem/data/periodictable.dat . 27c4762a1bSJed Brown 28c4762a1bSJed Brown Run with 29c4762a1bSJed Brown ./extchemfield -ts_arkimex_fully_implicit -ts_max_snes_failures -1 -ts_adapt_monitor -ts_adapt_dt_max 1e-4 -ts_arkimex_type 4 -ts_max_time .005 30c4762a1bSJed Brown 31c4762a1bSJed Brown Options for visualizing the solution: 32c4762a1bSJed Brown Watch certain variables in each cell evolve with time 33c4762a1bSJed Brown -draw_solution 1 -ts_monitor_lg_solution_variables Temp,H2,O2,H2O,CH4,CO,CO2,C2H2,N2 -lg_use_markers false -draw_pause -2 34c4762a1bSJed Brown 35c4762a1bSJed Brown Watch certain variables in all cells evolve with time 36c4762a1bSJed Brown -da_refine 4 -ts_monitor_draw_solution -draw_fields_by_name Temp,H2 -draw_vec_mark_points -draw_pause -2 37c4762a1bSJed Brown 38c4762a1bSJed Brown Keep the initial temperature distribution as one monitors the current temperature distribution 39c4762a1bSJed Brown -ts_monitor_draw_solution_initial -draw_bounds .9,1.7 -draw_fields_by_name Temp 40c4762a1bSJed Brown 41c4762a1bSJed Brown Save the images in a .gif (movie) file 42c4762a1bSJed Brown -draw_save -draw_save_single_file 43c4762a1bSJed Brown 44a5b23f4aSJose E. Roman Compute the sensitivies of the solution of the first temperature on the initial conditions 45c4762a1bSJed Brown -ts_adjoint_solve -ts_dt 1.e-5 -ts_type cn -ts_adjoint_view_solution draw 46c4762a1bSJed Brown 47c4762a1bSJed Brown Turn off diffusion 48c4762a1bSJed Brown -diffusion no 49c4762a1bSJed Brown 50c4762a1bSJed Brown Turn off reactions 51c4762a1bSJed Brown -reactions no 52c4762a1bSJed Brown 53c4762a1bSJed Brown The solution for component i = 0 is the temperature. 54c4762a1bSJed Brown 55c4762a1bSJed Brown The solution, i > 0, is the mass fraction, massf[i], of species i, i.e. mass of species i/ total mass of all species 56c4762a1bSJed Brown 57c4762a1bSJed Brown The mole fraction molef[i], i > 0, is the number of moles of a species/ total number of moles of all species 58c4762a1bSJed Brown Define M[i] = mass per mole of species i then 59c4762a1bSJed Brown molef[i] = massf[i]/(M[i]*(sum_j massf[j]/M[j])) 60c4762a1bSJed Brown 61c4762a1bSJed Brown FormMoleFraction(User,massf,molef) converts the mass fraction solution of each species to the mole fraction of each species. 62c4762a1bSJed Brown 63c4762a1bSJed Brown */ 64c4762a1bSJed Brown typedef struct _User *User; 65c4762a1bSJed Brown struct _User { 66c4762a1bSJed Brown PetscReal pressure; 67c4762a1bSJed Brown int Nspec; 68c4762a1bSJed Brown int Nreac; 69c4762a1bSJed Brown PetscReal Tini,dx; 70c4762a1bSJed Brown PetscReal diffus; 71c4762a1bSJed Brown DM dm; 72c4762a1bSJed Brown PetscBool diffusion,reactions; 73c4762a1bSJed Brown double *tchemwork; 74c4762a1bSJed Brown double *Jdense; /* Dense array workspace where Tchem computes the Jacobian */ 75c4762a1bSJed Brown PetscInt *rows; 76c4762a1bSJed Brown }; 77c4762a1bSJed Brown 78c4762a1bSJed Brown static PetscErrorCode MonitorCell(TS,User,PetscInt); 79c4762a1bSJed Brown static PetscErrorCode FormRHSFunction(TS,PetscReal,Vec,Vec,void*); 80c4762a1bSJed Brown static PetscErrorCode FormRHSJacobian(TS,PetscReal,Vec,Mat,Mat,void*); 81c4762a1bSJed Brown static PetscErrorCode FormInitialSolution(TS,Vec,void*); 82c4762a1bSJed Brown 833c633725SBarry Smith #define CHKERRTC(ierr) do {PetscCheck(!ierr,PETSC_COMM_SELF,PETSC_ERR_LIB,"Error in TChem library, return code %d",ierr);} while (0) 84c4762a1bSJed Brown 85c4762a1bSJed Brown int main(int argc,char **argv) 86c4762a1bSJed Brown { 87c4762a1bSJed Brown TS ts; /* time integrator */ 88c4762a1bSJed Brown TSAdapt adapt; 89c4762a1bSJed Brown Vec X; /* solution vector */ 90c4762a1bSJed Brown Mat J; /* Jacobian matrix */ 91c4762a1bSJed Brown PetscInt steps,ncells,xs,xm,i; 92c4762a1bSJed Brown PetscErrorCode ierr; 93c4762a1bSJed Brown PetscReal ftime,dt; 94c4762a1bSJed Brown char chemfile[PETSC_MAX_PATH_LEN] = "chem.inp",thermofile[PETSC_MAX_PATH_LEN] = "therm.dat"; 95c4762a1bSJed Brown struct _User user; 96c4762a1bSJed Brown TSConvergedReason reason; 97c4762a1bSJed Brown PetscBool showsolutions = PETSC_FALSE; 98c4762a1bSJed Brown char **snames,*names; 99c4762a1bSJed Brown Vec lambda; /* used with TSAdjoint for sensitivities */ 100c4762a1bSJed Brown 101*b122ec5aSJacob Faibussowitsch CHKERRQ(PetscInitialize(&argc,&argv,(char*)0,help)); 102c4762a1bSJed Brown ierr = PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"Chemistry solver options","");CHKERRQ(ierr); 1035f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsString("-chem","CHEMKIN input file","",chemfile,chemfile,sizeof(chemfile),NULL)); 1045f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsString("-thermo","NASA thermo input file","",thermofile,thermofile,sizeof(thermofile),NULL)); 105c4762a1bSJed Brown user.pressure = 1.01325e5; /* Pascal */ 1065f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsReal("-pressure","Pressure of reaction [Pa]","",user.pressure,&user.pressure,NULL)); 107c4762a1bSJed Brown user.Tini = 1550; 1085f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsReal("-Tini","Initial temperature [K]","",user.Tini,&user.Tini,NULL)); 109c4762a1bSJed Brown user.diffus = 100; 1105f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsReal("-diffus","Diffusion constant","",user.diffus,&user.diffus,NULL)); 1115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-draw_solution","Plot the solution for each cell","",showsolutions,&showsolutions,NULL)); 112c4762a1bSJed Brown user.diffusion = PETSC_TRUE; 1135f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-diffusion","Have diffusion","",user.diffusion,&user.diffusion,NULL)); 114c4762a1bSJed Brown user.reactions = PETSC_TRUE; 1155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsBool("-reactions","Have reactions","",user.reactions,&user.reactions,NULL)); 116c4762a1bSJed Brown ierr = PetscOptionsEnd();CHKERRQ(ierr); 117c4762a1bSJed Brown 1185f80ce2aSJacob Faibussowitsch CHKERRTC(TC_initChem(chemfile, thermofile, 0, 1.0)); 119c4762a1bSJed Brown user.Nspec = TC_getNspec(); 120c4762a1bSJed Brown user.Nreac = TC_getNreac(); 121c4762a1bSJed Brown 1225f80ce2aSJacob Faibussowitsch CHKERRQ(DMDACreate1d(PETSC_COMM_WORLD,DM_BOUNDARY_PERIODIC,10,user.Nspec+1,1,NULL,&user.dm)); 1235f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions(user.dm)); 1245f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(user.dm)); 1255f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetInfo(user.dm,NULL,&ncells,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL)); 126c4762a1bSJed Brown user.dx = 1.0/ncells; /* Set the coordinates of the cell centers; note final ghost cell is at x coordinate 1.0 */ 1275f80ce2aSJacob Faibussowitsch CHKERRQ(DMDASetUniformCoordinates(user.dm,0.0,1.0,0.0,1.0,0.0,1.0)); 128c4762a1bSJed Brown 129c4762a1bSJed Brown /* set the names of each field in the DMDA based on the species name */ 1305f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1((user.Nspec+1)*LENGTHOFSPECNAME,&names)); 1315f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcpy(names,"Temp")); 1322f613bf5SBarry Smith TC_getSnames(user.Nspec,names+LENGTHOFSPECNAME); 1335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1((user.Nspec+2),&snames)); 134c4762a1bSJed Brown for (i=0; i<user.Nspec+1; i++) snames[i] = names+i*LENGTHOFSPECNAME; 135c4762a1bSJed Brown snames[user.Nspec+1] = NULL; 1365f80ce2aSJacob Faibussowitsch CHKERRQ(DMDASetFieldNames(user.dm,(const char * const *)snames)); 1375f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(snames)); 1385f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(names)); 139c4762a1bSJed Brown 1405f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateMatrix(user.dm,&J)); 1415f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateGlobalVector(user.dm,&X)); 142c4762a1bSJed Brown 1435f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc3(user.Nspec+1,&user.tchemwork,PetscSqr(user.Nspec+1),&user.Jdense,user.Nspec+1,&user.rows)); 144c4762a1bSJed Brown 145c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 146c4762a1bSJed Brown Create timestepping solver context 147c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1485f80ce2aSJacob Faibussowitsch CHKERRQ(TSCreate(PETSC_COMM_WORLD,&ts)); 1495f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetDM(ts,user.dm)); 1505f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetType(ts,TSARKIMEX)); 1515f80ce2aSJacob Faibussowitsch CHKERRQ(TSARKIMEXSetFullyImplicit(ts,PETSC_TRUE)); 1525f80ce2aSJacob Faibussowitsch CHKERRQ(TSARKIMEXSetType(ts,TSARKIMEX4)); 1535f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetRHSFunction(ts,NULL,FormRHSFunction,&user)); 1545f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetRHSJacobian(ts,J,J,FormRHSJacobian,&user)); 155c4762a1bSJed Brown 156c4762a1bSJed Brown ftime = 1.0; 1575f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetMaxTime(ts,ftime)); 1585f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetExactFinalTime(ts,TS_EXACTFINALTIME_STEPOVER)); 159c4762a1bSJed Brown 160c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 161c4762a1bSJed Brown Set initial conditions 162c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1635f80ce2aSJacob Faibussowitsch CHKERRQ(FormInitialSolution(ts,X,&user)); 1645f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetSolution(ts,X)); 165c4762a1bSJed Brown dt = 1e-10; /* Initial time step */ 1665f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetTimeStep(ts,dt)); 1675f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetAdapt(ts,&adapt)); 1685f80ce2aSJacob Faibussowitsch CHKERRQ(TSAdaptSetStepLimits(adapt,1e-12,1e-4)); /* Also available with -ts_adapt_dt_min/-ts_adapt_dt_max */ 1695f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetMaxSNESFailures(ts,-1)); /* Retry step an unlimited number of times */ 170c4762a1bSJed Brown 171c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 172c4762a1bSJed Brown Pass information to graphical monitoring routine 173c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 174c4762a1bSJed Brown if (showsolutions) { 1755f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetCorners(user.dm,&xs,NULL,NULL,&xm,NULL,NULL)); 176c4762a1bSJed Brown for (i=xs;i<xs+xm;i++) { 1775f80ce2aSJacob Faibussowitsch CHKERRQ(MonitorCell(ts,&user,i)); 178c4762a1bSJed Brown } 179c4762a1bSJed Brown } 180c4762a1bSJed Brown 181c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 182c4762a1bSJed Brown Set runtime options 183c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1845f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetFromOptions(ts)); 185c4762a1bSJed Brown 186c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 187c4762a1bSJed Brown Set final conditions for sensitivities 188c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1895f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateGlobalVector(user.dm,&lambda)); 1905f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetCostGradients(ts,1,&lambda,NULL)); 1915f80ce2aSJacob Faibussowitsch CHKERRQ(VecSetValue(lambda,0,1.0,INSERT_VALUES)); 1925f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyBegin(lambda)); 1935f80ce2aSJacob Faibussowitsch CHKERRQ(VecAssemblyEnd(lambda)); 194c4762a1bSJed Brown 195c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 196c4762a1bSJed Brown Solve ODE 197c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 1985f80ce2aSJacob Faibussowitsch CHKERRQ(TSSolve(ts,X)); 1995f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetSolveTime(ts,&ftime)); 2005f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetStepNumber(ts,&steps)); 2015f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetConvergedReason(ts,&reason)); 2025f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_WORLD,"%s at time %g after %D steps\n",TSConvergedReasons[reason],(double)ftime,steps)); 203c4762a1bSJed Brown 204c4762a1bSJed Brown { 205c4762a1bSJed Brown Vec max; 206c4762a1bSJed Brown const char * const *names; 207c4762a1bSJed Brown PetscInt i; 208c4762a1bSJed Brown const PetscReal *bmax; 209c4762a1bSJed Brown 2105f80ce2aSJacob Faibussowitsch CHKERRQ(TSMonitorEnvelopeGetBounds(ts,&max,NULL)); 211c4762a1bSJed Brown if (max) { 2125f80ce2aSJacob Faibussowitsch CHKERRQ(TSMonitorLGGetVariableNames(ts,&names)); 213c4762a1bSJed Brown if (names) { 2145f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(max,&bmax)); 2155f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF,"Species - maximum mass fraction\n")); 216c4762a1bSJed Brown for (i=1; i<user.Nspec; i++) { 2175f80ce2aSJacob Faibussowitsch if (bmax[i] > .01) CHKERRQ(PetscPrintf(PETSC_COMM_SELF,"%s %g\n",names[i],bmax[i])); 218c4762a1bSJed Brown } 2195f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(max,&bmax)); 220c4762a1bSJed Brown } 221c4762a1bSJed Brown } 222c4762a1bSJed Brown } 223c4762a1bSJed Brown 224c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 225c4762a1bSJed Brown Free work space. 226c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 227c4762a1bSJed Brown TC_reset(); 2285f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&user.dm)); 2295f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&J)); 2305f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&X)); 2315f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&lambda)); 2325f80ce2aSJacob Faibussowitsch CHKERRQ(TSDestroy(&ts)); 2335f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree3(user.tchemwork,user.Jdense,user.rows)); 234*b122ec5aSJacob Faibussowitsch CHKERRQ(PetscFinalize()); 235*b122ec5aSJacob Faibussowitsch return 0; 236c4762a1bSJed Brown } 237c4762a1bSJed Brown 238c4762a1bSJed Brown /* 239c4762a1bSJed Brown Applies the second order centered difference diffusion operator on a one dimensional periodic domain 240c4762a1bSJed Brown */ 241c4762a1bSJed Brown static PetscErrorCode FormDiffusionFunction(TS ts,PetscReal t,Vec X,Vec F,void *ptr) 242c4762a1bSJed Brown { 243c4762a1bSJed Brown User user = (User)ptr; 244c4762a1bSJed Brown PetscErrorCode ierr; 245c4762a1bSJed Brown PetscScalar **f; 246c4762a1bSJed Brown const PetscScalar **x; 247c4762a1bSJed Brown DM dm; 248c4762a1bSJed Brown PetscInt i,xs,xm,j,dof; 249c4762a1bSJed Brown Vec Xlocal; 250c4762a1bSJed Brown PetscReal idx; 251c4762a1bSJed Brown 252c4762a1bSJed Brown PetscFunctionBeginUser; 2535f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetDM(ts,&dm)); 2545f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetInfo(dm,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL)); 2555f80ce2aSJacob Faibussowitsch CHKERRQ(DMGetLocalVector(dm,&Xlocal)); 2565f80ce2aSJacob Faibussowitsch CHKERRQ(DMGlobalToLocalBegin(dm,X,INSERT_VALUES,Xlocal)); 2575f80ce2aSJacob Faibussowitsch CHKERRQ(DMGlobalToLocalEnd(dm,X,INSERT_VALUES,Xlocal)); 2585f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecGetArrayDOFRead(dm,Xlocal,&x)); 2595f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecGetArrayDOF(dm,F,&f)); 2605f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetCorners(dm,&xs,NULL,NULL,&xm,NULL,NULL)); 261c4762a1bSJed Brown 262c4762a1bSJed Brown idx = 1.0*user->diffus/user->dx; 263c4762a1bSJed Brown for (i=xs; i<xs+xm; i++) { 264c4762a1bSJed Brown for (j=0; j<dof; j++) { 265c4762a1bSJed Brown f[i][j] += idx*(x[i+1][j] - 2.0*x[i][j] + x[i-1][j]); 266c4762a1bSJed Brown } 267c4762a1bSJed Brown } 2685f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecRestoreArrayDOFRead(dm,Xlocal,&x)); 2695f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecRestoreArrayDOF(dm,F,&f)); 2705f80ce2aSJacob Faibussowitsch CHKERRQ(DMRestoreLocalVector(dm,&Xlocal)); 271c4762a1bSJed Brown PetscFunctionReturn(0); 272c4762a1bSJed Brown } 273c4762a1bSJed Brown 274c4762a1bSJed Brown /* 275c4762a1bSJed Brown Produces the second order centered difference diffusion operator on a one dimensional periodic domain 276c4762a1bSJed Brown */ 277c4762a1bSJed Brown static PetscErrorCode FormDiffusionJacobian(TS ts,PetscReal t,Vec X,Mat Amat,Mat Pmat,void *ptr) 278c4762a1bSJed Brown { 279c4762a1bSJed Brown User user = (User)ptr; 280c4762a1bSJed Brown PetscErrorCode ierr; 281c4762a1bSJed Brown DM dm; 282c4762a1bSJed Brown PetscInt i,xs,xm,j,dof; 283c4762a1bSJed Brown PetscReal idx,values[3]; 284c4762a1bSJed Brown MatStencil row,col[3]; 285c4762a1bSJed Brown 286c4762a1bSJed Brown PetscFunctionBeginUser; 2875f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetDM(ts,&dm)); 2885f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetInfo(dm,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL)); 2895f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetCorners(dm,&xs,NULL,NULL,&xm,NULL,NULL)); 290c4762a1bSJed Brown 291c4762a1bSJed Brown idx = 1.0*user->diffus/user->dx; 292c4762a1bSJed Brown values[0] = idx; 293c4762a1bSJed Brown values[1] = -2.0*idx; 294c4762a1bSJed Brown values[2] = idx; 295c4762a1bSJed Brown for (i=xs; i<xs+xm; i++) { 296c4762a1bSJed Brown for (j=0; j<dof; j++) { 297c4762a1bSJed Brown row.i = i; row.c = j; 298c4762a1bSJed Brown col[0].i = i-1; col[0].c = j; 299c4762a1bSJed Brown col[1].i = i; col[1].c = j; 300c4762a1bSJed Brown col[2].i = i+1; col[2].c = j; 3015f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValuesStencil(Pmat,1,&row,3,col,values,ADD_VALUES)); 302c4762a1bSJed Brown } 303c4762a1bSJed Brown } 3045f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(Pmat,MAT_FINAL_ASSEMBLY)); 3055f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(Pmat,MAT_FINAL_ASSEMBLY)); 306c4762a1bSJed Brown PetscFunctionReturn(0); 307c4762a1bSJed Brown } 308c4762a1bSJed Brown 309c4762a1bSJed Brown static PetscErrorCode FormRHSFunction(TS ts,PetscReal t,Vec X,Vec F,void *ptr) 310c4762a1bSJed Brown { 311c4762a1bSJed Brown User user = (User)ptr; 312c4762a1bSJed Brown PetscErrorCode ierr; 313c4762a1bSJed Brown PetscScalar **f; 314c4762a1bSJed Brown const PetscScalar **x; 315c4762a1bSJed Brown DM dm; 316c4762a1bSJed Brown PetscInt i,xs,xm; 317c4762a1bSJed Brown 318c4762a1bSJed Brown PetscFunctionBeginUser; 319c4762a1bSJed Brown if (user->reactions) { 3205f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetDM(ts,&dm)); 3215f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecGetArrayDOFRead(dm,X,&x)); 3225f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecGetArrayDOF(dm,F,&f)); 3235f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetCorners(dm,&xs,NULL,NULL,&xm,NULL,NULL)); 324c4762a1bSJed Brown 325c4762a1bSJed Brown for (i=xs; i<xs+xm; i++) { 3265f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(user->tchemwork,x[i],user->Nspec+1)); 327c4762a1bSJed Brown user->tchemwork[0] *= user->Tini; /* Dimensionalize */ 3285f80ce2aSJacob Faibussowitsch CHKERRTC(TC_getSrc(user->tchemwork,user->Nspec+1,f[i])); 329c4762a1bSJed Brown f[i][0] /= user->Tini; /* Non-dimensionalize */ 330c4762a1bSJed Brown } 331c4762a1bSJed Brown 3325f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecRestoreArrayDOFRead(dm,X,&x)); 3335f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecRestoreArrayDOF(dm,F,&f)); 334c4762a1bSJed Brown } else { 3355f80ce2aSJacob Faibussowitsch CHKERRQ(VecZeroEntries(F)); 336c4762a1bSJed Brown } 337c4762a1bSJed Brown if (user->diffusion) { 3385f80ce2aSJacob Faibussowitsch CHKERRQ(FormDiffusionFunction(ts,t,X,F,ptr)); 339c4762a1bSJed Brown } 340c4762a1bSJed Brown PetscFunctionReturn(0); 341c4762a1bSJed Brown } 342c4762a1bSJed Brown 343c4762a1bSJed Brown static PetscErrorCode FormRHSJacobian(TS ts,PetscReal t,Vec X,Mat Amat,Mat Pmat,void *ptr) 344c4762a1bSJed Brown { 345c4762a1bSJed Brown User user = (User)ptr; 346c4762a1bSJed Brown PetscErrorCode ierr; 347c4762a1bSJed Brown const PetscScalar **x; 348c4762a1bSJed Brown PetscInt M = user->Nspec+1,i,j,xs,xm; 349c4762a1bSJed Brown DM dm; 350c4762a1bSJed Brown 351c4762a1bSJed Brown PetscFunctionBeginUser; 352c4762a1bSJed Brown if (user->reactions) { 3535f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetDM(ts,&dm)); 3545f80ce2aSJacob Faibussowitsch CHKERRQ(MatZeroEntries(Pmat)); 3555f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(Pmat,MAT_ROW_ORIENTED,PETSC_FALSE)); 3565f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(Pmat,MAT_IGNORE_ZERO_ENTRIES,PETSC_TRUE)); 3575f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecGetArrayDOFRead(dm,X,&x)); 3585f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetCorners(dm,&xs,NULL,NULL,&xm,NULL,NULL)); 359c4762a1bSJed Brown 360c4762a1bSJed Brown for (i=xs; i<xs+xm; i++) { 3615f80ce2aSJacob Faibussowitsch CHKERRQ(PetscArraycpy(user->tchemwork,x[i],user->Nspec+1)); 362c4762a1bSJed Brown user->tchemwork[0] *= user->Tini; /* Dimensionalize temperature (first row) because that is what Tchem wants */ 3635f80ce2aSJacob Faibussowitsch CHKERRQ(TC_getJacTYN(user->tchemwork,user->Nspec,user->Jdense,1)); 364c4762a1bSJed Brown 365c4762a1bSJed Brown for (j=0; j<M; j++) user->Jdense[j + 0*M] /= user->Tini; /* Non-dimensionalize first column */ 366c4762a1bSJed Brown for (j=0; j<M; j++) user->Jdense[0 + j*M] /= user->Tini; /* Non-dimensionalize first row */ 367c4762a1bSJed Brown for (j=0; j<M; j++) user->rows[j] = i*M+j; 3685f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(Pmat,M,user->rows,M,user->rows,user->Jdense,INSERT_VALUES)); 369c4762a1bSJed Brown } 3705f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecRestoreArrayDOFRead(dm,X,&x)); 3715f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(Pmat,MAT_FINAL_ASSEMBLY)); 3725f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(Pmat,MAT_FINAL_ASSEMBLY)); 373c4762a1bSJed Brown } else { 3745f80ce2aSJacob Faibussowitsch CHKERRQ(MatZeroEntries(Pmat)); 375c4762a1bSJed Brown } 376c4762a1bSJed Brown if (user->diffusion) { 3775f80ce2aSJacob Faibussowitsch CHKERRQ(FormDiffusionJacobian(ts,t,X,Amat,Pmat,ptr)); 378c4762a1bSJed Brown } 379c4762a1bSJed Brown if (Amat != Pmat) { 3805f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(Amat,MAT_FINAL_ASSEMBLY)); 3815f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(Amat,MAT_FINAL_ASSEMBLY)); 382c4762a1bSJed Brown } 383c4762a1bSJed Brown PetscFunctionReturn(0); 384c4762a1bSJed Brown } 385c4762a1bSJed Brown 386c4762a1bSJed Brown PetscErrorCode FormInitialSolution(TS ts,Vec X,void *ctx) 387c4762a1bSJed Brown { 388c4762a1bSJed Brown PetscScalar **x,*xc; 389c4762a1bSJed Brown PetscErrorCode ierr; 390c4762a1bSJed Brown struct {const char *name; PetscReal massfrac;} initial[] = { 391c4762a1bSJed Brown {"CH4", 0.0948178320887}, 392c4762a1bSJed Brown {"O2", 0.189635664177}, 393c4762a1bSJed Brown {"N2", 0.706766236705}, 394c4762a1bSJed Brown {"AR", 0.00878026702874} 395c4762a1bSJed Brown }; 396c4762a1bSJed Brown PetscInt i,j,xs,xm; 397c4762a1bSJed Brown DM dm; 398c4762a1bSJed Brown 399c4762a1bSJed Brown PetscFunctionBeginUser; 4005f80ce2aSJacob Faibussowitsch CHKERRQ(VecZeroEntries(X)); 4015f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetDM(ts,&dm)); 4025f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetCorners(dm,&xs,NULL,NULL,&xm,NULL,NULL)); 403c4762a1bSJed Brown 4045f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetCoordinateArray(dm,&xc)); 4055f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecGetArrayDOF(dm,X,&x)); 406c4762a1bSJed Brown for (i=xs; i<xs+xm; i++) { 407c4762a1bSJed Brown x[i][0] = 1.0 + .05*PetscSinScalar(2.*PETSC_PI*xc[i]); /* Non-dimensionalized by user->Tini */ 408c4762a1bSJed Brown for (j=0; j<sizeof(initial)/sizeof(initial[0]); j++) { 409c4762a1bSJed Brown int ispec = TC_getSpos(initial[j].name, strlen(initial[j].name)); 4103c633725SBarry Smith PetscCheck(ispec >= 0,PETSC_COMM_SELF,PETSC_ERR_USER,"Could not find species %s",initial[j].name); 4115f80ce2aSJacob Faibussowitsch CHKERRQ(PetscPrintf(PETSC_COMM_SELF,"Species %d: %s %g\n",j,initial[j].name,initial[j].massfrac)); 412c4762a1bSJed Brown x[i][1+ispec] = initial[j].massfrac; 413c4762a1bSJed Brown } 414c4762a1bSJed Brown } 4155f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecRestoreArrayDOF(dm,X,&x)); 4165f80ce2aSJacob Faibussowitsch CHKERRQ(DMDARestoreCoordinateArray(dm,&xc)); 417c4762a1bSJed Brown PetscFunctionReturn(0); 418c4762a1bSJed Brown } 419c4762a1bSJed Brown 420c4762a1bSJed Brown /* 421c4762a1bSJed Brown Routines for displaying the solutions 422c4762a1bSJed Brown */ 423c4762a1bSJed Brown typedef struct { 424c4762a1bSJed Brown PetscInt cell; 425c4762a1bSJed Brown User user; 426c4762a1bSJed Brown } UserLGCtx; 427c4762a1bSJed Brown 428c4762a1bSJed Brown static PetscErrorCode FormMoleFraction(UserLGCtx *ctx,Vec massf,Vec *molef) 429c4762a1bSJed Brown { 430c4762a1bSJed Brown User user = ctx->user; 431c4762a1bSJed Brown PetscErrorCode ierr; 432c4762a1bSJed Brown PetscReal *M,tM=0; 433c4762a1bSJed Brown PetscInt i,n = user->Nspec+1; 434c4762a1bSJed Brown PetscScalar *mof; 435c4762a1bSJed Brown const PetscScalar **maf; 436c4762a1bSJed Brown 437c4762a1bSJed Brown PetscFunctionBegin; 4385f80ce2aSJacob Faibussowitsch CHKERRQ(VecCreateSeq(PETSC_COMM_SELF,n,molef)); 4395f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(user->Nspec,&M)); 440c4762a1bSJed Brown TC_getSmass(user->Nspec, M); 4415f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecGetArrayDOFRead(user->dm,massf,&maf)); 4425f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArray(*molef,&mof)); 443c4762a1bSJed Brown mof[0] = maf[ctx->cell][0]; /* copy over temperature */ 444c4762a1bSJed Brown for (i=1; i<n; i++) tM += maf[ctx->cell][i]/M[i-1]; 445c4762a1bSJed Brown for (i=1; i<n; i++) { 446c4762a1bSJed Brown mof[i] = maf[ctx->cell][i]/(M[i-1]*tM); 447c4762a1bSJed Brown } 4485f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecRestoreArrayDOFRead(user->dm,massf,&maf)); 4495f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArray(*molef,&mof)); 4505f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(M)); 451c4762a1bSJed Brown PetscFunctionReturn(0); 452c4762a1bSJed Brown } 453c4762a1bSJed Brown 454c4762a1bSJed Brown static PetscErrorCode MonitorCellDestroy(UserLGCtx *uctx) 455c4762a1bSJed Brown { 456c4762a1bSJed Brown PetscErrorCode ierr; 457c4762a1bSJed Brown 458c4762a1bSJed Brown PetscFunctionBegin; 4595f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(uctx)); 460c4762a1bSJed Brown PetscFunctionReturn(0); 461c4762a1bSJed Brown } 462c4762a1bSJed Brown 463c4762a1bSJed Brown /* 464c4762a1bSJed Brown Use TSMonitorLG to monitor the reactions in a particular cell 465c4762a1bSJed Brown */ 466c4762a1bSJed Brown static PetscErrorCode MonitorCell(TS ts,User user,PetscInt cell) 467c4762a1bSJed Brown { 468c4762a1bSJed Brown PetscErrorCode ierr; 469c4762a1bSJed Brown TSMonitorLGCtx ctx; 470c4762a1bSJed Brown char **snames; 471c4762a1bSJed Brown UserLGCtx *uctx; 472c4762a1bSJed Brown char label[128]; 473c4762a1bSJed Brown PetscReal temp,*xc; 474c4762a1bSJed Brown PetscMPIInt rank; 475c4762a1bSJed Brown 476c4762a1bSJed Brown PetscFunctionBegin; 4775f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetCoordinateArray(user->dm,&xc)); 478c4762a1bSJed Brown temp = 1.0 + .05*PetscSinScalar(2.*PETSC_PI*xc[cell]); /* Non-dimensionalized by user->Tini */ 4795f80ce2aSJacob Faibussowitsch CHKERRQ(DMDARestoreCoordinateArray(user->dm,&xc)); 4805f80ce2aSJacob Faibussowitsch CHKERRMPI(MPI_Comm_rank(PETSC_COMM_WORLD,&rank)); 4815f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSNPrintf(label,sizeof(label),"Initial Temperature %g Cell %d Rank %d",(double)user->Tini*temp,(int)cell,rank)); 4825f80ce2aSJacob Faibussowitsch CHKERRQ(TSMonitorLGCtxCreate(PETSC_COMM_SELF,NULL,label,PETSC_DECIDE,PETSC_DECIDE,600,400,1,&ctx)); 4835f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetFieldNames(user->dm,(const char * const **)&snames)); 4845f80ce2aSJacob Faibussowitsch CHKERRQ(TSMonitorLGCtxSetVariableNames(ctx,(const char * const *)snames)); 4855f80ce2aSJacob Faibussowitsch CHKERRQ(PetscNew(&uctx)); 486c4762a1bSJed Brown uctx->cell = cell; 487c4762a1bSJed Brown uctx->user = user; 4885f80ce2aSJacob Faibussowitsch CHKERRQ(TSMonitorLGCtxSetTransform(ctx,(PetscErrorCode (*)(void*,Vec,Vec*))FormMoleFraction,(PetscErrorCode (*)(void*))MonitorCellDestroy,uctx)); 4895f80ce2aSJacob Faibussowitsch CHKERRQ(TSMonitorSet(ts,TSMonitorLGSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy)); 490c4762a1bSJed Brown PetscFunctionReturn(0); 491c4762a1bSJed Brown } 492