/* the metapopulation. */ struct sample * draw_sample(struct metapopulation *in, int n, struct param *par){ int i, j, *nIsolatesPerPop, count; double *nAvailPerPop; struct pathogen *ppat; /* create pointer to pathogens */ struct sample *out=create_sample(n); /* escape if no isolate available */ if(get_total_ninf(in) + get_total_nexp(in) < 1){ printf("\nMetapopulation without infections - sample will be empty.\n"); out->n = 0; out->pathogens = NULL; out->popid = NULL; return out; } /* get nb of isolates available in each population */ nAvailPerPop = (double *) calloc(get_npop(in), sizeof(double)); if(nAvailPerPop == NULL){ fprintf(stderr, "\n[in: population.c->draw_sample]\nNo memory left to isolate available pathogens. Exiting.\n"); exit(1); } for(j=0;j<get_npop(in);j++){ nAvailPerPop[j] = (double) get_nexp(get_populations(in)[j]) + get_ninf(get_populations(in)[j]); } /* get nb of isolates sampled in each population*/ nIsolatesPerPop = (int *) calloc(get_npop(in), sizeof(int)); if(nIsolatesPerPop == NULL){ fprintf(stderr, "\n[in: population.c->draw_sample]\nNo memory left to isolate available pathogens. Exiting.\n"); exit(1); } gsl_ran_multinomial(par->rng, get_npop(in), n, nAvailPerPop, (unsigned int *) nIsolatesPerPop); /* fill in the sample pathogens */ count = 0; for(j=0;j<get_npop(in);j++){ /* for each population */ for(i=0;i<nIsolatesPerPop[j];i++){ ppat = select_random_pathogen(get_populations(in)[j], par); /* free_pathogen(out->pathogens[count]); */ out->pathogens[count] = reconstruct_genome(ppat); out->popid[count++] = j; } } /* free local pointers */ free(nAvailPerPop); free(nIsolatesPerPop); return out; } /* end draw_sample */
int get_total_ninfcum(struct metapopulation *in){ int i, k=get_npop(in), out=0; for(i=0;i<k;i++) { out += get_ninfcum(get_populations(in)[i]); } return out; }
/* Print metapopulation content */ void print_metapopulation(struct metapopulation *in, bool showGen){ int i, k, K=get_npop(in); struct population *curPop; struct pathogen * curpat; /* display general info */ printf("\nnb of populations: %d", K); printf("\ntotal nb susceptible: %d", get_total_nsus(in)); printf("\ntotal nb infected: %d", get_total_ninf(in)); printf("\ntotal nb recovered: %d", get_total_nrec(in)); printf("\ntotal population size: %d\n", get_total_nsus(in)+get_total_ninf(in)+get_total_nrec(in)); /* display populations */ for(k=0;k<K;k++){ curPop = get_populations(in)[k]; printf("\npopulation %d", k); print_population(curPop); if(showGen){ for(i=0;i<get_maxnpat(in);i++){ curpat = get_pathogens(in)[i]; if(!isNULL_pathogen(curpat) && get_popid(curpat)==k) print_pathogen(curpat); } printf("\n"); } } }
/* Function to be called from R */ void R_epidemics(int *seqLength, double *mutRate, int *npop, int *nHostPerPop, double *beta, int *nStart, int *t1, int *t2, int *Nsample, int *Tsample, int *duration, int *nbnb, int *listnb, double *pdisp){ int i, nstep, counter_sample = 0, tabidx; /* Initialize random number generator */ int j; time_t t; t = time(NULL); // time in seconds, used to change the seed of the random generator gsl_rng * rng; const gsl_rng_type *typ; gsl_rng_env_setup(); typ=gsl_rng_default; rng=gsl_rng_alloc(typ); gsl_rng_set(rng,t); // changes the seed of the random generator /* transfer simulation parameters */ struct param * par; par = (struct param *) malloc(sizeof(struct param)); par->L = *seqLength; par->mu = *mutRate; par->muL = par->mu * par->L; par->rng = rng; par->npop = *npop; par->popsizes = nHostPerPop; par->beta = *beta; par->nstart = *nStart; par->t1 = *t1; par->t2 = *t2; par->t_sample = Tsample; par->n_sample = *Nsample; par->duration = *duration; par->cn_nb_nb = nbnb; par->cn_list_nb = listnb; par->cn_weights = pdisp; /* check/print parameters */ check_param(par); print_param(par); /* dispersal matrix */ struct network *cn = create_network(par); /* print_network(cn, TRUE); */ /* group sizes */ struct ts_groupsizes * grpsizes = create_ts_groupsizes(par); /* initiate population */ struct metapopulation * metapop; metapop = create_metapopulation(par); /* get sampling schemes (timestep+effectives) */ translate_dates(par); struct table_int *tabdates = get_table_int(par->t_sample, par->n_sample); printf("\n\nsampling at timesteps:"); print_table_int(tabdates); /* create sample */ struct sample ** samplist = (struct sample **) malloc(tabdates->n * sizeof(struct sample *)); struct sample *samp; /* MAKE METAPOPULATION EVOLVE */ nstep = 0; while(get_total_nsus(metapop)>0 && (get_total_ninf(metapop)+get_total_nexp(metapop))>0 && nstep<par->duration){ nstep++; /* age metapopulation */ age_metapopulation(metapop, par); /* process infections */ for(j=0;j<get_npop(metapop);j++){ process_infections(get_populations(metapop)[j], metapop, cn, par); } /* draw samples */ if((tabidx = int_in_vec(nstep, tabdates->items, tabdates->n)) > -1){ /* TRUE if step must be sampled */ samplist[counter_sample++] = draw_sample(metapop, tabdates->times[tabidx], par); } fill_ts_groupsizes(grpsizes, metapop, nstep); } /* we stopped after 'nstep' steps */ if(nstep < par->duration){ printf("\nEpidemics ended at time %d, before last sampling time (%d).\n", nstep, par->duration); } else { /* printf("\n\n-- FINAL METAPOPULATION --"); */ /* print_metapopulation(metapop, FALSE); */ /* merge samples */ samp = merge_samples(samplist, tabdates->n, par); /* write sample to file */ printf("\n\nWriting sample to file 'out-sample.txt'\n"); write_sample(samp); /* free memory */ free_sample(samp); } /* write group sizes to file */ printf("\n\nPrinting group sizes to file 'out-popsize.txt'\n"); write_ts_groupsizes(grpsizes); /* free memory */ free_metapopulation(metapop); free_param(par); for(i=0;i<counter_sample;i++) free_sample(samplist[i]); free(samplist); free_table_int(tabdates); free_network(cn); free_ts_groupsizes(grpsizes); }
/* all-in-one function testing epidemics growth, summary statistics, etc. */ void test_epidemics(int seqLength, double mutRate, int npop, int *nHostPerPop, double beta, int nStart, int t1, int t2, int Nsample, int *Tsample, int duration, int *nbnb, int *listnb, double *pdisp){ int i, j, nstep=0, tabidx, counter_sample = 0; /* Initialize random number generator */ time_t t; t = time(NULL); // time in seconds, used to change the seed of the random generator gsl_rng * rng; const gsl_rng_type *typ; gsl_rng_env_setup(); typ=gsl_rng_default; rng=gsl_rng_alloc(typ); gsl_rng_set(rng,t); // changes the seed of the random generator /* transfer simulation parameters */ struct param * par; par = (struct param *) malloc(sizeof(struct param)); par->L = seqLength; par->mu = mutRate; par->muL = par->mu * par->L; par->rng = rng; par->npop = npop; par->npop = npop; par->popsizes = nHostPerPop; par->beta = beta; par->nstart = nStart; par->t1 = t1; par->t2 = t2; par->t_sample = Tsample; par->n_sample = Nsample; par->duration = duration; par->cn_nb_nb = nbnb; par->cn_list_nb = listnb; par->cn_weights = pdisp; /* check/print parameters */ check_param(par); print_param(par); /* dispersal matrix */ struct network *cn = create_network(par); /* group sizes */ struct ts_groupsizes * grpsizes = create_ts_groupsizes(par); /* initiate population */ struct metapopulation * metapop; metapop = create_metapopulation(par); /* get sampling schemes (timestep+effectives) */ translate_dates(par); struct table_int *tabdates = get_table_int(par->t_sample, par->n_sample); printf("\n\nsampling at timesteps:"); print_table_int(tabdates); /* create sample */ struct sample ** samplist = (struct sample **) malloc(tabdates->n * sizeof(struct sample *)); struct sample *samp; /* MAKE METAPOPULATION EVOLVE */ nstep = 0; while(get_total_nsus(metapop)>0 && (get_total_ninf(metapop)+get_total_nexp(metapop))>0 && nstep<par->duration){ nstep++; /* age metapopulation */ age_metapopulation(metapop, par); /* process infections */ for(j=0;j<get_npop(metapop);j++){ process_infections(get_populations(metapop)[j], metapop, cn, par); } /* draw samples */ if((tabidx = int_in_vec(nstep, tabdates->items, tabdates->n)) > -1){ /* TRUE if step must be sampled */ samplist[counter_sample++] = draw_sample(metapop, tabdates->times[tabidx], par); } fill_ts_groupsizes(grpsizes, metapop, nstep); } /* we stopped after 'nstep' steps */ if(nstep < par->duration){ printf("\nEpidemics ended at time %d, before last sampling time (%d).\n", nstep, par->duration); } else { printf("\n\n-- FINAL METAPOPULATION --"); print_metapopulation(metapop, TRUE); /* test samples */ for(i=0;i<tabdates->n;i++) { printf("\nsample %d\n", i); print_sample(samplist[i], TRUE); } samp = merge_samples(samplist, tabdates->n, par) ; print_sample(samp, TRUE); /* test allele listing */ struct snplist *snpbilan; snpbilan = list_snps(samp, par); print_snplist(snpbilan); /* test allele frequencies */ struct allfreq *freq; freq = get_frequencies(samp, par); print_allfreq(freq); /* test Hs*/ double Hs = hs(samp,par); printf("\nHs = %0.3f\n", Hs); /* test Hs full genome */ Hs = hs_full_genome(samp,par); printf("\nHs (full genome) = %0.5f\n", Hs); /* test nb of snps */ int nball = nb_snps(samp,par); printf("\nnumber of SNPs = %d\n", nball); /* test mean nb of snps */ double temp = mean_nb_snps(samp); printf("\nmean number of SNPs = %.2f\n", temp); /* test var nb of snps */ temp = var_nb_snps(samp); printf("\nvariance of number of alleles = %.2f\n", temp); /* test pairwise distances */ struct distmat_int *mat = pairwise_dist(samp, par); print_distmat_int(mat); /* test mean pairwise distances */ temp = mean_pairwise_dist(samp,par); printf("\nmean pairwise distance: %.2f", temp); /* test variance of pairwise distances */ temp = var_pairwise_dist(samp,par); printf("\nvar pairwise distance: %.2f", temp); /* test Fst */ temp = fst(samp,par); printf("\nfst: %.2f", temp); printf("\n\n"); /* free memory */ free_sample(samp); free_snplist(snpbilan); free_allfreq(freq); free_distmat_int(mat); } /* write group sizes to file */ printf("\n\nPrinting group sizes to file 'out-popsize.txt'"); write_ts_groupsizes(grpsizes); /* free memory */ free_metapopulation(metapop); free_param(par); for(i=0;i<counter_sample;i++) free_sample(samplist[i]); free(samplist); free_table_int(tabdates); free_network(cn); free_ts_groupsizes(grpsizes); }
/* Function to be called from R */ void R_monitor_epidemics(int *seqLength, double *mutRate, int *npop, int *nHostPerPop, double *beta, int *nStart, int *t1, int *t2, int *Nsample, int *Tsample, int *duration, int *nbnb, int *listnb, double *pdisp, int *minSize){ int nstep; /* Initialize random number generator */ int j; time_t t; t = time(NULL); // time in seconds, used to change the seed of the random generator gsl_rng * rng; const gsl_rng_type *typ; gsl_rng_env_setup(); typ=gsl_rng_default; rng=gsl_rng_alloc(typ); gsl_rng_set(rng,t); // changes the seed of the random generator /* transfer simulation parameters */ struct param * par; par = (struct param *) malloc(sizeof(struct param)); par->L = *seqLength; par->mu = *mutRate; par->muL = par->mu * par->L; par->rng = rng; par->npop = *npop; par->popsizes = nHostPerPop; par->beta = *beta; par->nstart = *nStart; par->t1 = *t1; par->t2 = *t2; par->t_sample = Tsample; par->n_sample = *Nsample; par->duration = *duration; par->cn_nb_nb = nbnb; par->cn_list_nb = listnb; par->cn_weights = pdisp; /* check/print parameters */ check_param(par); print_param(par); /* dispersal matrix */ struct network *cn = create_network(par); /* print_network(cn, TRUE); */ /* group sizes */ struct ts_groupsizes * grpsizes = create_ts_groupsizes(par); struct ts_sumstat * sumstats = create_ts_sumstat(par); /* initiate population */ struct metapopulation * metapop; metapop = create_metapopulation(par); /* get sampling schemes (timestep+effectives) */ translate_dates(par); struct table_int *tabdates = get_table_int(par->t_sample, par->n_sample); printf("\n\nsampling at timesteps:"); print_table_int(tabdates); /* create sample */ struct sample *samp; /* MAKE METAPOPULATION EVOLVE */ nstep = 0; while(get_total_nsus(metapop)>0 && (get_total_ninf(metapop)+get_total_nexp(metapop))>0 && nstep<par->duration){ nstep++; /* age metapopulation */ age_metapopulation(metapop, par); /* process infections */ for(j=0;j<get_npop(metapop);j++){ process_infections(get_populations(metapop)[j], metapop, cn, par); } /* draw sample */ samp = draw_sample(metapop, par->n_sample, par); /* compute statistics */ if(get_total_ninf(metapop)> *minSize) fill_ts_sumstat(sumstats, samp, nstep, par); /* get group sizes */ fill_ts_groupsizes(grpsizes, metapop, nstep); } /* write group sizes to file */ printf("\n\nWriting results to file..."); write_ts_groupsizes(grpsizes); write_ts_sumstat(sumstats); printf("done.\n\n"); /* free memory */ free_sample(samp); free_metapopulation(metapop); free_param(par); free_network(cn); free_ts_groupsizes(grpsizes); free_ts_sumstat(sumstats); }
/* * steady_state solves for the steady_state of the system * that was previously setup using the add_to_ham and add_lin * routines. Solver selection and parameterscan be controlled via PETSc * command line options. */ void steady_state(Vec x){ PetscViewer mat_view; PC pc; Vec b; KSP ksp; /* linear solver context */ PetscInt row,col,its,j,i,Istart,Iend; PetscScalar mat_tmp; long dim; int num_pop; double *populations; Mat solve_A; if (_lindblad_terms) { dim = total_levels*total_levels; solve_A = full_A; if (nid==0) { printf("Lindblad terms found, using Lindblad solver."); } } else { if (nid==0) { printf("Warning! Steady state not supported for Schrodinger.\n"); printf(" Defaulting to (less efficient) Lindblad Solver\n"); exit(0); } dim = total_levels*total_levels; solve_A = ham_A; } if (!stab_added){ if (nid==0) printf("Adding stabilization...\n"); /* * Add elements to the matrix to make the normalization work * I have no idea why this works, I am copying it from qutip * We add 1.0 in the 0th spot and every n+1 after */ if (nid==0) { row = 0; for (i=0;i<total_levels;i++){ col = i*(total_levels+1); mat_tmp = 1.0 + 0.*PETSC_i; MatSetValue(full_A,row,col,mat_tmp,ADD_VALUES); } /* Print dense ham, if it was asked for */ if (_print_dense_ham){ FILE *fp_ham; fp_ham = fopen("ham","w"); if (nid==0){ for (i=0;i<total_levels;i++){ for (j=0;j<total_levels;j++){ fprintf(fp_ham,"%e %e ",PetscRealPart(_hamiltonian[i][j]),PetscImaginaryPart(_hamiltonian[i][j])); } fprintf(fp_ham,"\n"); } } fclose(fp_ham); for (i=0;i<total_levels;i++){ free(_hamiltonian[i]); } free(_hamiltonian); _print_dense_ham = 0; } } stab_added = 1; } // if (!matrix_assembled) { MatGetOwnershipRange(full_A,&Istart,&Iend); /* * Explicitly add 0.0 to all diagonal elements; * this fixes a 'matrix in wrong state' message that PETSc * gives if the diagonal was never initialized. */ if (nid==0) printf("Adding 0 to diagonal elements...\n"); for (i=Istart;i<Iend;i++){ mat_tmp = 0 + 0.*PETSC_i; MatSetValue(full_A,i,i,mat_tmp,ADD_VALUES); } /* Tell PETSc to assemble the matrix */ MatAssemblyBegin(full_A,MAT_FINAL_ASSEMBLY); MatAssemblyEnd(full_A,MAT_FINAL_ASSEMBLY); if (nid==0) printf("Matrix Assembled.\n"); matrix_assembled = 1; // } /* Print information about the matrix. */ PetscViewerASCIIOpen(PETSC_COMM_WORLD,NULL,&mat_view); PetscViewerPushFormat(mat_view,PETSC_VIEWER_ASCII_INFO); MatView(full_A,mat_view); PetscViewerPopFormat(mat_view); PetscViewerDestroy(&mat_view); /* * Create parallel vectors. * - When using VecCreate(), VecSetSizes() and VecSetFromOptions(), * we specify only the vector's global * dimension; the parallel partitioning is determined at runtime. * - Note: We form 1 vector from scratch and then duplicate as needed. */ VecCreate(PETSC_COMM_WORLD,&b); VecSetSizes(b,PETSC_DECIDE,dim); VecSetFromOptions(b); // VecDuplicate(b,&x); Assume x is passed in /* * Set rhs, b, and solution, x to 1.0 in the first * element, 0.0 elsewhere. */ VecSet(b,0.0); VecSet(x,0.0); if(nid==0) { row = 0; mat_tmp = 1.0 + 0.0*PETSC_i; VecSetValue(x,row,mat_tmp,INSERT_VALUES); VecSetValue(b,row,mat_tmp,INSERT_VALUES); } /* Assemble x and b */ VecAssemblyBegin(x); VecAssemblyEnd(x); VecAssemblyBegin(b); VecAssemblyEnd(b); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -* * Create the linear solver and set various options * *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* * Create linear solver context */ KSPCreate(PETSC_COMM_WORLD,&ksp); /* * Set operators. Here the matrix that defines the linear system * also serves as the preconditioning matrix. */ KSPSetOperators(ksp,full_A,full_A); /* * Set good default options for solver */ /* relative tolerance */ KSPSetTolerances(ksp,default_rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT); /* bjacobi preconditioner */ KSPGetPC(ksp,&pc); PCSetType(pc,PCASM); /* gmres solver with 100 restart*/ KSPSetType(ksp,KSPGMRES); KSPGMRESSetRestart(ksp,default_restart); /* * Set runtime options, e.g., * -ksp_type <type> -pc_type <type> -ksp_monitor -ksp_rtol <rtol> */ KSPSetFromOptions(ksp); /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Solve the linear system - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ if (nid==0) printf("KSP set. Solving for steady state...\n"); KSPSolve(ksp,b,x); num_pop = get_num_populations(); populations = malloc(num_pop*sizeof(double)); get_populations(x,&populations); if(nid==0){ printf("Final populations: "); for(i=0;i<num_pop;i++){ printf(" %e ",populations[i]); } printf("\n"); } KSPGetIterationNumber(ksp,&its); PetscPrintf(PETSC_COMM_WORLD,"Iterations %D\n",its); /* Free work space */ KSPDestroy(&ksp); // VecDestroy(&x); VecDestroy(&b); return; }
/* * time_step solves for the time_dependence of the system * that was previously setup using the add_to_ham and add_lin * routines. Solver selection and parameters can be controlled via PETSc * command line options. Default solver is TSRK3BS * * Inputs: * Vec x: The density matrix, with appropriate inital conditions * double dt: initial timestep. For certain explicit methods, this timestep * can be changed, as those methods have adaptive time steps * double time_max: the maximum time to integrate to * int steps_max: max number of steps to take */ void time_step(Vec x, PetscReal init_time, PetscReal time_max,PetscReal dt,PetscInt steps_max){ PetscViewer mat_view; TS ts; /* timestepping context */ PetscInt i,j,Istart,Iend,steps,row,col; PetscScalar mat_tmp; PetscReal tmp_real; Mat AA; PetscInt nevents,direction; PetscBool terminate; operator op; int num_pop; double *populations; Mat solve_A,solve_stiff_A; PetscLogStagePop(); PetscLogStagePush(solve_stage); if (_lindblad_terms) { if (nid==0) { printf("Lindblad terms found, using Lindblad solver.\n"); } solve_A = full_A; if (_stiff_solver) { if(nid==0) printf("ERROR! Lindblad-stiff solver untested."); exit(0); } } else { if (nid==0) { printf("No Lindblad terms found, using (more efficient) Schrodinger solver.\n"); } solve_A = ham_A; solve_stiff_A = ham_stiff_A; if (_num_time_dep&&_stiff_solver) { if(nid==0) printf("ERROR! Schrodinger-stiff + timedep solver untested."); exit(0); } } /* Possibly print dense ham. No stabilization is needed? */ if (nid==0) { /* Print dense ham, if it was asked for */ if (_print_dense_ham){ FILE *fp_ham; fp_ham = fopen("ham","w"); if (nid==0){ for (i=0;i<total_levels;i++){ for (j=0;j<total_levels;j++){ fprintf(fp_ham,"%e %e ",PetscRealPart(_hamiltonian[i][j]),PetscImaginaryPart(_hamiltonian[i][j])); } fprintf(fp_ham,"\n"); } } fclose(fp_ham); for (i=0;i<total_levels;i++){ free(_hamiltonian[i]); } free(_hamiltonian); _print_dense_ham = 0; } } /* Remove stabilization if it was previously added */ if (stab_added){ if (nid==0) printf("Removing stabilization...\n"); /* * We add 1.0 in the 0th spot and every n+1 after */ if (nid==0) { row = 0; for (i=0;i<total_levels;i++){ col = i*(total_levels+1); mat_tmp = -1.0 + 0.*PETSC_i; MatSetValue(full_A,row,col,mat_tmp,ADD_VALUES); } } } MatGetOwnershipRange(solve_A,&Istart,&Iend); /* * Explicitly add 0.0 to all diagonal elements; * this fixes a 'matrix in wrong state' message that PETSc * gives if the diagonal was never initialized. */ //if (nid==0) printf("Adding 0 to diagonal elements...\n"); for (i=Istart;i<Iend;i++){ mat_tmp = 0 + 0.*PETSC_i; MatSetValue(solve_A,i,i,mat_tmp,ADD_VALUES); } if(_stiff_solver){ MatGetOwnershipRange(solve_stiff_A,&Istart,&Iend); for (i=Istart;i<Iend;i++){ mat_tmp = 0 + 0.*PETSC_i; MatSetValue(solve_stiff_A,i,i,mat_tmp,ADD_VALUES); } } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -* * Create the timestepping solver and set various options * *- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* * Create timestepping solver context */ TSCreate(PETSC_COMM_WORLD,&ts); TSSetProblemType(ts,TS_LINEAR); /* * Set function to get information at every timestep */ if (_ts_monitor!=NULL){ TSMonitorSet(ts,_ts_monitor,_tsctx,NULL); } /* * Set up ODE system */ TSSetRHSFunction(ts,NULL,TSComputeRHSFunctionLinear,NULL); if(_stiff_solver) { /* TSSetIFunction(ts,NULL,TSComputeRHSFunctionLinear,NULL); */ if (nid==0) { printf("Stiff solver not implemented!\n"); exit(0); } if(nid==0) printf("Using stiff solver - TSROSW\n"); } if(_num_time_dep+_num_time_dep_lin) { for(i=0;i<_num_time_dep;i++){ tmp_real = 0.0; _add_ops_to_mat_ham(tmp_real,solve_A,_time_dep_list[i].num_ops,_time_dep_list[i].ops); } for(i=0;i<_num_time_dep_lin;i++){ tmp_real = 0.0; _add_ops_to_mat_lin(tmp_real,solve_A,_time_dep_list_lin[i].num_ops,_time_dep_list_lin[i].ops); } /* Tell PETSc to assemble the matrix */ MatAssemblyBegin(solve_A,MAT_FINAL_ASSEMBLY); MatAssemblyEnd(solve_A,MAT_FINAL_ASSEMBLY); if (nid==0) printf("Matrix Assembled.\n"); MatDuplicate(solve_A,MAT_COPY_VALUES,&AA); MatAssemblyBegin(AA,MAT_FINAL_ASSEMBLY); MatAssemblyEnd(AA,MAT_FINAL_ASSEMBLY); TSSetRHSJacobian(ts,AA,AA,_RHS_time_dep_ham_p,NULL); } else { /* Tell PETSc to assemble the matrix */ MatAssemblyBegin(solve_A,MAT_FINAL_ASSEMBLY); MatAssemblyEnd(solve_A,MAT_FINAL_ASSEMBLY); if (_stiff_solver){ MatAssemblyBegin(solve_stiff_A,MAT_FINAL_ASSEMBLY); MatAssemblyEnd(solve_stiff_A,MAT_FINAL_ASSEMBLY); /* TSSetIJacobian(ts,solve_stiff_A,solve_stiff_A,TSComputeRHSJacobianConstant,NULL); */ if (nid==0) { printf("Stiff solver not implemented!\n"); exit(0); } } if (nid==0) printf("Matrix Assembled.\n"); TSSetRHSJacobian(ts,solve_A,solve_A,TSComputeRHSJacobianConstant,NULL); } /* Print information about the matrix. */ PetscViewerASCIIOpen(PETSC_COMM_WORLD,NULL,&mat_view); PetscViewerPushFormat(mat_view,PETSC_VIEWER_ASCII_INFO); /* PetscViewerPushFormat(mat_view,PETSC_VIEWER_ASCII_MATLAB); */ /* MatView(solve_A,mat_view); */ /* PetscInt ncols; */ /* const PetscInt *cols; */ /* const PetscScalar *vals; */ /* for(i=0;i<total_levels*total_levels;i++){ */ /* MatGetRow(solve_A,i,&ncols,&cols,&vals); */ /* for (j=0;j<ncols;j++){ */ /* if(PetscAbsComplex(vals[j])>1e-5){ */ /* printf("%d %d %lf %lf\n",i,cols[j],vals[j]); */ /* } */ /* } */ /* MatRestoreRow(solve_A,i,&ncols,&cols,&vals); */ /* } */ if(_stiff_solver){ MatView(solve_stiff_A,mat_view); } PetscViewerPopFormat(mat_view); PetscViewerDestroy(&mat_view); TSSetTimeStep(ts,dt); /* * Set default options, can be changed at runtime */ TSSetMaxSteps(ts,steps_max); TSSetMaxTime(ts,time_max); TSSetTime(ts,init_time); TSSetExactFinalTime(ts,TS_EXACTFINALTIME_STEPOVER); if (_stiff_solver) { TSSetType(ts,TSROSW); } else { TSSetType(ts,TSRK); TSRKSetType(ts,TSRK3BS); } /* If we have gates to apply, set up the event handler. */ if (_num_quantum_gates > 0) { nevents = 1; //Only one event for now (did we cross a gate?) direction = -1; //We only want to count an event if we go from positive to negative terminate = PETSC_FALSE; //Keep time stepping after we passed our event /* Arguments are: ts context, nevents, direction of zero crossing, whether to terminate, * a function to check event status, a function to apply events, private data context. */ TSSetEventHandler(ts,nevents,&direction,&terminate,_QG_EventFunction,_QG_PostEventFunction,NULL); } if (_num_circuits > 0) { nevents = 1; //Only one event for now (did we cross a gate?) direction = -1; //We only want to count an event if we go from positive to negative terminate = PETSC_FALSE; //Keep time stepping after we passed our event /* Arguments are: ts context, nevents, direction of zero crossing, whether to terminate, * a function to check event status, a function to apply events, private data context. */ TSSetEventHandler(ts,nevents,&direction,&terminate,_QC_EventFunction,_QC_PostEventFunction,NULL); } if (_discrete_ec > 0) { nevents = 1; //Only one event for now (did we cross an ec step?) direction = -1; //We only want to count an event if we go from positive to negative terminate = PETSC_FALSE; //Keep time stepping after we passed our event /* Arguments are: ts context, nevents, direction of zero crossing, whether to terminate, * a function to check event status, a function to apply events, private data context. */ TSSetEventHandler(ts,nevents,&direction,&terminate,_DQEC_EventFunction,_DQEC_PostEventFunction,NULL); } /* if (_lindblad_terms) { */ /* nevents = 1; //Only one event for now (did we cross a gate?) */ /* direction = 0; //We only want to count an event if we go from positive to negative */ /* terminate = PETSC_FALSE; //Keep time stepping after we passed our event */ /* TSSetEventHandler(ts,nevents,&direction,&terminate,_Normalize_EventFunction,_Normalize_PostEventFunction,NULL); */ /* } */ TSSetFromOptions(ts); TSSolve(ts,x); TSGetStepNumber(ts,&steps); num_pop = get_num_populations(); populations = malloc(num_pop*sizeof(double)); get_populations(x,&populations); /* if(nid==0){ */ /* printf("Final populations: "); */ /* for(i=0;i<num_pop;i++){ */ /* printf(" %e ",populations[i]); */ /* } */ /* printf("\n"); */ /* } */ /* PetscPrintf(PETSC_COMM_WORLD,"Steps %D\n",steps); */ /* Free work space */ TSDestroy(&ts); if(_num_time_dep+_num_time_dep_lin){ MatDestroy(&AA); } free(populations); PetscLogStagePop(); PetscLogStagePush(post_solve_stage); return; }