Esempio n. 1
0
int
full_solve (hid_t fid, hid_t dataset, hid_t* routeDatasets, hid_t dataspace, hid_t routeDataspace, hid_t datatype, hid_t routeDatatype, int cell_index, const inp_t * input_params, SOURCE_MODE mode,
            const cell_table_t * cell, const net_t * network, const time_steps_t * ts,
            int verbose)
{

  double *abundances = NULL;
  alloc_abundances( network, &abundances ); // Allocate the abundances array; it contains all species.

  rout_t* routes = NULL;
  if (( routes =
        malloc (sizeof (rout_t) *  input_params->output.n_output_species * N_OUTPUT_ROUTES)) == NULL)
    {
      fprintf (stderr, "astrochem: %s:%d: routes allocation failed.\n",
               __FILE__, __LINE__);
      return EXIT_SUCCESS;
    }

  double* output_abundances = NULL;
  if (( output_abundances =
        malloc (sizeof (double) * input_params->output.n_output_species )) == NULL)
    {
      fprintf (stderr, "astrochem: %s:%d: array allocation failed.\n",
               __FILE__, __LINE__);
      return EXIT_FAILURE;
    }

#ifdef HAVE_OPENMP
              omp_set_lock(&lock);
#endif


  // Create the memory dataspace, selecting all output abundances
  hsize_t size = input_params->output.n_output_species;
  hid_t memDataspace = H5Screate_simple(1, &size, NULL);

  // Create the file dataspace, and prepare selection of a chunk of the file
  hid_t fileDataspace = H5Scopy(dataspace);
  hsize_t     count[3]={  1, 1,  input_params->output.n_output_species };

  hsize_t routeSize[2] = { input_params->output.n_output_species, N_OUTPUT_ROUTES };
  hsize_t     routeCount[4]={  1, 1,  input_params->output.n_output_species, N_OUTPUT_ROUTES };
  hid_t routeFileDataspace, routeMemDataspace;
  if (input_params->output.trace_routes)
    {
      // Create the route memory dataspace, selecting all output routes
      routeMemDataspace = H5Screate_simple(2, routeSize, NULL);
      // Create the route file dataspace, and prepare selection of a chunk of the file
      routeFileDataspace = H5Scopy(routeDataspace);
    }

#ifdef HAVE_OPENMP
              omp_unset_lock(&lock);
#endif


  // Initializing abundance
#if 0 //Ultra complicated code
  const species_name_t* species = malloc( input_params->abundances.n_initial_abundances * sizeof(*species));
  double *initial_abundances = malloc( input_params->abundances.n_initial_abundances * sizeof(double) );

  int i;
  for( i = 0; i <  input_params->abundances.n_initial_abundances ; i++ )
    {
      strcpy( network->species_names[input_params->abundances.initial_abundances[i].species_idx ] , species[i] );
      initial_abundances[i] = input_params->abundances.initial_abundances[i].abundance;
    }
  set_initial_abundances( species, 3, initial_abundances, &network, abundances); // Set initial abundances
#else // same thing , without using api
  int i;
  for( i = 0; i <  input_params->abundances.n_initial_abundances ; i++ )
    {
      abundances[ input_params->abundances.initial_abundances[i].species_idx ] = input_params->abundances.initial_abundances[i].abundance;
    }
    
    // Add grain abundances
    int g, gm, gp;
    double gabs;
    g = find_species ("grain", network);
    gm = find_species ("grain(-)", network);
    gp = find_species ("grain(+)", network);
    
    // Check if grain abundances have already been initialized one way or another
    gabs=0.0;
    if(g>=0) gabs += abundances[ g ];
    if(gm>=0) gabs += abundances[ gm ];
    if(gp>=0) gabs += abundances[ gp ];
    
    if(gabs == 0.0) {
    	// Grains have not been initialized
    	// Check that grains are defined in our network, and if so, set the grain abundance
    	if(g>=0)
    		abundances[ g ] = input_params->phys.grain_abundance;
    }
#endif


  double min_nh;                 /* Minimum density */

  /* Compute the minimum density to set the absolute tolerance of the
     solver */
  min_nh = cell->nh[0];
  if (mode == DYNAMIC)
    {
      int i;

      for (i = 1; i < ts->n_time_steps; i++)
        {
          if (cell->nh[i] < min_nh)
            {
              min_nh = cell->nh[i];
            }
        }
    }

  astrochem_mem_t astrochem_mem;
  cell_t cell_unik;
  cell_unik.av = cell->av[0];
  cell_unik.nh = cell->nh[0];
  cell_unik.tgas = cell->tgas[0];
  cell_unik.tdust = cell->tdust[0];
  if( solver_init( &cell_unik, network, &input_params->phys, abundances, min_nh, input_params->solver.abs_err,  input_params->solver.rel_err, &astrochem_mem ) != EXIT_SUCCESS )
    {
      return EXIT_FAILURE;
    }
  else
    {
      int i, j;

      /* Solve the system for each time step. */
      for (i = 0; i < ts->n_time_steps; i++)
        {


          if (i!=0 && mode == DYNAMIC)
            {
              cell_unik.av = cell->av[i];
              cell_unik.nh = cell->nh[i];
              cell_unik.tgas = cell->tgas[i];
              cell_unik.tdust = cell->tdust[i];

              if( solve( &astrochem_mem, network, abundances,  ts->time_steps[i], &cell_unik, verbose ) != EXIT_SUCCESS )
                {
                  return EXIT_FAILURE;
                }
            }
          else
            {
              if( solve( &astrochem_mem, network, abundances,  ts->time_steps[i], NULL, verbose ) != EXIT_SUCCESS )
                {
                  return EXIT_FAILURE;
                }
            }


          /* Fill the array of abundances with the output species
             abundances. Ignore species that are not in the
             network. Abundance that are lower than MIN_ABUNDANCES are
             set to 0. */

          for (j = 0; j < input_params->output.n_output_species; j++)
            {
              if (mode == STATIC)
                {
                  output_abundances[j] =
                   (double) NV_Ith_S (astrochem_mem.y, input_params->output.output_species_idx[j]) / cell->nh[0];
                }
              else
                {
                  output_abundances[j] =
                   (double) NV_Ith_S (astrochem_mem.y, input_params->output.output_species_idx[j]) / cell->nh[i];
                }
              if (output_abundances[j] < MIN_ABUNDANCE)
                output_abundances[j] = 0.;

#ifdef HAVE_OPENMP
              omp_set_lock(&lock);
#endif
              // Select a chunk of the file
              hsize_t     start[3]={  cell_index, i, 0 };
              H5Sselect_hyperslab( fileDataspace, H5S_SELECT_SET, start, NULL, count , NULL );

              // Write the chunk
              H5Dwrite(dataset, datatype, memDataspace, fileDataspace, H5P_DEFAULT,
                       output_abundances );

#ifdef HAVE_OPENMP
              omp_unset_lock(&lock);
#endif

            }

          /* Compute the rate of each formation/destruction route for
             each output specie. */

          if (input_params->output.trace_routes)
            {
              for (j = 0; j < input_params->output.n_output_species; j++)
                {
                  int k;
                  int l;
                  for (l = 0; l < N_OUTPUT_ROUTES; l++)
                    {
                      routes[ j*N_OUTPUT_ROUTES + l ].formation.rate = 0;
                      routes[ j*N_OUTPUT_ROUTES + l ].destruction.rate = 0;
                    }
                  for (k = 0; k < network->n_reactions; k++)
                    {
                      /* If the species is a product of the
                         reaction then compute the formation
                         rate. If the rate is greater than the
                         smallest rate in the formation route
                         structure, we add the current reaction
                         number and rate to that structure. */

                      bool specie_in_products = false;
                      int p;
                      for( p = 0; p < MAX_PRODUCTS; p++ )
                        {
                          if( network->reactions[k].products[p] ==  input_params->output.output_species_idx[j])
                            {
                              specie_in_products = true;
                              break;
                            }
                        }
                      if( specie_in_products )
                        {
                          r_t formation_route;
                          double min_rate;
                          unsigned int min_rate_index;
                          if (network->reactions[k].reaction_type == 0)
                            {
                              formation_route.rate = astrochem_mem.params.reac_rates[k];
                              formation_route.rate *=
                               NV_Ith_S (astrochem_mem.y, network->reactions[k].reactants[0]);
                            }
                          else if (network->reactions[k].reaction_type == 23)
                            {
                              formation_route.rate = astrochem_mem.params.reac_rates[k];
                            }
                          else
                            {
                              formation_route.rate = astrochem_mem.params.reac_rates[k];
                              int r;
                              for( r = 0; r < MAX_REACTANTS; r++ )
                                {
                                  if( network->reactions[k].reactants[r] != -1 )
                                    {
                                      formation_route.rate *=
                                       NV_Ith_S (astrochem_mem.y, network->reactions[k].reactants[r]);
                                    }
                                }
                            }
                          formation_route.reaction_no =
                           network->reactions[k].reaction_no;
                          min_rate = routes[ j*N_OUTPUT_ROUTES  ].formation.rate;
                          min_rate_index = 0;
                          for (l = 1; l < N_OUTPUT_ROUTES; l++)
                            {
                              if (routes[ j*N_OUTPUT_ROUTES + l ].formation.rate <
                                  min_rate)
                                {
                                  min_rate =
                                   routes[ j*N_OUTPUT_ROUTES + l ].formation.rate;
                                  min_rate_index = (unsigned int) l;
                                }
                            }
                          if (formation_route.rate > min_rate)
                            {
                              routes[ j*N_OUTPUT_ROUTES + min_rate_index ].formation.rate = formation_route.rate;
                              routes[ j*N_OUTPUT_ROUTES + min_rate_index ].formation.reaction_no = formation_route.reaction_no;
                            }
                        }

                      /* If the species is reactant of the reaction
                         then compute the destruction rate. */
                      bool species_in_reactants = false;
                      int r;
                      for ( r = 0; r < MAX_REACTANTS; r++ )
                        {
                          if ( network->reactions[k].reactants[r] == input_params->output.output_species_idx[j])
                            {
                              species_in_reactants = true;
                              break;
                            }
                        }
                      if( species_in_reactants )
                        {
                          r_t destruction_route;
                          double min_rate;
                          unsigned int min_rate_index;

                          if (network->reactions[k].reaction_type == 0)
                            {
                              destruction_route.rate = astrochem_mem.params.reac_rates[k];
                              destruction_route.rate *=
                               NV_Ith_S (astrochem_mem.y, network->reactions[k].reactants[0]);
                            }
                          else if (network->reactions[k].reaction_type == 23)
                            {
                              destruction_route.rate = astrochem_mem.params.reac_rates[k];
                            }
                          else
                            {
                              destruction_route.rate = astrochem_mem.params.reac_rates[k];
                              for ( r = 0; r < MAX_REACTANTS; r++ )
                                {
                                  if (network->reactions[k].reactants[r] != -1)
                                    {
                                      destruction_route.rate *=
                                       NV_Ith_S (astrochem_mem.y, network->reactions[k].reactants[r]);
                                    }
                                }
                            }
                          destruction_route.reaction_no =
                           network->reactions[k].reaction_no;

                          min_rate = routes[ j*N_OUTPUT_ROUTES  ].destruction.rate;
                          min_rate_index = 0;
                          for (l = 1; l < N_OUTPUT_ROUTES; l++)
                            {
                              if (routes[ j*N_OUTPUT_ROUTES + l ].destruction.rate <
                                  min_rate)
                                {
                                  min_rate =
                                   routes[ j*N_OUTPUT_ROUTES + l ].destruction.rate;
                                  min_rate_index = (unsigned int) l;
                                }
                            }
                          if (destruction_route.rate > min_rate)
                            {
                              routes[ j*N_OUTPUT_ROUTES + min_rate_index ].destruction.rate = destruction_route.rate;
                              routes[ j*N_OUTPUT_ROUTES + min_rate_index ].destruction.reaction_no = destruction_route.reaction_no;
                            }
                        }
                    }
                }
#ifdef HAVE_OPENMP
              omp_set_lock(&lock);
#endif
              // Selecting a chunk of the file
              hsize_t     routeStart[4]={  cell_index, i, 0, 0 };
              H5Sselect_hyperslab( routeFileDataspace, H5S_SELECT_SET, routeStart, NULL, routeCount , NULL );

              int spec_idx;
              for( spec_idx = 0; spec_idx < input_params->output.n_output_species; spec_idx++ )
                {
                  // Writing in each route datasets
                  H5Dwrite( routeDatasets[ spec_idx ], routeDatatype, routeMemDataspace, routeFileDataspace, H5P_DEFAULT,
                            routes );
                }

#ifdef HAVE_OPENMP
              omp_unset_lock(&lock);
#endif
            }
        }

    }
#ifdef HAVE_OPENMP
  omp_set_lock(&lock);
#endif
  // Cleaning up hdf5
  H5Sclose(memDataspace);
  H5Sclose(fileDataspace);
  if (input_params->output.trace_routes)
    {
      H5Sclose(routeMemDataspace);
      H5Sclose(routeFileDataspace);
    }
#ifdef HAVE_OPENMP
  omp_unset_lock(&lock);
#endif
  // Free
  free( output_abundances );
  free( routes );
  free_abundances( abundances );
  solver_close( &astrochem_mem );
  return EXIT_SUCCESS;
}
Esempio n. 2
0
int
main (void)
{
  FILE *f;
  net_t network;
  int verbose = 0;

  /* Create the input.ini, source.mdl and network_chm files */

  f = fopen ("network.chm", "w");
  fprintf (f, "# This network file was created by full_solve_test\n");
  fprintf (f, "X -> Y    1e-9    0    0    2    1\n");
  fclose (f);

  /* Read them */
  if( read_network ("network.chm", &network, verbose) )
    {
      return EXIT_FAILURE;
    }

  phys_t phys;
  phys.cosmic = 1.3e-17;
  phys.chi = 1;
  phys.grain_size = 1e-5;
  phys.grain_abundance = 0;

  double abs_err, rel_err;
  abs_err = 1e-15;
  rel_err = 1e-6;

  const char* species[]  = { "X", "Y" };
  const double initial_abundances[] = { 1.0, 0.0 };

  double *abundances;
  alloc_abundances( &network, &abundances ); // Allocate the abundances array; it contains all species.
  set_initial_abundances(species, 2, initial_abundances, &network, abundances); // Set initial abundances

  double density = 1000;
  double av = 20;
  double temperature = 10;

  cell_t cell;
  cell.nh = density;
  cell.av = av;
  cell.tgas = temperature;
  cell.tdust = temperature; // Assume tgas = tdust in this specific case

  astrochem_mem_t astrochem_mem;

  if( solver_init( &cell, &network, &phys, abundances , density, abs_err, rel_err, &astrochem_mem ) != EXIT_SUCCESS )
    {
      return EXIT_FAILURE;
   }
  int i;
  double time = 0;
  for( i = 0; i < 1000 ; i++ )
    {

      time+= 10;
      if( solve( &astrochem_mem, &network, abundances, time, NULL,verbose) != EXIT_SUCCESS )
        {
          return EXIT_FAILURE;
        }
      double x_abundance;
      double y_abundance;
      double x_abs_err;
      double x_rel_err;
      double y_abs_err;
      double y_rel_err;

      x_abundance = 1.0 * exp (-1e-9 *  time);
      y_abundance = 1.0 - x_abundance;
      x_abs_err = fabs( abundances[0] - x_abundance);
      y_abs_err = fabs( abundances[1] - y_abundance);
      x_rel_err = x_abs_err / x_abundance;
      y_rel_err = y_abs_err / y_abundance;

      /* Errors accumulate after each time step, so the actual error
         on the abundance is somewhat larger than the solver
         relative tolerance. */
      if ((x_abs_err > abs_err) && (x_rel_err > rel_err * 5e2))
        {
          fprintf (stderr, "full_solve_test: %s:%d: incorrect abundance at t=%12.15e: expected %12.15e, got %12.15e.\n",
                   __FILE__, __LINE__, time, x_abundance, abundances[0]);
          solver_close( &astrochem_mem );
          free_abundances( abundances );
          free_network (&network);
          return EXIT_FAILURE;
        }

      if ((y_abs_err > abs_err) && (y_rel_err > rel_err * 5e2))
        {
          fprintf (stderr, "full_solve_test: %s:%d: incorrect abundance at t=%12.6e: expected %12.6e, got %12.6e.\n",
                   __FILE__, __LINE__, time, y_abundance, abundances[1]);
          solver_close( &astrochem_mem );
          free_abundances( abundances );
          free_network (&network);
          return EXIT_FAILURE;
        }
    }
  solver_close( &astrochem_mem );
  free_abundances( abundances );
  free_network (&network);
  return EXIT_SUCCESS;
}