📄 ex_conv.c
字号:
/* * Copyright (c) 2005 Sandia Corporation. Under the terms of Contract * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Governement * retains certain rights in this software. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * * Neither the name of Sandia Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *//******************************************************************************* exutils - exodus utilities** entry conditions - ** exit conditions - ** revision history - ** $Id: ex_conv.c 2928 2008-07-11 17:45:07Z friedmud $******************************************************************************/#include <stdlib.h>#include "exodusII.h"#include "exodusII_int.h"/*! \file * this file contains code needed to support the various floating point word * size combinations for computation and i/o that applications might want to * use. the following discussion uses the C type names "float" and "double". * * netCDF supports two floating point word sizes for its files: * - NC_FLOAT - 32 bit IEEE * - NC_DOUBLE - 64 bit IEEE * * now, if you want to write an array of NC_FLOATs, netCDF expects as input * an array of native floats; NC_DOUBLEs require an input array of native * doubles. * * so, suppose you're computing using variables declared double, but you want * to write a netCDF file using NC_FLOATs. you need to copy your array into * a buffer array declared as float, which truncates your data from double to * float (type conversion). then you can pass the buffer array to netCDF * routines for output as NC_FLOATs, and everything will work OK. similarly, * if you are computing in floats but want to write NC_DOUBLEs, you need to * copy your data into a buffer array declared as double, which promotes it * from float to double, and then call the netCDF routine with the buffer array. * * these routines are designed to do this type conversion, based on information * given in the ex_open or ex_create calls. thus, except for when the file is * opened, the user is relieved of the burden of caring about compute word size * (the size of floating point variables used in the application program, and * passed into the EXODUS II calls) and i/o word size (the size of floating * point data as written in the netCDF file). * * this code is supposed to be general enough to handle weird cases like the * cray, where in C (and C++) both floats and doubles are 8 byte quantities. * thus the same array can be passed into a netCDF routine to write either * NC_FLOATs or NC_DOUBLEs. * * \note 16 byte floating point values, such as might be obtained from an ANSI C * "long double", are specifically not handled. Also, I don't know how * the vanilla netCDF interface handles double precision on a CRAY, which * gives 16 byte values, but these routines as written won't be able to * handle it. * */#define NC_FLOAT_WORDSIZE 4#define NC_DOUBLE_WORDSIZE 8struct file_item { int file_id; nc_type netcdf_type_code; int user_compute_wordsize; struct file_item* next;};struct file_item* file_list = NULL;/* * Now recognized at more locations worldwide in this file... */static size_t cur_len = 0; /* in bytes! */static void* buffer_array = NULL;#define FIND_FILE(ptr,id) { ptr = file_list; \ while(ptr) { \ if( ptr->file_id == id ) break; \ ptr = ptr->next; \ } \ }int ex_conv_ini( int exoid, int* comp_wordsize, int* io_wordsize, int file_wordsize ){ char errmsg[MAX_ERR_LENGTH]; struct file_item* new_file; /*! ex_conv_ini() initializes the floating point conversion process. * * \param exoid an integer uniquely identifying the file of interest. * * \param comp_wordsize compute floating point word size in the user's code. * a zero value indicates that the user is requesting the * default float size for the machine. The appropriate * value is chosen and returned in comp_wordsize, and used * in subsequent conversions. a valid but inappropriate * for this parameter cannot be detected. * * \param io_wordsize the desired floating point word size for a netCDF file. * for an existing file, if this parameter doesn't match * the word size of data already stored in the file, a * fatal error is generated. a value of 0 for an existing * file indicates that the word size of the file was not * known a priori, so use whatever is in the file. a value * of 0 for a new file means to use the default size, an * NC_FLOAT (4 bytes). when a value of 0 is specified the * actual value used is returned in io_wordsize. * * \param file_wordsize floating point word size in an existing netCDF file. * a value of 0 should be passed in for a new netCDF file. * * word size parameters are specified in bytes. valid values are 0, 4, and 8: */ /* check to make sure machine word sizes aren't weird */ if ((sizeof(float) != 4 && sizeof(float) != 8) || (sizeof(double) != 4 && sizeof(double) != 8 ) ) { sprintf(errmsg,"Error: unsupported compute word size for file id: %d", exoid); ex_err("ex_conv_ini",errmsg,EX_FATAL); return(EX_FATAL); } /* check to see if requested word sizes are valid */ if (!*io_wordsize ) { if (!file_wordsize ) *io_wordsize = NC_FLOAT_WORDSIZE; else *io_wordsize = file_wordsize; } else if (*io_wordsize != 4 && *io_wordsize != 8 ) { sprintf(errmsg,"Error: unsupported I/O word size for file id: %d",exoid); ex_err("ex_conv_ini",errmsg,EX_FATAL); return(EX_FATAL); } else if (file_wordsize && *io_wordsize != file_wordsize ) { *io_wordsize = file_wordsize; sprintf(errmsg, "Error: invalid I/O word size specified for existing file id: %d", exoid); ex_err("ex_conv_ini",errmsg,EX_MSG); ex_err("ex_conv_ini", " Requested I/O word size overridden.", EX_MSG); } if (!*comp_wordsize ) { *comp_wordsize = sizeof(float); } else if (*comp_wordsize != 4 && *comp_wordsize != 8 ) { ex_err("ex_conv_ini","Error: invalid compute wordsize specified",EX_FATAL); return(EX_FATAL); } new_file = malloc(sizeof(struct file_item)); new_file->file_id = exoid; new_file->user_compute_wordsize = *comp_wordsize; new_file->next = file_list; file_list = new_file; if (*io_wordsize == NC_FLOAT_WORDSIZE) new_file->netcdf_type_code = NC_FLOAT; else new_file->netcdf_type_code = NC_DOUBLE; return(EX_NOERR);}/*............................................................................*//*............................................................................*/void ex_conv_exit( int exoid ){ /*! ex_conv_exit() takes the structure identified by "exoid" out of the linked * list which describes the files that ex_conv_array() knows how to convert. * * \note it is absolutely necessary for ex_conv_array() to be called after * ncclose(), if the parameter used as "exoid" is the id returned from * an ncopen() or nccreate() call, as netCDF reuses file ids! * the best place to do this is ex_close(), which is where I did it. * * \param exoid integer which uniquely identifies the file of interest. */ char errmsg[MAX_ERR_LENGTH]; struct file_item* file = file_list; struct file_item* prev = NULL; exerrval = 0; /* clear error code */ while( file ) { if (file->file_id == exoid ) break; prev = file; file = file->next; } if (!file ) { sprintf(errmsg,"Warning: failure to clear file id %d - not in list.",exoid); ex_err("ex_conv_exit",errmsg,EX_MSG); exerrval = EX_BADFILEID; return; } if (prev ) prev->next = file->next; else file_list = file->next; free( file ); /* * If no other files are opened, any buffer arrays for float/double * conversion ought to be cleaned up. */ if ( !file_list ) { if ( cur_len > 0 ) { free(buffer_array); /* Better not be null if condition true! */ buffer_array = NULL; cur_len = 0; } }}/*............................................................................*//*............................................................................*/nc_type nc_flt_code( int exoid ){ /* nc_flt_code() returns either NC_FLOAT or NC_DOUBLE, based on the parameters * with which ex_conv_ini() was called. nc_flt_code() is used as the nc_type * parameter on ncvardef() calls that define floating point variables. * * "exoid" is some integer which uniquely identifies the file of interest. */ char errmsg[MAX_ERR_LENGTH]; struct file_item* file; exerrval = 0; /* clear error code */ FIND_FILE( file, exoid ); if (!file ) { exerrval = EX_BADFILEID; sprintf(errmsg,"Error: unknown file id %d for nc_flt_code().",exoid); ex_err("nc_flt_code",errmsg,exerrval); return (nc_type) -1; } return file->netcdf_type_code;}int ex_comp_ws( int exoid ){/*! * ex_comp_ws() returns 4 (i.e. sizeof(float)) or 8 (i.e. sizeof(double)), * depending on the value of floating point word size used to initialize * the conversion facility for this file id (exoid). * \param exoid integer which uniquely identifies the file of interest.*/ char errmsg[MAX_ERR_LENGTH]; struct file_item* file; exerrval = 0; /* clear error code */ FIND_FILE( file, exoid ); if (!file ) { exerrval = EX_BADFILEID; sprintf(errmsg,"Error: unknown file id %d",exoid); ex_err("ex_comp_ws",errmsg,exerrval); return(EX_FATAL); } return file->user_compute_wordsize;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -