Пример #1
0
void FreeAlquimiaProperties(AlquimiaProperties* props) {
  if (props != NULL) {
    FreeAlquimiaVectorDouble(&(props->isotherm_kd));
    FreeAlquimiaVectorDouble(&(props->freundlich_n));
    FreeAlquimiaVectorDouble(&(props->langmuir_b));
    FreeAlquimiaVectorDouble(&(props->mineral_rate_cnst));
    FreeAlquimiaVectorDouble(&(props->aqueous_kinetic_rate_cnst));
  }
}  /* end FreeAlquimiaProperties() */
Пример #2
0
int main(int argc, char* argv[])
{
    if (argc == 1)
        Usage();

    // Initialize PETSc/MPI for command line options and engines that
    // require it.
    char help[] = "Alquimia advective, nondispersive reactive transport driver";
    PetscInitialize(&argc, &argv, (char*)0, help);
    PetscInitializeFortran();

    char input_file[FILENAME_MAX];
    strncpy(input_file, argv[1], FILENAME_MAX-1);

    // Parse the input file.
    TransportDriverInput* input = TransportDriverInput_New(input_file);
    if (input == NULL)
        alquimia_error("transport: error encountered reading input file '%s'.", input_file);

    // Set up output.
    DriverOutput* output = NULL;
    if (AlquimiaCaseInsensitiveStringCompare(input->output_type, "python"))
        output = PythonDriverOutput_New();
    else if (AlquimiaCaseInsensitiveStringCompare(input->output_type, "gnuplot"))
        output = GnuplotDriverOutput_New();

    // Create a TransportDriver from the parsed input.
    TransportDriver* transport = TransportDriver_New(input);

    // Run the simulation.
    int status = TransportDriver_Run(transport);

    // Get the solution out of the driver and write it out.
    if (output != NULL)
    {
        double final_time;
        AlquimiaVectorString var_names = {.size = 0};
        AlquimiaVectorDouble var_data = {.size = 0};
        TransportDriver_GetSoluteAndAuxData(transport, &final_time, &var_names, &var_data);
        DriverOutput_WriteMulticompVector(output, input->output_file, var_names, var_data);

        FreeAlquimiaVectorString(&var_names);
        FreeAlquimiaVectorDouble(&var_data);
    }

    // Clean up.
    TransportDriverInput_Free(input);
    TransportDriver_Free(transport);
    PetscInt petsc_error = PetscFinalize();
    if (status == EXIT_SUCCESS && petsc_error == 0)
        printf("Success!\n");
    else
        printf("Failed!\n");

    return status;
}
Пример #3
0
void FreeAlquimiaAuxiliaryOutputData(AlquimiaAuxiliaryOutputData* aux_output) {
  if (aux_output != NULL) {
    FreeAlquimiaVectorDouble(&(aux_output->aqueous_kinetic_rate));
    FreeAlquimiaVectorDouble(&(aux_output->mineral_saturation_index));
    FreeAlquimiaVectorDouble(&(aux_output->mineral_reaction_rate));
    FreeAlquimiaVectorDouble(&(aux_output->primary_free_ion_concentration));
    FreeAlquimiaVectorDouble(&(aux_output->primary_activity_coeff));
    FreeAlquimiaVectorDouble(&(aux_output->secondary_free_ion_concentration));
    FreeAlquimiaVectorDouble(&(aux_output->secondary_activity_coeff));
  }
}  /* end FreeAlquimiaAuxiliaryOutputData() */
Пример #4
0
void FreeAlquimiaState(AlquimiaState* state) {
  if (state != NULL) {
    FreeAlquimiaVectorDouble(&(state->total_mobile));
    FreeAlquimiaVectorDouble(&(state->total_immobile));
    FreeAlquimiaVectorDouble(&(state->mineral_volume_fraction));
    FreeAlquimiaVectorDouble(&(state->mineral_specific_surface_area));
    FreeAlquimiaVectorDouble(&(state->cation_exchange_capacity));
    FreeAlquimiaVectorDouble(&(state->surface_site_density));
  }
}  /* end FreeAlquimiaState() */
Пример #5
0
void DriverOutput_WriteMulticompVector(DriverOutput* output, 
                                       const char* filename,
                                       AlquimiaVectorString comp_names,
                                       AlquimiaVectorDouble multicomp_vector)
{
  int num_comps = comp_names.size;
  if ((multicomp_vector.size % num_comps) != 0)
  {
    alquimia_error("DriverOutput_WriteMulticompVector: multicomp_vector data has invalid size for %d components (%d).", 
                   num_comps, multicomp_vector.size);
  }
  int vec_size = multicomp_vector.size / num_comps;
  AlquimiaVectorDouble var_vectors[num_comps];
  for (int i = 0; i < num_comps; ++i)
  {
    AllocateAlquimiaVectorDouble(vec_size, &var_vectors[i]);
    for (int j = 0; j < vec_size; ++j)
      var_vectors[i].data[j] = multicomp_vector.data[num_comps*j+i];
  }
  DriverOutput_WriteVectors(output, filename, comp_names, var_vectors);
  for (int i = 0; i < num_comps; ++i)
    FreeAlquimiaVectorDouble(&var_vectors[i]);
}
Пример #6
0
void TransportDriver_GetSoluteAndAuxData(TransportDriver* driver,
                                         double* time,
                                         AlquimiaVectorString* var_names,
                                         AlquimiaVectorDouble* var_data)
{
  // Destroy the contents of the vectors we're given.
  if (var_names->size > 0)
    FreeAlquimiaVectorString(var_names);
  if (var_data->size > 0)
    FreeAlquimiaVectorDouble(var_data);

  // Construct a list of all variables, which are those in the state and 
  // the auxiliary output data, and fill their data.
  int num_cells = driver->num_cells;
  int num_primary = driver->chem_sizes.num_primary;
  int num_sorbed = driver->chem_sizes.num_sorbed;
  int num_minerals = driver->chem_sizes.num_minerals;
  int num_surface_sites = driver->chem_sizes.num_surface_sites;
  int num_ion_exchange_sites = driver->chem_sizes.num_ion_exchange_sites;
  int num_aqueous_complexes = driver->chem_sizes.num_aqueous_complexes;
  int num_aqueous_kinetics = driver->chem_sizes.num_aqueous_kinetics;
  int num_vars = 1 +                        // grid cell locations 
                 num_primary +              // total mobile
                 num_sorbed +               // total immobile
                 2 * num_minerals +         // mineral volume fractions, specific surface area
                 num_surface_sites +        // surface site density
                 num_ion_exchange_sites +   // cation exchange capacity
                 1 +                        // pH
                 num_aqueous_kinetics +     // aqueous kinetic rate
                 2 * num_minerals +         // mineral saturation index, reaction rate
                 2 * num_primary +          // primary free ion concentration, activity coeff
                 2 * num_aqueous_complexes; // secondary free ion concentration, activity coeff
  int counter = 0;
  AllocateAlquimiaVectorString(num_vars, var_names);
  AllocateAlquimiaVectorDouble(num_vars * driver->num_cells, var_data);
  {
    var_names->data[counter] = AlquimiaStringDup("x");
    for (int j = 0; j < num_cells; ++j)
      var_data->data[num_vars*j + counter] = driver->x_min + (j+0.5) * (driver->x_max - driver->x_min) / driver->num_cells;
    ++counter;
  }
  for (int i = 0; i < num_primary; ++i, ++counter)
  {
    char var_name[1024];
    snprintf(var_name, 1023, "total_mobile[%s]", driver->chem_metadata.primary_names.data[i]);
    var_names->data[counter] = AlquimiaStringDup(var_name);
    for (int j = 0; j < num_cells; ++j)
      var_data->data[num_vars*j + counter] = driver->chem_state[j].total_mobile.data[i];
  }
  for (int i = 0; i < num_sorbed; ++i, ++counter)
  {
    char var_name[1024];
    snprintf(var_name, 1023, "total_immobile[%d]", i);
    var_names->data[counter] = AlquimiaStringDup(var_name);
    for (int j = 0; j < num_cells; ++j)
      var_data->data[num_vars*j + counter] = driver->chem_state[j].total_immobile.data[i];
  }
  for (int i = 0; i < num_minerals; ++i, ++counter)
  {
    char var_name[1024];
    snprintf(var_name, 1023, "mineral_volume_fractions[%s]", driver->chem_metadata.mineral_names.data[i]);
    var_names->data[counter] = AlquimiaStringDup(var_name);
    for (int j = 0; j < num_cells; ++j)
      var_data->data[num_vars*j + counter] = driver->chem_state[j].mineral_volume_fraction.data[i];
  }
  for (int i = 0; i < num_minerals; ++i, ++counter)
  {
    char var_name[1024];
    snprintf(var_name, 1023, "mineral_specific_surface_area[%s]", driver->chem_metadata.mineral_names.data[i]);
    var_names->data[counter] = AlquimiaStringDup(var_name);
    for (int j = 0; j < num_cells; ++j)
      var_data->data[num_vars*j + counter] = driver->chem_state[j].mineral_specific_surface_area.data[i];
  }
  for (int i = 0; i < num_surface_sites; ++i, ++counter)
  {
    char var_name[1024];
    snprintf(var_name, 1023, "surface_site_density[%s]", driver->chem_metadata.surface_site_names.data[i]);
    var_names->data[counter] = AlquimiaStringDup(var_name);
    for (int j = 0; j < num_cells; ++j)
      var_data->data[num_vars*j + counter] = driver->chem_state[j].surface_site_density.data[i];
  }
  for (int i = 0; i < num_ion_exchange_sites; ++i, ++counter)
  {
    char var_name[1024];
    snprintf(var_name, 1023, "cation_exchange_capacity[%s]", driver->chem_metadata.ion_exchange_names.data[i]);
    var_names->data[counter] = AlquimiaStringDup(var_name);
    for (int j = 0; j < num_cells; ++j)
      var_data->data[num_vars*j + counter] = driver->chem_state[j].cation_exchange_capacity.data[i];
  }
  {
    var_names->data[counter] = AlquimiaStringDup("pH");
    for (int j = 0; j < num_cells; ++j)
      var_data->data[num_vars*j + counter] = driver->chem_aux_output[j].pH;
    ++counter;
  }
  for (int i = 0; i < num_aqueous_kinetics; ++i, ++counter)
  {
    char var_name[1024];
    snprintf(var_name, 1023, "aqueous_kinetic_rate[%s]", driver->chem_metadata.aqueous_kinetic_names.data[i]);
    var_names->data[counter] = AlquimiaStringDup(var_name);
    for (int j = 0; j < num_cells; ++j)
      var_data->data[num_vars*j + counter] = driver->chem_aux_output[j].aqueous_kinetic_rate.data[i];
  }
  for (int i = 0; i < num_minerals; ++i, ++counter)
  {
    char var_name[1024];
    snprintf(var_name, 1023, "mineral_saturation_index[%s]", driver->chem_metadata.mineral_names.data[i]);
    var_names->data[counter] = AlquimiaStringDup(var_name);
    for (int j = 0; j < num_cells; ++j)
      var_data->data[num_vars*j + counter] = driver->chem_aux_output[j].mineral_saturation_index.data[i];
  }
  for (int i = 0; i < num_minerals; ++i, ++counter)
  {
    char var_name[1024];
    snprintf(var_name, 1023, "mineral_reaction_rate[%s]", driver->chem_metadata.mineral_names.data[i]);
    var_names->data[counter] = AlquimiaStringDup(var_name);
    for (int j = 0; j < num_cells; ++j)
      var_data->data[num_vars*j + counter] = driver->chem_aux_output[j].mineral_reaction_rate.data[i];
  }
  for (int i = 0; i < num_primary; ++i, ++counter)
  {
    char var_name[1024];
    snprintf(var_name, 1023, "primary_free_ion_concentration[%s]", driver->chem_metadata.primary_names.data[i]);
    var_names->data[counter] = AlquimiaStringDup(var_name);
    for (int j = 0; j < num_cells; ++j)
      var_data->data[num_vars*j + counter] = driver->chem_aux_output[j].primary_free_ion_concentration.data[i];
  }
  for (int i = 0; i < num_primary; ++i, ++counter)
  {
    char var_name[1024];
    snprintf(var_name, 1023, "primary_activity_coeff[%s]", driver->chem_metadata.primary_names.data[i]);
    var_names->data[counter] = AlquimiaStringDup(var_name);
    for (int j = 0; j < num_cells; ++j)
      var_data->data[num_vars*j + counter] = driver->chem_aux_output[j].primary_activity_coeff.data[i];
  }
  for (int i = 0; i < num_aqueous_complexes; ++i, ++counter)
  {
    char var_name[1024];
    snprintf(var_name, 1023, "secondary_free_ion_concentration[%d]", i);
    var_names->data[counter] = AlquimiaStringDup(var_name);
    for (int j = 0; j < num_cells; ++j)
      var_data->data[num_vars*j + counter] = driver->chem_aux_output[j].secondary_free_ion_concentration.data[i];
  }
  for (int i = 0; i < num_aqueous_complexes; ++i, ++counter)
  {
    char var_name[1024];
    snprintf(var_name, 1023, "secondary_activity_coeff[%d]", i);
    var_names->data[counter] = AlquimiaStringDup(var_name);
    for (int j = 0; j < num_cells; ++j)
      var_data->data[num_vars*j + counter] = driver->chem_aux_output[j].secondary_activity_coeff.data[i];
  }
}
Пример #7
0
void FreeAlquimiaAuxiliaryData(AlquimiaAuxiliaryData* aux_data) {
  if (aux_data != NULL) {
    FreeAlquimiaVectorInt(&(aux_data->aux_ints));
    FreeAlquimiaVectorDouble(&(aux_data->aux_doubles));
  }
}  /* end FreeAlquimiaAuxiliaryData() */