コード例 #1
0
void Input_CreateAlquimiaInterface(const char* input_file,
                                   AlquimiaInterface* engine_interface,
                                   AlquimiaSizes* engine_sizes,
                                   AlquimiaEngineFunctionality* engine_functionality,
                                   AlquimiaEngineStatus* engine_status)
{
  // Get the engine and other parameters.
  EngineData data;
  int error = ini_parse(input_file, ParseEngineData, &data);
  if (error != 0)
    alquimia_error("Input_CreateAlqumiaInterface: Error parsing input: %s", input_file);

  // Initialize the engine.
  CreateAlquimiaInterface(data.engine_name, engine_interface, engine_status);
  if (engine_status->error != 0) 
    alquimia_error("Input_CreateAlquimiaInterface: %s", engine_status->message);

  // Set it up with our parameters and retrieve functionality.
  engine_interface->Setup(data.input_file,
                          data.hands_off,
                          engine_interface,
                          engine_sizes,
                          engine_functionality,
                          engine_status);

  if (engine_status->error != 0) 
    alquimia_error("Input_CreateAlquimiaInterface: %s", engine_status->message);
}
コード例 #2
0
void Input_GetRegions(const char* input_file,
                      AlquimiaVectorString* region_names)
{
  int error = ini_parse(input_file, ParseRegionName, region_names);
  if (error != 0)
    alquimia_error("Input_GetRegions: Error parsing input: %s", input_file);
}
コード例 #3
0
ファイル: transport.c プロジェクト: jnjohnsonlbl/alquimia-dev
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;
}
コード例 #4
0
void DriverOutput_WriteVectors(DriverOutput* output, 
                               const char* filename,
                               AlquimiaVectorString var_names,
                               AlquimiaVectorDouble* var_vectors)
{
  if (var_names.size == 0)
    alquimia_error("DriverOutput_WriteVectors: no variables to write!");
  for (int i = 1; i < var_names.size; ++i)
  {
    if (var_vectors[i].size != var_vectors[0].size)
    {
      alquimia_error("DriverOutput_WriteVectors: vector %d has %d data, but vector 0 has %d.", 
                     i, var_vectors[i].size, var_vectors[0].size);
    }
  }
  FILE* file = fopen(filename, "w");
  output->Write(var_names, var_vectors, file);
  fclose(file);
}
コード例 #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
static int Run_GlobalImplicit(TransportDriver* driver)
{
  alquimia_error("Globally implicit transport is not yet supported.");
  return -1;
}
コード例 #7
0
TransportDriver* TransportDriver_New(TransportDriverInput* input)
{
  TransportDriver* driver = malloc(sizeof(TransportDriver));

  // Get basic simulation parameters.
  driver->description = AlquimiaStringDup(input->description);
  driver->coupling = input->coupling;
  driver->t_min = input->t_min; 
  driver->t_max = input->t_max;
  driver->max_steps = input->max_steps;
  driver->dt = input->dt;
  driver->cfl = input->cfl_factor;
  driver->verbose = input->verbose;

  // Get grid information.
  driver->x_min = input->x_min; 
  driver->x_max = input->x_max;
  driver->num_cells = input->num_cells;

  // Get material properties.
  driver->porosity = input->porosity;
  driver->saturation = input->saturation;

  // Get flow variables.
  driver->vx = input->velocity;
  driver->temperature = input->temperature;

  // Simulation state.
  driver->time = driver->t_min;
  driver->step = 0;

  // Set up the chemistry engine.
  AllocateAlquimiaEngineStatus(&driver->chem_status);
  CreateAlquimiaInterface(input->chemistry_engine, &driver->chem, &driver->chem_status);
  if (driver->chem_status.error != 0) 
  {
    alquimia_error("TransportDriver_New: %s", driver->chem_status.message);
    return NULL;
  }

  // Set up the engine and get storage requirements.
  AlquimiaEngineFunctionality chem_engine_functionality;
  driver->chem.Setup(input->chemistry_input_file,
                     input->hands_off,
                     &driver->chem_engine,
                     &driver->chem_sizes,
                     &chem_engine_functionality,
                     &driver->chem_status);
  if (driver->chem_status.error != 0) 
  {
    alquimia_error("TransportDriver_New: %s", driver->chem_status.message);
    return NULL;
  }

  // If you want multiple copies of the chemistry engine with
  // OpenMP, verify: chem_data.functionality.thread_safe == true,
  // then create the appropriate number of chem status and data
  // objects.

  // Allocate memory for the chemistry data.
  AllocateAlquimiaProblemMetaData(&driver->chem_sizes, &driver->chem_metadata);
  driver->chem_properties = malloc(sizeof(AlquimiaProperties) * driver->num_cells);
  driver->chem_state = malloc(sizeof(AlquimiaState) * driver->num_cells);
  driver->chem_aux_data = malloc(sizeof(AlquimiaAuxiliaryData) * driver->num_cells);
  driver->chem_aux_output = malloc(sizeof(AlquimiaAuxiliaryOutputData) * driver->num_cells);
  for (int i = 0; i < driver->num_cells; ++i)
  {
    AllocateAlquimiaState(&driver->chem_sizes, &driver->chem_state[i]);
    AllocateAlquimiaProperties(&driver->chem_sizes, &driver->chem_properties[i]);
    AllocateAlquimiaAuxiliaryData(&driver->chem_sizes, &driver->chem_aux_data[i]);
    AllocateAlquimiaAuxiliaryOutputData(&driver->chem_sizes, &driver->chem_aux_output[i]);
  }

  // Metadata.
  driver->chem.GetProblemMetaData(&driver->chem_engine, 
                                  &driver->chem_metadata, 
                                  &driver->chem_status);
  if (driver->chem_status.error != 0)
  {
    alquimia_error("TransportDriver_New: %s", driver->chem_status.message);
    return NULL;
  }

  // Initial condition.
  AllocateAlquimiaGeochemicalCondition(strlen(input->ic_name), 0, 0, &driver->chem_ic);
  strcpy(driver->chem_ic.name, input->ic_name);

  // Boundary conditions.
  if (input->left_bc_name != NULL)
  {
    AllocateAlquimiaGeochemicalCondition(strlen(input->left_bc_name), 0, 0, &driver->chem_left_bc);
    strcpy(driver->chem_left_bc.name, input->left_bc_name);
  }
  AllocateAlquimiaState(&driver->chem_sizes, &driver->chem_left_state);
  AllocateAlquimiaAuxiliaryData(&driver->chem_sizes, &driver->chem_left_aux_data);
  if (input->right_bc_name != NULL)
  {
    AllocateAlquimiaGeochemicalCondition(strlen(input->right_bc_name), 0, 0, &driver->chem_right_bc);
    strcpy(driver->chem_right_bc.name, input->right_bc_name);
  }
  AllocateAlquimiaState(&driver->chem_sizes, &driver->chem_right_state);
  AllocateAlquimiaAuxiliaryData(&driver->chem_sizes, &driver->chem_right_aux_data);

  // Copy the miscellaneous chemistry state information in.
  // NOTE: For now, we only allow one of each of these reactions.
  for (int i = 0; i < driver->num_cells; ++i)
  {
    for (int j = 0; j < driver->chem_state[i].cation_exchange_capacity.size; ++j)
      driver->chem_state[i].cation_exchange_capacity.data[j] = input->cation_exchange_capacity;
    for (int j = 0; j < driver->chem_state[i].surface_site_density.size; ++j)
      driver->chem_state[i].surface_site_density.data[j] = input->surface_site_density;
  }
  for (int j = 0; j < driver->chem_left_state.cation_exchange_capacity.size; ++j)
    driver->chem_left_state.cation_exchange_capacity.data[j] = input->cation_exchange_capacity;
  for (int j = 0; j < driver->chem_left_state.surface_site_density.size; ++j)
    driver->chem_left_state.surface_site_density.data[j] = input->surface_site_density;
  for (int j = 0; j < driver->chem_right_state.cation_exchange_capacity.size; ++j)
    driver->chem_right_state.cation_exchange_capacity.data[j] = input->cation_exchange_capacity;
  for (int j = 0; j < driver->chem_right_state.surface_site_density.size; ++j)
    driver->chem_right_state.surface_site_density.data[j] = input->surface_site_density;

  // Bookkeeping.
  AllocateAlquimiaState(&driver->chem_sizes, &driver->advected_chem_state);
  AllocateAlquimiaAuxiliaryData(&driver->chem_sizes, &driver->advected_chem_aux_data);
  driver->advective_fluxes = malloc(sizeof(double) * driver->chem_sizes.num_primary * (driver->num_cells + 1));

  return driver;
}
コード例 #8
0
TransportDriverInput* TransportDriverInput_New(const char* input_file)
{
  TransportDriverInput* input = malloc(sizeof(TransportDriverInput));
  memset(input, 0, sizeof(TransportDriverInput));

  // Make sure we have some meaningful defaults.
  input->hands_off = true; // Hands-off by default.
  input->t_min = 0.0;
  input->max_steps = INT_MAX;
  input->dt = FLT_MAX;
  input->cfl_factor = 1.0;
  input->porosity = 1.0;
  input->saturation = 1.0;
  input->temperature = 25.0;
  input->velocity = 0.0;
  input->left_bc_name = NULL;
  input->right_bc_name = NULL;
  input->cation_exchange_capacity = 0.0;
  input->surface_site_density = 0.0;
  input->output_type = NULL;
  input->output_file = NULL;

  // Fill in fields by parsing the input file.
  int error = ini_parse(input_file, ParseInput, input);
  if (error != 0)
  {
    TransportDriverInput_Free(input);
    alquimia_error("TransportDriver: Error parsing input: %s", input_file);
  }

  // Verify that our required fields are filled properly.
  if (!input->hands_off)
    alquimia_error("TransportDriver: simulation->hands_off must be set to true at the moment.");
  if (input->t_max <= input->t_min)
    alquimia_error("TransportDriver: simulation->t_max must be greater than simulation->t_min.");
  if (input->max_steps < 0)
    alquimia_error("TransportDriver: simulation->max_steps must be non-negative.");
  if ((input->cfl_factor <= 0.0) || (input->cfl_factor > 1.0))
    alquimia_error("TransportDriver: simulation->cfl_factor must be within (0, 1].");
  if (input->x_max <= input->x_min)
    alquimia_error("TransportDriver: domain->x_max must be greater than domain->x_min.");
  if (input->num_cells <= 0)
    alquimia_error("TransportDriver: domain->num_cells must be positive.");
  if ((input->porosity <= 0.0) || (input->porosity > 1.0))
    alquimia_error("TransportDriver: material->porosity must be within (0, 1].");
  if ((input->saturation <= 0.0) || (input->saturation > 1.0))
    alquimia_error("TransportDriver: material->saturation must be within (0, 1].");
  if (input->temperature <= 0.0)
    alquimia_error("TransportDriver: flow->temperature must be positive.");
  if ((input->left_bc_name == NULL) && (input->right_bc_name == NULL) && (input->velocity != 0.0))
    alquimia_error("TransportDriver: When velocity != 0, left or right boundary condition must be given.");

  // Default output.
  if (input->output_type == NULL)
    input->output_type = AlquimiaStringDup("gnuplot");
  char default_output_file[FILENAME_MAX];
  if (input->output_file == NULL)
  {
    // Find the last '.' in the input filename.
    int dot = strlen(input_file)-1;
    while ((dot > 0) && (input_file[dot] != '.')) --dot;
    char suffix[16];

    // Determine the suffix from the output type.
    if (AlquimiaCaseInsensitiveStringCompare(input->output_type, "gnuplot"))
      sprintf(suffix, ".gnuplot");
    else if (AlquimiaCaseInsensitiveStringCompare(input->output_type, "python"))
      sprintf(suffix, ".py");

    // Append the suffix.
    if (dot == 0)
      sprintf(default_output_file, "%s%s", input_file, suffix);
    else
    {
      memcpy(default_output_file, input_file, sizeof(char) * dot);
      strcat(default_output_file, suffix);
    }

    // Python modules can't have hyphens in their names, so we replace them 
    // with underscores.
    if (AlquimiaCaseInsensitiveStringCompare(input->output_type, "python"))
    {
      int len = strlen(default_output_file);
      for (int i = 0; i < len; ++i)
      {
        if (default_output_file[i] == '-')
          default_output_file[i] = '_';
      }
    }

    input->output_file = AlquimiaStringDup(default_output_file);
  }

  return input;
}