// Returns true if the given value string matches a "true" boolean value. static bool ValueIsTrue(const char* value) { return ((strcmp(value, "1") == 0) || AlquimiaCaseInsensitiveStringCompare(value, "true") || AlquimiaCaseInsensitiveStringCompare(value, "yes") || AlquimiaCaseInsensitiveStringCompare(value, "on")) ? true : false; }
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; }
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; }