You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
543 lines
19 KiB
543 lines
19 KiB
/*
|
|
* Copyright(C) 1999-2020 National Technology & Engineering Solutions
|
|
* of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with
|
|
* NTESS, the U.S. Government retains certain rights in this software.
|
|
*
|
|
* See packages/seacas/LICENSE for details
|
|
*/
|
|
/*--------------------------------------------------------------------------*/
|
|
/* Purpose: Determine file types for command files and read in the parallel */
|
|
/* ExodusII command file. */
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
#include "copy_string_cpp.h"
|
|
#include "fmt/ostream.h"
|
|
#include "nem_spread.h"
|
|
#include "ps_pario_const.h" // for PIO_Info, Parallel_IO, etc
|
|
#include "rf_allo.h" // for array_alloc
|
|
#include "rf_io_const.h" // for ExoFile, etc
|
|
#include "scopeguard.h"
|
|
#include <cstdio> // for nullptr, stderr, etc
|
|
#include <cstdlib> // for exit, realloc
|
|
#include <cstring> // for strtok, strchr, strstr, etc
|
|
#include <rf_allo.h>
|
|
|
|
#define TLIST_CNT 5
|
|
|
|
constexpr int MAX_INPUT_STR_LN = 4096; /* maximum string length for read_string() */
|
|
|
|
/*****************************************************************************/
|
|
int read_mesh_file_name(const char *filename)
|
|
{
|
|
/* local declarations */
|
|
FILE *file_cmd = nullptr;
|
|
char inp_line[MAX_INPUT_STR_LN + 1];
|
|
char inp_copy[MAX_INPUT_STR_LN + 1];
|
|
|
|
/* Open the file */
|
|
if ((file_cmd = fopen(filename, "r")) == nullptr) {
|
|
return -1;
|
|
}
|
|
ON_BLOCK_EXIT(fclose, file_cmd);
|
|
|
|
/* Begin parsing the input file */
|
|
while (fgets(inp_line, MAX_INPUT_STR_LN, file_cmd) != nullptr) {
|
|
/* skip any line that is a comment */
|
|
if ((inp_line[0] != '#') && (inp_line[0] != '\n')) {
|
|
|
|
copy_string(inp_copy, inp_line);
|
|
clean_string(inp_line, " \t");
|
|
char *cptr = strtok(inp_line, "\t=");
|
|
/****** The input ExodusII file name ******/
|
|
if (token_compare(cptr, "input fem file") != 0) {
|
|
if (ExoFile.empty()) {
|
|
cptr = strtok(nullptr, "\t=");
|
|
strip_string(cptr, " \t\n");
|
|
ExoFile = std::string(cptr);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
template <typename T, typename INT>
|
|
int read_pexoII_info(NemSpread<T, INT> &spreader, const char *filename)
|
|
|
|
/*
|
|
* This function reads the ASCII parallel-exodus command file.
|
|
*
|
|
* Input
|
|
* -----
|
|
* filename - The name of the command file.
|
|
*/
|
|
{
|
|
/* local declarations */
|
|
FILE *file_cmd = nullptr;
|
|
char inp_line[MAX_INPUT_STR_LN + 1];
|
|
char inp_copy[MAX_INPUT_STR_LN + 1];
|
|
char *cptr;
|
|
char *cptr2;
|
|
char *cptr3;
|
|
int i;
|
|
int icnt;
|
|
int tlist_alloc;
|
|
|
|
/***************************** BEGIN EXECUTION ******************************/
|
|
|
|
/* Open the file */
|
|
if ((file_cmd = fopen(filename, "r")) == nullptr) {
|
|
return -1;
|
|
}
|
|
ON_BLOCK_EXIT(fclose, file_cmd);
|
|
|
|
/* Begin parsing the input file */
|
|
while (fgets(inp_line, MAX_INPUT_STR_LN, file_cmd)) {
|
|
/* skip any line that is a comment */
|
|
if ((inp_line[0] != '#') && (inp_line[0] != '\n')) {
|
|
|
|
copy_string(inp_copy, inp_line);
|
|
clean_string(inp_line, " \t");
|
|
cptr = strtok(inp_line, "\t=");
|
|
/****** The input ExodusII file name ******/
|
|
if (token_compare(cptr, "input fem file")) {
|
|
if (ExoFile.empty()) {
|
|
cptr = strtok(nullptr, "\t=");
|
|
strip_string(cptr, " \t\n");
|
|
ExoFile = std::string(cptr);
|
|
}
|
|
}
|
|
/****** The input NemesisI load balance file name ******/
|
|
else if (token_compare(cptr, "lb file")) {
|
|
if (Exo_LB_File.empty()) {
|
|
cptr = strtok(nullptr, "\t=");
|
|
strip_string(cptr, " \t\n");
|
|
Exo_LB_File = std::string(cptr);
|
|
}
|
|
}
|
|
/****** The scalar results ExodusII file name ******/
|
|
else if (token_compare(cptr, "scalar results fem file")) {
|
|
if (Exo_Res_File.empty()) {
|
|
cptr = strtok(nullptr, "\t=");
|
|
strip_string(cptr, " \t\n");
|
|
Exo_Res_File = std::string(cptr);
|
|
}
|
|
}
|
|
/****** The parallel results ExodusII file name ******/
|
|
else if (token_compare(cptr, "parallel results file base name")) {
|
|
if (Output_File_Base_Name.empty()) {
|
|
cptr = strtok(nullptr, "\t=");
|
|
strip_string(cptr, " \t\n");
|
|
Output_File_Base_Name = std::string(cptr);
|
|
}
|
|
}
|
|
/****** The Number of Processors ******/
|
|
else if (token_compare(cptr, "number of processors")) {
|
|
if (spreader.Proc_Info[0] < 0) {
|
|
cptr = strtok(nullptr, "\t=");
|
|
strip_string(cptr, " \t\n");
|
|
if (sscanf(cptr, "%d", &(spreader.Proc_Info[0])) != 1) {
|
|
fmt::print(stderr,
|
|
"{}: ERROR, can\'t interpret int for number of"
|
|
" Processors.\n",
|
|
__func__);
|
|
exit(1);
|
|
}
|
|
}
|
|
}
|
|
/****** The File extension to use for spread files ******/
|
|
else if (token_compare(cptr, "file extension for spread files")) {
|
|
cptr = strtok(nullptr, "\t=");
|
|
strip_string(cptr, " \t\n");
|
|
PIO_Info.Exo_Extension = std::string(cptr);
|
|
}
|
|
|
|
/****** Is There a Scalar Mesh File to Use ******/
|
|
else if (token_compare(cptr, "use scalar mesh file")) {
|
|
if (Gen_Flag < 0) {
|
|
cptr = strtok(nullptr, "\t=");
|
|
strip_string(cptr, " \t\n");
|
|
if (Gen_Flag < 0) {
|
|
if (token_compare(cptr, "yes")) {
|
|
Gen_Flag = 1;
|
|
}
|
|
else {
|
|
Gen_Flag = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/****** The Debug reporting level ******/
|
|
else if (token_compare(cptr, "debug")) {
|
|
if (Debug_Flag < 0) {
|
|
cptr = strtok(nullptr, "\t=");
|
|
strip_string(cptr, " \t\n");
|
|
if (sscanf(cptr, "%d", &Debug_Flag) != 1) {
|
|
fmt::print(stderr, "{}: ERROR, can\'t interpret int for Debug_Flag\n", __func__);
|
|
exit(1);
|
|
}
|
|
}
|
|
}
|
|
/****** Restart Time List ******/
|
|
else if (token_compare(cptr, "restart info")) {
|
|
|
|
cptr = strchr(cptr, '\0');
|
|
cptr++;
|
|
|
|
/*
|
|
* If there is a list, then need to change the comma's in
|
|
* the list to blank spaces so that the strtok below works
|
|
* correctly. So, search for commas between the beginning
|
|
* delimiter, "{", and the end delimiter, "}", and change
|
|
* them to blank spaces.
|
|
*/
|
|
cptr2 = strchr(cptr, '{');
|
|
if (cptr2 != nullptr) {
|
|
icnt = strlen(cptr2);
|
|
for (i = 0; i < icnt; i++) {
|
|
if (*cptr2 == '}') {
|
|
break;
|
|
}
|
|
if (*cptr2 == ',') {
|
|
*cptr2 = ' ';
|
|
}
|
|
cptr2++;
|
|
}
|
|
}
|
|
|
|
strip_string(cptr, " \t\n=");
|
|
cptr = strtok(cptr, ",");
|
|
|
|
/* Loop until all the suboptions have been specified */
|
|
while (cptr != nullptr) {
|
|
strip_string(cptr, " \t\n");
|
|
string_to_lower(cptr, '\0');
|
|
|
|
/* check if the user wants to specifically turn this off */
|
|
if (strcmp(cptr, "off") == 0) {
|
|
if (spreader.Restart_Info.Flag < 0) {
|
|
spreader.Restart_Info.Flag = 0;
|
|
spreader.Restart_Info.Num_Times = 0;
|
|
}
|
|
}
|
|
/* check if the user wants all of the time steps */
|
|
else if (strcmp(cptr, "all") == 0) {
|
|
if (spreader.Restart_Info.Flag < 0) {
|
|
spreader.Restart_Info.Flag = 1;
|
|
spreader.Restart_Info.Num_Times = -1; /* -1 designates read all times */
|
|
}
|
|
}
|
|
/* IGNORED check if the user wants move variable in blocks IGNORED */
|
|
else if (strstr(cptr, "block")) {
|
|
cptr2 = strchr(cptr, '=');
|
|
if (cptr2 == nullptr) {
|
|
fmt::print(stderr, "fatal: must specify a value with \"block\"");
|
|
exit(1);
|
|
}
|
|
cptr2++;
|
|
}
|
|
/* check if the user has a list of time indices to get */
|
|
else if (strstr(cptr, "list")) {
|
|
/* "{" defines the beginning of the group designator */
|
|
cptr2 = strchr(cptr, '{');
|
|
if (cptr2 == nullptr) {
|
|
fmt::print(stderr, "fatal: list start designator \"{\" not found");
|
|
exit(1);
|
|
}
|
|
cptr2++;
|
|
cptr3 = strchr(cptr, '}');
|
|
if (cptr3 == nullptr) {
|
|
fmt::print(stderr, "fatal: list end designator \"}\" not found");
|
|
exit(1);
|
|
}
|
|
*cptr3 = '\0';
|
|
|
|
/* Allocate the time list */
|
|
spreader.Restart_Info.Time_Idx.resize(TLIST_CNT);
|
|
tlist_alloc = TLIST_CNT;
|
|
spreader.Restart_Info.Num_Times = 0;
|
|
|
|
while (cptr2) {
|
|
/* first check to see if they want to get the last time index */
|
|
if (strncmp(cptr2, "last", 4) == 0) {
|
|
icnt = 0;
|
|
spreader.Restart_Info.Time_Idx[spreader.Restart_Info.Num_Times] = 0;
|
|
}
|
|
else {
|
|
icnt = sscanf(cptr2, "%d",
|
|
&(spreader.Restart_Info.Time_Idx[spreader.Restart_Info.Num_Times]));
|
|
}
|
|
|
|
if (icnt >= 0) {
|
|
(spreader.Restart_Info.Num_Times)++;
|
|
}
|
|
|
|
if (spreader.Restart_Info.Num_Times >= tlist_alloc) {
|
|
tlist_alloc += TLIST_CNT;
|
|
spreader.Restart_Info.Time_Idx.resize(tlist_alloc);
|
|
}
|
|
/* move to the next blank space */
|
|
cptr3 = strchr(cptr2, ' ');
|
|
if (cptr3) {
|
|
/* find the next non-blank space */
|
|
while (*cptr3 == ' ') {
|
|
cptr3++;
|
|
}
|
|
}
|
|
cptr2 = cptr3;
|
|
}
|
|
}
|
|
else {
|
|
fmt::print(stderr, "warning: unknown restart info suboption {}", cptr);
|
|
exit(1);
|
|
}
|
|
cptr = strtok(nullptr, ",");
|
|
}
|
|
} /* End "if (token_compare(cptr, "restart time list"))" */
|
|
/****** Reserved Space for Variables ******/
|
|
else if (token_compare(cptr, "reserve space")) {
|
|
|
|
cptr = strchr(cptr, '\0');
|
|
cptr++;
|
|
strip_string(cptr, " \t\n=");
|
|
cptr = strtok(cptr, ",");
|
|
|
|
while (cptr != nullptr) {
|
|
strip_string(cptr, " \t\n");
|
|
string_to_lower(cptr, '=');
|
|
if (strstr(cptr, "nodal")) {
|
|
cptr2 = strchr(cptr, '=');
|
|
if (cptr2 == nullptr) {
|
|
fmt::print(stderr, "Error: integer value must be specified for"
|
|
" reserve space.\n");
|
|
return 0;
|
|
}
|
|
cptr2++;
|
|
icnt = sscanf(cptr2, "%d", &Num_Nod_Var);
|
|
if ((icnt <= 0) || (Num_Nod_Var < 0)) {
|
|
fmt::print(stderr, "Error: Invalid value for nodal variable\n");
|
|
return 0;
|
|
}
|
|
}
|
|
else if (strstr(cptr, "elemental")) {
|
|
cptr2 = strchr(cptr, '=');
|
|
if (cptr2 == nullptr) {
|
|
fmt::print(stderr, "Error: integer value must be specified for"
|
|
" reserve space.\n");
|
|
return 0;
|
|
}
|
|
cptr2++;
|
|
icnt = sscanf(cptr2, "%d", &Num_Elem_Var);
|
|
if ((icnt <= 0) || (Num_Elem_Var < 0)) {
|
|
fmt::print(stderr, "Error: Invalid value for elemental variable\n");
|
|
return 0;
|
|
}
|
|
}
|
|
else if (strstr(cptr, "global")) {
|
|
cptr2 = strchr(cptr, '=');
|
|
if (cptr2 == nullptr) {
|
|
fmt::print(stderr, "Error: integer value must be specified for"
|
|
" reserve space.\n");
|
|
return 0;
|
|
}
|
|
cptr2++;
|
|
icnt = sscanf(cptr2, "%d", &Num_Glob_Var);
|
|
if ((icnt <= 0) || (Num_Glob_Var < 0)) {
|
|
fmt::print(stderr, "Error: Invalid value for global variable\n");
|
|
return 0;
|
|
}
|
|
}
|
|
else if (strstr(cptr, "nodeset")) {
|
|
cptr2 = strchr(cptr, '=');
|
|
if (cptr2 == nullptr) {
|
|
fmt::print(stderr, "Error: integer value must be specified for"
|
|
" reserve space.\n");
|
|
return 0;
|
|
}
|
|
cptr2++;
|
|
icnt = sscanf(cptr2, "%d", &Num_Nset_Var);
|
|
if ((icnt <= 0) || (Num_Nset_Var < 0)) {
|
|
fmt::print(stderr, "Error: Invalid value for nodeset variable\n");
|
|
return 0;
|
|
}
|
|
}
|
|
else if (strstr(cptr, "sideset")) {
|
|
cptr2 = strchr(cptr, '=');
|
|
if (cptr2 == nullptr) {
|
|
fmt::print(stderr, "Error: integer value must be specified for"
|
|
" reserve space.\n");
|
|
return 0;
|
|
}
|
|
cptr2++;
|
|
icnt = sscanf(cptr2, "%d", &Num_Sset_Var);
|
|
if ((icnt <= 0) || (Num_Sset_Var < 0)) {
|
|
fmt::print(stderr, "Error: Invalid value for sideset variable\n");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
cptr = strtok(nullptr, ",");
|
|
|
|
} /* End "while (cptr != nullptr)" */
|
|
} /* End "else if (token_compare(cptr, "reserve space"))" */
|
|
/****** Parallel Disk Information ******/
|
|
else if (token_compare(cptr, "parallel disk info")) {
|
|
|
|
cptr = strchr(cptr, '\0');
|
|
cptr++;
|
|
strip_string(cptr, " \t\n=");
|
|
cptr = strtok(cptr, ",");
|
|
strip_string(cptr, " \t\n");
|
|
string_to_lower(cptr, '=');
|
|
|
|
/* the first sub-option must be "number" */
|
|
if (!strstr(cptr, "number")) {
|
|
fmt::print(stderr, "Error: First sup-option for disk info must be "
|
|
"\"number\"\n");
|
|
return 0;
|
|
}
|
|
|
|
cptr2 = strchr(cptr, '=');
|
|
if (cptr2 == nullptr) {
|
|
fmt::print(stderr, "Error: integer value must be specified for"
|
|
" reserve space.\n");
|
|
return 0;
|
|
}
|
|
cptr2++;
|
|
icnt = sscanf(cptr2, "%d", &(PIO_Info.Num_Dsk_Ctrlrs));
|
|
if ((icnt <= 0) || (PIO_Info.Num_Dsk_Ctrlrs <= 0)) {
|
|
fmt::print(stderr, "Error: Invalid value for # of raid controllers\n");
|
|
return 0;
|
|
}
|
|
|
|
cptr = strtok(nullptr, ",");
|
|
while (cptr != nullptr) {
|
|
strip_string(cptr, " \t\n");
|
|
string_to_lower(cptr, '=');
|
|
if (strstr(cptr, "list")) {
|
|
/*
|
|
* So, "number" references the length of the list, and
|
|
* I need to do some shuffling to make the new form
|
|
* work with the old code.
|
|
*/
|
|
PIO_Info.Dsk_List_Cnt = PIO_Info.Num_Dsk_Ctrlrs;
|
|
PIO_Info.Num_Dsk_Ctrlrs = 0;
|
|
|
|
/* "{" defines the beginning of the list */
|
|
cptr = strchr(cptr, '{');
|
|
if (cptr == nullptr) {
|
|
fmt::print(stderr, "Error: disk list must be specified\n");
|
|
return 0;
|
|
}
|
|
cptr++;
|
|
|
|
/* allocate memory for to hold the values */
|
|
PIO_Info.Dsk_List = reinterpret_cast<int *>(
|
|
array_alloc(__FILE__, __LINE__, 1, PIO_Info.Dsk_List_Cnt, sizeof(int)));
|
|
for (i = 0; i < (PIO_Info.Dsk_List_Cnt - 1); i++) {
|
|
sscanf(cptr, "%d", &(PIO_Info.Dsk_List[i]));
|
|
cptr = strtok(nullptr, ", \t;");
|
|
}
|
|
/* last one is a special case */
|
|
sscanf(cptr, "%d}", &(PIO_Info.Dsk_List[i]));
|
|
}
|
|
else if (strstr(cptr, "offset")) {
|
|
cptr2 = strchr(cptr, '=');
|
|
if (cptr2 == nullptr) {
|
|
fmt::print(stderr, "Error: value must be specified with the "
|
|
"\"offset\" option.\n");
|
|
return 0;
|
|
}
|
|
cptr2++;
|
|
icnt = sscanf(cptr2, "%d", &(PIO_Info.PDsk_Add_Fact));
|
|
if ((icnt <= 0) || (PIO_Info.PDsk_Add_Fact < 0)) {
|
|
fmt::print(stderr, "Error: Invalid value for offset\n");
|
|
return 0;
|
|
}
|
|
}
|
|
else if (strstr(cptr, "zeros")) {
|
|
PIO_Info.Zeros = 1;
|
|
}
|
|
else if (strstr(cptr, "nosubdirectory")) {
|
|
PIO_Info.NoSubdirectory = 1;
|
|
}
|
|
else if (strstr(cptr, "stage_off")) {
|
|
PIO_Info.Staged_Writes = false;
|
|
}
|
|
else if (strstr(cptr, "stage_on")) {
|
|
PIO_Info.Staged_Writes = true;
|
|
}
|
|
|
|
cptr = strtok(nullptr, ",");
|
|
}
|
|
} /* End "else if (token_compare(cptr, "parallel disk info"))" */
|
|
else if (token_compare(cptr, "parallel file location")) {
|
|
cptr = strchr(cptr, '\0');
|
|
cptr++;
|
|
strip_string(cptr, " \t\n=");
|
|
cptr = strtok(cptr, ",");
|
|
|
|
while (cptr != nullptr) {
|
|
strip_string(cptr, " \t\n");
|
|
string_to_lower(cptr, '=');
|
|
if (strstr(cptr, "root")) {
|
|
cptr2 = strchr(cptr, '=');
|
|
if (cptr2 == nullptr) {
|
|
fmt::print(stderr, "fatal: must specify a path with \"root\"");
|
|
return 0;
|
|
}
|
|
cptr2++;
|
|
if (strlen(cptr2) == 0) {
|
|
fmt::print(stderr, "fatal: invalid path name specified with"
|
|
" \"root\"");
|
|
return 0;
|
|
}
|
|
PIO_Info.Par_Dsk_Root = std::string(cptr2);
|
|
}
|
|
if (strstr(cptr, "subdir")) {
|
|
cptr2 = strchr(cptr, '=');
|
|
if (cptr2 == nullptr) {
|
|
fmt::print(stderr, "fatal: must specify a path with \"subdir\"");
|
|
return 0;
|
|
}
|
|
cptr2++;
|
|
if (strlen(cptr2) == 0) {
|
|
fmt::print(stderr, "fatal: invalid path name specified with"
|
|
" \"subdir\"");
|
|
return 0;
|
|
}
|
|
PIO_Info.Par_Dsk_SubDirec = std::string(cptr2);
|
|
if (PIO_Info.Par_Dsk_SubDirec.back() != '/') {
|
|
PIO_Info.Par_Dsk_SubDirec += '/';
|
|
}
|
|
}
|
|
|
|
cptr = strtok(nullptr, ",");
|
|
}
|
|
}
|
|
|
|
} /* End "if(inp_line[0] != '#')" */
|
|
} /* End "while(fgets(inp_line, MAX_INPUT_STR_LN, file_cmd))" */
|
|
|
|
if (Output_File_Base_Name.empty() && !Exo_LB_File.empty()) {
|
|
// User did not specify a base name. Use the basenmae of the
|
|
// Exo_LB_File instead.
|
|
Output_File_Base_Name = Exo_LB_File;
|
|
|
|
// If there is an extension, strip it off...
|
|
size_t found = Output_File_Base_Name.find_last_of('.');
|
|
if (found != std::string::npos) {
|
|
Output_File_Base_Name = Output_File_Base_Name.substr(0, found);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
template int read_pexoII_info(NemSpread<float, int> &spreader, const char *filename);
|
|
template int read_pexoII_info(NemSpread<double, int> &spreader, const char *filename);
|
|
|
|
template int read_pexoII_info(NemSpread<double, int64_t> &spreader, const char *filename);
|
|
template int read_pexoII_info(NemSpread<float, int64_t> &spreader, const char *filename);
|
|
|