コード例 #1
0
ファイル: sampling.c プロジェクト: rforge/epidemics
/* 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 */
コード例 #2
0
ファイル: populations.c プロジェクト: rforge/epidemics
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;
}
コード例 #3
0
ファイル: populations.c プロジェクト: rforge/epidemics
/* 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");
		}
	}
}
コード例 #4
0
ファイル: epidemics.c プロジェクト: rforge/epidemics
/* 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);
}
コード例 #5
0
ファイル: epidemics.c プロジェクト: rforge/epidemics
/* 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);
}
コード例 #6
0
ファイル: epidemics.c プロジェクト: rforge/epidemics
/* 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);
}
コード例 #7
0
ファイル: solver.c プロジェクト: 0tt3r/QuaC
/*
 * 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;
}
コード例 #8
0
ファイル: solver.c プロジェクト: 0tt3r/QuaC
/*
 * 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;
}