Use udunits package for units conversions

Initial checkin of using udunits for measurement units conversions.  Replaced
our conversion code in ICG and swig code to use udunits.

Also added code to convert unit symbols that we used in Trick that are different
names in udunits.

Added a sim_object that will eventually allow users to specify a custom
set of files to read units information.

refs #231
This commit is contained in:
Alex Lin 2016-05-05 14:49:49 -05:00
parent d144907b49
commit 684f0e6bdc
23 changed files with 423 additions and 150 deletions

View File

@ -53,7 +53,8 @@ SIM_SERV_DIRS = \
${TRICK_HOME}/trick_source/sim_services/SimTime \
${TRICK_HOME}/trick_source/sim_services/ThreadBase \
${TRICK_HOME}/trick_source/sim_services/Timer \
${TRICK_HOME}/trick_source/sim_services/Units \
${TRICK_HOME}/trick_source/sim_services/UdUnits \
${TRICK_HOME}/trick_source/sim_services/UnitsMap \
${TRICK_HOME}/trick_source/sim_services/VariableServer \
${TRICK_HOME}/trick_source/sim_services/Zeroconf \
${TRICK_HOME}/trick_source/sim_services/include \

21
include/trick/UdUnits.hh Normal file
View File

@ -0,0 +1,21 @@
#ifndef UDUNITS_HH
#define UDUNITS_HH
#include <udunits2/udunits2.h>
#include <string>
namespace Trick {
class UdUnits {
public:
static ut_system * get_u_system() ;
int read_default_xml() ;
int read_user_xml(std::string) ;
protected:
static ut_system * u_system ; // ** system of units
} ;
}
#endif

View File

@ -82,6 +82,7 @@
#include "trick/StripChart.hh"
#include "trick/RtiStager.hh"
#include "trick/RtiExec.hh"
#include "trick/UdUnits.hh"
#include "trick/UnitsMap.hh"
#include "trick/Zeroconf.hh"
#include "trick/Flag.h"

View File

@ -41,7 +41,7 @@
t->ref.num_index_left = 1 ;
t->ref.ref_type = REF_ADDRESS ;
t->ref.attr->units = strdup("--") ;
t->ref.attr->units = strdup("1") ;
//cout << "returning a structured swig_ref" << std::endl ;
$result = SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIG_TypeQuery("_p_swig_ref"), SWIG_POINTER_OWN);
@ -101,7 +101,7 @@
t->ref.attr->num_index = 2 ;
t->ref.attr->index[0].size = $1_dim0 ;
t->ref.attr->index[1].size = 0 ;
t->ref.attr->units = strdup("--") ;
t->ref.attr->units = strdup("1") ;
t->ref.create_add_path = 0 ;
t->ref.num_index = 0 ;
@ -140,7 +140,7 @@
t->ref.num_index_left = 2 ;
t->ref.ref_type = REF_ADDRESS ;
t->ref.attr->units = strdup("--") ;
t->ref.attr->units = strdup("1") ;
$result = SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIG_TypeQuery("_p_swig_ref"), SWIG_POINTER_OWN);
}
@ -179,7 +179,7 @@
t->ref.num_index_left = 2 ;
t->ref.ref_type = REF_ADDRESS ;
t->ref.attr->units = strdup("--") ;
t->ref.attr->units = strdup("1") ;
//cout << "returning a structured swig_ref" << std::endl ;
$result = SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIG_TypeQuery("_p_swig_ref"), SWIG_POINTER_OWN);

View File

@ -6,18 +6,32 @@
#ifndef SWIG_INT_TEMPLATES_HH
#define SWIG_INT_TEMPLATES_HH
#include "trick/UdUnits.hh"
#include <udunits2/udunits2.h>
template< class S , typename T > static int convert_and_set( T & output , void * my_argp , std::string to_units ) {
int ret = 0 ;
S * temp_m = reinterpret_cast< S * >(my_argp) ;
if ( temp_m->units.compare("--") ) {
try {
Unit converter(temp_m->units.c_str()) ;
output = (T)converter.Convert_to( temp_m->value , to_units.c_str()) ;
if ( temp_m->units.compare("1") ) {
ut_unit * from = ut_parse(Trick::UdUnits::get_u_system(), temp_m->units.c_str(), UT_ASCII) ;
if ( !from ) {
PyErr_SetString(PyExc_AttributeError,(std::string("could not covert from units "+temp_m->units).c_str()));
return -1 ;
}
catch (Unit::CONVERSION_ERROR & ce_err ) {
PyErr_SetString(PyExc_TypeError,"Units conversion error");
ret = -1;
ut_unit * to = ut_parse(Trick::UdUnits::get_u_system(), to_units.c_str(), UT_ASCII) ;
if ( !to ) {
PyErr_SetString(PyExc_AttributeError,(std::string("could not covert to units "+to_units).c_str()));
return -1 ;
}
cv_converter * converter = ut_get_converter(from,to) ;
if ( converter ) {
output = (T)cv_convert_double(converter, temp_m->value ) ;
cv_free(converter) ;
} else {
PyErr_SetString(PyExc_AttributeError,"Units conversion Error");
return -1 ;
}
} else {
output = (T)temp_m->value ;

View File

@ -5,8 +5,12 @@
#define UNITS_ATTACH_I
%inline %{
#include "trick/Unit.hh"
#include <frameobject.h>
#include <udunits2/udunits2.h>
#include "trick/swig/swig_double.hh"
std::string map_trick_units_to_udunits( std::string orig_units ) ;
%}
%inline %{
@ -19,6 +23,19 @@ PyObject * attach_units(PyObject * in_units_obj , PyObject * in_object) {
if ( PyString_Check(in_units_obj) ) {
in_units = PyString_AsString(in_units_obj) ;
std::string new_units = map_trick_units_to_udunits(in_units) ;
if ( in_units.compare(new_units) ) {
PyThreadState *tstate = PyThreadState_GET();
std::string file_name ;
int line_no = 0 ;
if (NULL != tstate && NULL != tstate->frame) {
file_name = PyString_AsString(tstate->frame->f_code->co_filename);
line_no = PyFrame_GetLineNumber(tstate->frame) ;
}
std::cout << "\033[31mUnits converted from [" << in_units << "] to [" << new_units << "] "
<< file_name << ":" << line_no << "\033[0m" << std::endl ;
in_units = new_units ;
}
}
if ( PyList_Check(in_object)) {
@ -32,19 +49,62 @@ PyObject * attach_units(PyObject * in_units_obj , PyObject * in_object) {
result_obj = SWIG_NewPointerObj(SWIG_as_voidptr(container), SWIG_TypeQuery("swig_double *") , SWIG_POINTER_OWN);
} else if ( SWIG_IsOK(SWIG_ConvertPtr(in_object, &my_argp,SWIG_TypeQuery("swig_double *"), 0 ))) {
swig_double * temp_m = reinterpret_cast< swig_double * >(my_argp) ;
if ( temp_m->units.compare("--") ) {
try {
Unit converter(temp_m->units.c_str()) ;
temp_m->value = converter.Convert_to( temp_m->value , in_units.c_str()) ;
if ( temp_m->units.compare("1") ) {
ut_unit * from = ut_parse(Trick::UdUnits::get_u_system(), temp_m->units.c_str(), UT_ASCII) ;
if ( !from ) {
PyErr_SetString(PyExc_AttributeError,(std::string("could not covert from units "+temp_m->units).c_str()));
return NULL ;
}
ut_unit * to = ut_parse(Trick::UdUnits::get_u_system(), in_units.c_str(), UT_ASCII) ;
if ( !to ) {
PyErr_SetString(PyExc_AttributeError,(std::string("could not covert to units "+in_units).c_str()));
return NULL ;
}
cv_converter * converter = ut_get_converter(from,to) ;
if ( converter ) {
temp_m->value = cv_convert_double(converter, temp_m->value ) ;
temp_m->units = in_units ;
cv_free(converter) ;
} else {
PyErr_SetString(PyExc_AttributeError,"Units conversion Error");
return NULL ;
}
catch (Unit::CONVERSION_ERROR & ce_err ) {
PyErr_SetString(PyExc_TypeError,"improper units conversion");
return NULL;
}
ut_free(from) ;
ut_free(to) ;
} else {
temp_m->units = in_units ;
}
result_obj = SWIG_NewPointerObj(SWIG_as_voidptr(new swig_double(*temp_m)), SWIG_TypeQuery("swig_double *") , SWIG_POINTER_OWN);
} else if ( SWIG_IsOK(SWIG_ConvertPtr(in_object, &my_argp,SWIG_TypeQuery("swig_int *"), 0 ))) {
swig_int * temp_m = reinterpret_cast< swig_int * >(my_argp) ;
if ( temp_m->units.compare("1") ) {
ut_unit * from = ut_parse(Trick::UdUnits::get_u_system(), temp_m->units.c_str(), UT_ASCII) ;
if ( !from ) {
PyErr_SetString(PyExc_AttributeError,(std::string("could not covert from units "+temp_m->units).c_str()));
return NULL ;
}
ut_unit * to = ut_parse(Trick::UdUnits::get_u_system(), in_units.c_str(), UT_ASCII) ;
if ( !to ) {
PyErr_SetString(PyExc_AttributeError,(std::string("could not covert to units "+in_units).c_str()));
return NULL ;
}
cv_converter * converter = ut_get_converter(from,to) ;
if ( converter ) {
temp_m->value = (long long)cv_convert_double(converter, (double)temp_m->value ) ;
temp_m->units = in_units ;
cv_free(converter) ;
} else {
PyErr_SetString(PyExc_AttributeError,"Units conversion Error");
return NULL ;
}
ut_free(from) ;
ut_free(to) ;
} else {
temp_m->units = in_units ;
}
result_obj = SWIG_NewPointerObj(SWIG_as_voidptr(new swig_int(*temp_m)), SWIG_TypeQuery("swig_int *") , SWIG_POINTER_OWN);
} else if ( PyTuple_Check(in_object)) {
unsigned int size = PyTuple_Size(in_object) ;
result_obj = PyTuple_New(size) ;

View File

@ -87,6 +87,7 @@ sub gte (@) {
$def{"TRICK_GTE_EXT"} = "" ;
$def{"TRICK_HOME"} = "$trick_home" ;
$def{"TRICK_HOST_CPU_USER_SUFFIX"} = "" ;
$def{"TRICK_ICGFLAGS"} = "" ;
$def{"TRICK_ICG_NOCOMMENT"} = "" ;
$def{"TRICK_ICG_EXCLUDE"} = "" ;
$def{"TRICK_SWIG_EXCLUDE"} = "" ;

View File

@ -39,7 +39,7 @@ export TRICK_SWIG_EXCLUDE
export TRICK_EXT_LIB_DIRS
export TRICK_GTE_EXT
export TRICK_HOST_CPU := $(shell export TRICK_CC=$(TRICK_CC) && $(TRICK_HOME)/bin/trick-gte TRICK_HOST_CPU)
export TRICK_EXEC_LINK_LIBS = ${PTHREAD_LIBS} $(PYTHON_LIB) $(PLATFORM_LIBS) -lm -ldl -lz
export TRICK_EXEC_LINK_LIBS = ${PTHREAD_LIBS} $(PYTHON_LIB) $(PLATFORM_LIBS) -lm -ldl -lz -ludunits2
export TRICK_LIBS = ${RPATH} -L${TRICK_LIB_DIR} -ltrick -ltrick_pyip -ltrick_comm -ltrick_math -ltrick_units -ltrick_mm
export TRICK_SYSTEM_CFLAGS
export TRICK_SYSTEM_CXXFLAGS

View File

@ -52,15 +52,15 @@ S_source.hh $(CURDIR)/build/S_define.lib_deps : S_define | build
# Automatic and manual ICG rules
$(CURDIR)/build/Makefile_io_src : | S_source.hh
$(PRINT_ICG)
$(ECHO_CMD)${TRICK_HOME}/bin/trick-ICG -m ${TRICK_CXXFLAGS} ${TRICK_SYSTEM_CXXFLAGS} S_source.hh
$(ECHO_CMD)${TRICK_HOME}/bin/trick-ICG -m ${TRICK_ICGFLAGS} ${TRICK_CXXFLAGS} ${TRICK_SYSTEM_CXXFLAGS} S_source.hh
ICG:
$(PRINT_ICG)
$(ECHO_CMD)${TRICK_HOME}/bin/trick-ICG -m ${TRICK_CXXFLAGS} ${TRICK_SYSTEM_CXXFLAGS} S_source.hh
$(ECHO_CMD)${TRICK_HOME}/bin/trick-ICG -m ${TRICK_ICGFLAGS} ${TRICK_CXXFLAGS} ${TRICK_SYSTEM_CXXFLAGS} S_source.hh
force_ICG:
$(PRINT_ICG)
$(ECHO_CMD)${TRICK_HOME}/bin/trick-ICG -f -m ${TRICK_CXXFLAGS} ${TRICK_SYSTEM_CXXFLAGS} S_source.hh
$(ECHO_CMD)${TRICK_HOME}/bin/trick-ICG -f -m ${TRICK_ICGFLAGS} ${TRICK_CXXFLAGS} ${TRICK_SYSTEM_CXXFLAGS} S_source.hh
# Build dependencies for recreating S_source.hh
$(CURDIR)/build/S_define.deps :

View File

@ -92,6 +92,7 @@ a replacement SimObject will create an uncompilable sim.
##include "trick/Zeroconf.hh"
##include "trick/RtiStager.hh"
##include "trick/RtiExec.hh"
##include "trick/UdUnits.hh"
// This is a user header block. Code here is copied without processing to S_source.hh
%header{
@ -787,6 +788,18 @@ class UnitTestSimObject : public Trick::SimObject {
UnitTestSimObject trick_utest ;
#endif
#ifndef TRICK_NO_UDUNITS
class UdUnitsSimObject : public Trick::SimObject {
public:
Trick::UdUnits udunits ;
UdUnitsSimObject() {
P65535 ("default_data") udunits.read_default_xml() ;
}
} ;
UdUnitsSimObject trick_udunits;
#endif
// Include optional external clocks
#include "sim_objects/TPROClock.sm"
#include "sim_objects/BC635Clock.sm"

View File

@ -12,7 +12,26 @@
#include "Utilities.hh"
// Provides units check capability.
#include "trick/units_conv.h"
std::string map_trick_units_to_udunits( std::string orig_units ) ;
extern llvm::cl::opt< bool > units_truth_is_scary ;
static ut_system * get_u_system() {
ut_system * u_system ;
/* Initialize the udunits-2 library */
ut_set_error_message_handler(ut_ignore) ;
if( (u_system = ut_read_xml( NULL )) == NULL ) {
std::cout << "Error initializing udunits-2 unit system" << std::endl ;
exit(-1);
}
ut_set_error_message_handler(ut_write_to_stderr) ;
return u_system ;
}
ut_system * FieldDescription::u_system = get_u_system() ;
FieldDescription::FieldDescription(
std::string in_container_class ) :
@ -20,7 +39,7 @@ FieldDescription::FieldDescription(
field_offset(0) ,
field_width(0) ,
inherited(false) ,
units("--") ,
units("1") ,
line_no(0) ,
io(3) ,
type_enum_string("TRICK_VOID") ,
@ -133,14 +152,45 @@ void FieldDescription::parseComment(std::string comment) {
get_regex_field(comment , "@?trick_io[\\({]([^\\)}]+)[\\)}](.*)" , 2) ;
}
//std::cout << "4. " << comment << std::endl ;
ret_str = get_regex_field(comment , "@?trick_units[\\({]([^\\)}]+)[\\)}]" , 1) ;
if ( ! ret_str.empty()) {
units = ret_str ;
//std::cout << "go for trick_units " << units << std::endl ;
units_found = true ;
comment = get_regex_field(comment , "(.*)@?trick_units[\\({]([^\\)}]+)[\\)}]" , 1) +
get_regex_field(comment , "@?trick_units[\\({]([^\\)}]+)[\\)}](.*)" , 2) ;
/*
Units can include parenthesis now. We need to match the parenthesis in
trick_units() to get the whole units string.
*/
std::size_t tu_string = comment.find("trick_units") ;
if ( tu_string != std::string::npos ) {
std::size_t ustart = tu_string + std::string("trick_units").length() ;
std::size_t uend = ustart + 1 ;
std::stack<char> parens ;
parens.push( comment[ustart]);
while ( ! parens.empty() and (uend < comment.length())) {
switch ( comment[uend] ) {
case '(':
parens.push('(') ;
break ;
case ')':
if (parens.top() == '(') {
parens.pop() ;
}
break ;
case '}':
if (parens.top() == '{') {
parens.pop() ;
}
break ;
}
uend++ ;
}
if ( parens.empty() ) {
units = comment.substr(ustart + 1 , uend - ustart - 2) ;
units_found = true ;
// If we have "@trick_units" include the "@" sign for erasure.
if ( tu_string > 0 and comment[tu_string-1] == '@' ) {
tu_string -= 1 ;
}
comment.erase(tu_string , uend - tu_string) ;
} else {
std::cout << "unmatched parenthesis for trick_units" << std::endl ;
}
}
if ( ! io_found ) {
@ -174,19 +224,33 @@ void FieldDescription::parseComment(std::string comment) {
}
}
// Test if we have valid units. We need to have found a units string and an io spec not zero
// Possible todo is to create a map of valid units so we don't have to retest each string.
if ( units_found and io != 0 and (valid_units.find(units) == valid_units.end())) {
Units_t * test_units = new_units(units.c_str()) ;
if ( test_units == NULL ) {
// If the units are invalid write an error message and change the units to "--"
std::cout << "\033[31mBad units specification (" << units << "): " << file_name << ":" << line_no
<< "\033[0m" << std::endl ;
units = "--" ;
if ( !units.compare("--") ) {
units = "1" ;
} else {
// If the units are valid, free the memory allocated by new_units.
CONV_FREE(test_units) ;
valid_units.insert(units) ;
// map old unit names to new names
std::string new_units = map_trick_units_to_udunits(units) ;
if ( units.compare(new_units) ) {
if ( ! units_truth_is_scary ) {
std::cout << "\033[31mUnits converted from [" << units << "] to [" << new_units << "] "
<< file_name << ":" << line_no << "\033[0m" << std::endl ;
}
units = new_units ;
}
ut_unit * test_units = ut_parse(u_system, units.c_str() , UT_ASCII) ;
if ( test_units == NULL ) {
// If the units are invalid write an error message and change the units to "1"
std::cout << "\033[31mBad units specification [" << units << "] " << file_name << ":" << line_no
<< "\033[0m" << std::endl ;
units = "1" ;
} else {
// If the units are valid, free the memory allocated by new_units.
ut_free(test_units) ;
valid_units.insert(units) ;
}
}
}

View File

@ -6,6 +6,8 @@
#include <map>
#include <stdint.h>
#include <udunits2/udunits2.h>
#include "ConstructValues.hh"
#include "clang/Basic/Specifiers.h"
@ -166,6 +168,7 @@ class FieldDescription : public ConstructValues {
/** Internal function to execute regular expression */
std::string get_regex_field(std::string input , const char * expr , unsigned int index) ;
static ut_system * u_system ;
} ;
#endif

View File

@ -39,7 +39,7 @@ void PrintFileContentsBase::print_units_map(std::ofstream & outfile, ClassValues
outfile << " Trick::UnitsMap * units_map_ptr __attribute__((unused)) = Trick::UnitsMap::units_map() ;\n" ;
for ( fit = cv->field_begin() ; fit != cv->field_end() ; fit++ ) {
if ( determinePrintAttr(cv , *fit) and (*fit)->getUnits().compare("--")) {
if ( determinePrintAttr(cv , *fit) and (*fit)->getUnits().compare("1")) {
FieldDescription * fdes = *fit ;
outfile << " units_map_ptr->add_param(\"" ;
printContainerClasses( outfile, cv , "__" ) ;

View File

@ -25,13 +25,12 @@
#include "PrintAttributesFactory.hh"
#include "Utilities.hh"
#include "trick/units_conv.h"
/* Command line arguments. These work better as globals, as suggested in llvm/CommandLine documentation */
llvm::cl::list< std::string > include_dirs("I", llvm::cl::Prefix, llvm::cl::desc("Include directory"),
llvm::cl::value_desc("directory")) ;
llvm::cl::list< std::string > defines("D", llvm::cl::Prefix, llvm::cl::desc("Defines"),
llvm::cl::value_desc("define")) ;
llvm::cl::opt< bool > units_truth_is_scary ("units-truth-is-scary", llvm::cl::desc("Don't print units conversion messages")) ;
llvm::cl::opt< bool > sim_services_flag ("s", llvm::cl::desc("Gernerate io_src for Trick core headers")) ;
llvm::cl::opt< bool > force ("f", llvm::cl::desc("Force all io_src files to be generated")) ;
llvm::cl::opt< int > attr_version ("v", llvm::cl::desc("Select version of attributes to produce. 10 and 13 are valid"), llvm::cl::init(10)) ;
@ -44,7 +43,7 @@ llvm::cl::list< std::string > input_file_names(llvm::cl::Positional, llvm::cl::d
llvm::cl::list< std::string > sink(llvm::cl::Sink, llvm::cl::ZeroOrMore) ;
llvm::cl::list< std::string > pre_compiled_headers("include", llvm::cl::Prefix, llvm::cl::desc("pre-compiled headers"),
llvm::cl::value_desc("pre_compiled_headers")) ;
llvm::cl::opt< bool > show_units ("u", llvm::cl::desc("List recognized units")) ;
//llvm::cl::opt< bool > show_units ("u", llvm::cl::desc("List recognized units")) ;
void ICG_version() {
std::cout << "Trick Interface Code Generator (ICG) 13.dev" << std::endl ;
@ -83,10 +82,12 @@ int main( int argc , char * argv[] ) {
return -1 ;
}
/*
if ( show_units ) {
list_units() ;
return 0 ;
}
*/
if ( input_file_names.empty() ) {
std::cerr << "No header file specified" << std::endl ;

View File

@ -8,7 +8,7 @@ CXXFLAGS := -g -I$(shell $(LLVM_HOME)/bin/llvm-config --includedir) -D__STDC_CON
CLANG_MINOR_GTEQ5 := $(shell expr `$(LLVM_HOME)/bin/llvm-config --version | cut -f2 -d. ` \>= 5 )
LLVMLDFLAGS := $(shell $(LLVM_HOME)/bin/llvm-config --ldflags)
LLVMLDFLAGS := $(shell $(LLVM_HOME)/bin/llvm-config --ldflags) -ludunits2
OBJ_DIR := object_$(TRICK_HOST_CPU)
@ -21,10 +21,8 @@ ICG := ${TRICK_HOME}/bin/trick-ICG
SOURCES = $(wildcard *.cpp)
OBJECTS = $(addprefix $(OBJ_DIR)/, $(subst .cpp,.o,$(SOURCES)))
# Include the units conversion source from trick_utils.
UNITS_CONV_SRC = ${TRICK_HOME}/trick_source/trick_utils/units/src/units_conv.c
UNITS_CONV_INCLUDE = -I${TRICK_HOME}/include
UNITS_CONV_OBJ = $(OBJ_DIR)/units_conv.o
UDUNITS_OBJS = \
$(OBJ_DIR)/map_trick_units_to_udunits.o
CLANGLIBS = \
-lclangFrontend \
@ -55,8 +53,8 @@ endif
all: $(ICG)
$(ICG): $(OBJECTS) $(UNITS_CONV_OBJ)
$(CXX) -o $@ $(OBJECTS) $(UNITS_CONV_OBJ) $(LLVMLDFLAGS) $(CLANGLIBS)
$(ICG): $(OBJECTS) $(UDUNITS_OBJS)
$(CXX) -o $@ $(OBJECTS) $(UNITS_CONV_OBJ) $(UDUNITS_OBJS) $(LLVMLDFLAGS) $(CLANGLIBS)
# Only FieldDescription.cpp includes the units conversion header.
$(OBJ_DIR)/FieldDescription.o : CXXFLAGS += $(UNITS_CONV_INCLUDE)
@ -66,8 +64,8 @@ $(OBJ_DIR)/main.o : CXXFLAGS += $(UNITS_CONV_INCLUDE)
$(OBJECTS): $(OBJ_DIR)/%.o : %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@
$(UNITS_CONV_OBJ): $(UNITS_CONV_SRC)
$(CC) $(UNITS_CONV_INCLUDE) -c $< -o $@
$(UDUNITS_OBJS): $(OBJ_DIR)/%.o : ${TRICK_HOME}/trick_source/sim_services/UdUnits/%.cpp
$(CXX) -c $< -o $@
$(OBJECTS) $(UNITS_CONV_OBJ) : | $(OBJ_DIR)

View File

@ -0,0 +1,5 @@
include ${TRICK_HOME}/share/trick/makefiles/Makefile.common
include ${TRICK_HOME}/share/trick/makefiles/Makefile.tricklib
-include Makefile_deps

View File

@ -0,0 +1,27 @@
#include <iostream>
#include "trick/UdUnits.hh"
ut_system * Trick::UdUnits::u_system = NULL ;
ut_system * Trick::UdUnits::get_u_system() {
return u_system ;
}
int Trick::UdUnits::read_default_xml() {
/* Initialize the udunits-2 library */
ut_set_error_message_handler(ut_ignore) ;
if( (u_system = ut_read_xml( NULL )) == NULL ) {
std::cerr << "Error initializing udunits-2 unit system" << std::endl ;
return -1 ;
}
ut_set_error_message_handler(ut_write_to_stderr) ;
return 0 ;
}
int Trick::UdUnits::read_user_xml(std::string file_name) {
return 0 ;
}

View File

@ -0,0 +1,96 @@
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <numeric>
static std::map< std::string, std::string> init_map_old_to_ud() {
std::map< std::string, std::string> init_map ;
init_map["r"] = "rad" ;
init_map["d"] = "degree" ;
init_map["as"] = "arcsecond" ;
init_map["am"] = "arcminute" ;
init_map["rev"] = "revolution" ;
init_map["M"] = "m" ; // really? people still using this? (yes)
init_map["n.m."] = "nmile" ;
init_map["sl"] = "slug" ;
init_map["mt"] = "t" ;
init_map["lbm"] = "lb" ;
init_map["oz"] = "ozf" ;
init_map["v"] = "V" ;
init_map["F"] = "degF" ;
init_map["C"] = "degC" ;
init_map["R"] = "degR" ;
init_map["TNT"] = "ton_TNT" ;
init_map["Wh"] = "(W*h)" ;
init_map["kWh"] = "(kW*h)" ;
init_map["gal"] = "gallon" ;
init_map["one"] = "1" ;
init_map["cnt"] = "count" ;
return init_map ;
}
static std::map< std::string, std::string> old_to_ud = init_map_old_to_ud() ;
static void tokenize_units(const std::string& str,
std::vector<std::string>& tokens,
const std::string& delimiters = " ")
{
// Skip delimiters at beginning.
std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
if ( lastPos != 0 ) {
tokens.push_back(str.substr(0, lastPos));
}
// Find first "non-delimiter".
std::string::size_type pos = str.find_first_of(delimiters, lastPos);
while (std::string::npos != pos || std::string::npos != lastPos) {
// Found a token, add it to the vector.
tokens.push_back(str.substr(lastPos, pos - lastPos));
// Find end of delimiters. Note the "not_of"
lastPos = str.find_first_not_of(delimiters, pos);
// Push the delimiters
if ( lastPos != std::string::npos ) {
tokens.push_back(str.substr(pos, lastPos - pos));
} else if ( pos != std::string::npos ) {
tokens.push_back(str.substr(pos));
}
// Find next "non-delimiter"
pos = str.find_first_of(delimiters, lastPos);
}
}
// This routine (partially) tokenizes a units string. It substitutes
// units that need their names changed to conform to the new units system.
std::string map_trick_units_to_udunits( std::string orig_units ) {
std::vector<std::string> tokens ;
std::vector<std::string>::iterator it ;
tokenize_units(orig_units, tokens, "*/^()") ;
for( it = tokens.begin() ; it != tokens.end() ; it++ ) {
std::string power ;
char last_char = *((*it).rbegin()) ;
// tokens can end in powers of 2 or 3 in the old system.
// save the power if it is the last character
if(last_char == '2' || last_char == '3') {
(*it).erase((*it).length() -1) ;
}
// look up the unit to see if it needs to be converted.
std::map< std::string, std::string>::iterator mit ;
mit = old_to_ud.find(*it) ;
if ( mit != old_to_ud.end() ) {
*it = mit->second ;
}
// put back the power after the base unit has been tested
if ((last_char == '2' || last_char == '3')) {
*it += last_char ;
}
//std::cout << " " << *it << std::endl ;
}
std::string new_units = std::accumulate( tokens.begin(),tokens.end(), std::string("") );
return new_units ;
}

View File

@ -43,11 +43,11 @@ std::string Trick::UnitsMap::get_units( std::string param ) {
/**
* @par Design Details:
* @li Finds the specified variable in the map and returns the units of the found variable.
* If the variable can not be found, returns "--" (unitless).
* If the variable can not be found, returns "1" (unitless).
*/
if ( param_units.find(param) != param_units.end() ) {
return(std::string(param_units[param])) ;
} else {
return(std::string("--")) ;
return(std::string("1")) ;
}
}

View File

@ -136,6 +136,7 @@
#include "trick/vval.h"
#include "trick/Flag.h"
#include "trick/Unit.hh"
#include "trick/UdUnits.hh"
#ifdef USE_ER7_UTILS_INTEGRATORS
#include "er7_utils/integration/core/include/integrator_constructor_factory.hh"

View File

@ -1,80 +1,73 @@
#include <Python.h>
#include <iostream>
#include <udunits2/udunits2.h>
#include "trick/Unit.hh"
#include "trick/UdUnits.hh"
int convert_united_value( std::string & to_units , std::string & from_units , long long * val ) {
if ( from_units.compare("--") ) {
try {
Unit converter(from_units.c_str()) ;
*val = (long long)converter.Convert_to( (double)(* val) , to_units.c_str()) ;
if ( from_units.compare("1") ) {
ut_unit * from = ut_parse(Trick::UdUnits::get_u_system(), from_units.c_str(), UT_ASCII) ;
if ( !from ) {
PyErr_SetString(PyExc_AttributeError,(std::string("could not covert from units "+from_units).c_str()));
return -1 ;
}
catch (Unit::CONVERSION_ERROR & ce_err ) {
ut_unit * to = ut_parse(Trick::UdUnits::get_u_system(), to_units.c_str(), UT_ASCII) ;
if ( !to ) {
PyErr_SetString(PyExc_AttributeError,(std::string("could not covert to units "+to_units).c_str()));
return -1 ;
}
cv_converter * converter = ut_get_converter(from,to) ;
if ( converter ) {
*val = (long long)cv_convert_double(converter, (double)*val ) ;
cv_free(converter) ;
} else {
PyErr_SetString(PyExc_AttributeError,"Units conversion Error");
return -1 ;
}
ut_free(from) ;
ut_free(to) ;
}
return 0 ;
}
int convert_united_value( std::string & to_units , std::string & from_units , double * val ) {
if ( from_units.compare("--") ) {
try {
Unit converter(from_units.c_str()) ;
*val = converter.Convert_to( *val , to_units.c_str()) ;
if ( from_units.compare("1") ) {
ut_unit * from = ut_parse(Trick::UdUnits::get_u_system(), from_units.c_str(), UT_ASCII) ;
if ( !from ) {
PyErr_SetString(PyExc_AttributeError,(std::string("could not covert from units "+from_units).c_str()));
return -1 ;
}
catch (Unit::CONVERSION_ERROR & ce_err ) {
ut_unit * to = ut_parse(Trick::UdUnits::get_u_system(), to_units.c_str(), UT_ASCII) ;
if ( !to ) {
PyErr_SetString(PyExc_AttributeError,(std::string("could not covert to units "+to_units).c_str()));
return -1 ;
}
cv_converter * converter = ut_get_converter(from,to) ;
if ( converter ) {
*val = cv_convert_double(converter, *val ) ;
cv_free(converter) ;
} else {
PyErr_SetString(PyExc_AttributeError,"Units conversion Error");
return -1 ;
}
ut_free(from) ;
ut_free(to) ;
}
return 0 ;
}
int scale_united_value( std::string & to_units , std::string & from_units , long long * val ) {
if ( from_units.compare("--") ) {
try {
Units_t * from = new_units(from_units.c_str()) ;
Units_t * to = new_units(to_units.c_str()) ;
UnitsConvFn_t conv_fn;
if (conv_fn_u(from, to, &conv_fn) != CONV_OK) {
throw Unit::CONVERSION_ERROR();
}
*val = (long long)(conv_fn.C[1] * (*val)) ;
free(from) ;
free(to) ;
}
catch (Unit::CONVERSION_ERROR & ce_err ) {
PyErr_SetString(PyExc_AttributeError,"Units conversion Error");
return -1 ;
}
}
return 0 ;
return convert_united_value(to_units, from_units, val) ;
}
int scale_united_value( std::string & to_units , std::string & from_units , double * val ) {
if ( from_units.compare("--") ) {
try {
Units_t * from = new_units(from_units.c_str()) ;
Units_t * to = new_units(to_units.c_str()) ;
UnitsConvFn_t conv_fn;
if (conv_fn_u(from, to, &conv_fn) != CONV_OK) {
throw Unit::CONVERSION_ERROR();
}
*val = conv_fn.C[1] * (*val) ;
free(from) ;
free(to) ;
}
catch (Unit::CONVERSION_ERROR & ce_err ) {
PyErr_SetString(PyExc_AttributeError,"Units conversion Error");
return -1 ;
}
}
return 0 ;
return convert_united_value(to_units, from_units, val) ;
}

View File

@ -11,11 +11,11 @@ char swig_double::str_output[32] ;
swig_double::swig_double() {
value = 0 ;
units = "--" ;
units = "1" ;
}
char * swig_double::__str__() {
if ( ! units.empty() && units.compare("--") ) {
if ( ! units.empty() && units.compare("1") ) {
sprintf(str_output , "%g %s", value , units.c_str()) ;
} else {
sprintf(str_output , "%g", value ) ;
@ -67,7 +67,7 @@ PyObject * swig_double::__add__( PyObject * obj1 ) {
result->units = units ;
ret = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIG_TypeQuery("swig_double *"), SWIG_POINTER_OWN);
return ret ;
}
@ -107,7 +107,7 @@ PyObject * swig_double::__sub__( PyObject * obj1 ) {
result->units = units ;
ret = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIG_TypeQuery("swig_double *"), SWIG_POINTER_OWN);
return ret ;
}
@ -123,35 +123,19 @@ PyObject * swig_double::__mul__( PyObject * obj1 ) {
result->units = units ;
} else if (SWIG_IsOK(SWIG_ConvertPtr(obj1, &argp2,SWIG_TypeQuery("swig_int *"), 0 ))) {
swig_int * temp_m = reinterpret_cast< swig_int * >(argp2) ;
if ( !temp_m->units.compare("--")) {
result->value = value * temp_m->value ;
result->units = units ;
} else if ( !units.compare("--")) {
result->value = value * temp_m->value ;
result->units = temp_m->units ;
} else {
PyErr_SetString(PyExc_TypeError,"Operation must contain at least one unit-less value. Cannot create new unit-ed type.");
return NULL ;
}
result->value = value * temp_m->value ;
result->units = units + "*(" + temp_m->units + ")";
} else if (SWIG_IsOK(SWIG_ConvertPtr(obj1, &argp2,SWIG_TypeQuery("swig_double *"), 0 ))) {
swig_double * temp_m = reinterpret_cast< swig_double * >(argp2) ;
if ( !temp_m->units.compare("--")) {
result->value = value * temp_m->value ;
result->units = units ;
} else if ( !units.compare("--")) {
result->value = value * temp_m->value ;
result->units = temp_m->units ;
} else {
PyErr_SetString(PyExc_TypeError,"Operation must contain at least one unit-less value. Cannot create new unit-ed type.");
return NULL ;
}
result->value = value * temp_m->value ;
result->units = units + "*(" + temp_m->units + ")";
} else if ( PyInt_Check(obj1) ) {
result->value = value * PyInt_AsLong(obj1) ;
result->units = units ;
}
ret = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIG_TypeQuery("swig_double *"), SWIG_POINTER_OWN);
return ret ;
}
@ -166,27 +150,17 @@ PyObject * swig_double::__div__( PyObject * obj1 ) {
result->value = value / PyFloat_AsDouble(obj1) ;
} else if (SWIG_IsOK(SWIG_ConvertPtr(obj1, &argp2,SWIG_TypeQuery("swig_int *"), 0 ))) {
swig_int * temp_m = reinterpret_cast< swig_int * >(argp2) ;
if ( !temp_m->units.compare("--")) {
result->value = value / temp_m->value ;
} else {
PyErr_SetString(PyExc_TypeError,"Divisor must be unitless. Cannot create new unit-ed type.");
return NULL ;
}
result->value = value / temp_m->value ;
result->units = units ;
result->units = units + "/(" + temp_m->units + ")";
} else if (SWIG_IsOK(SWIG_ConvertPtr(obj1, &argp2,SWIG_TypeQuery("swig_double *"), 0 ))) {
swig_double * temp_m = reinterpret_cast< swig_double * >(argp2) ;
if ( !temp_m->units.compare("--")) {
result->value = value / temp_m->value ;
} else {
PyErr_SetString(PyExc_TypeError,"Divisor must be unitless. Cannot create new unit-ed type.");
return NULL ;
}
result->value = value / temp_m->value ;
result->units = units + "/(" + temp_m->units + ")";
} else if ( PyInt_Check(obj1) ) {
result->value = value / PyInt_AsLong(obj1) ;
}
result->units = units ;
ret = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIG_TypeQuery("swig_double *"), SWIG_POINTER_OWN);
return ret ;
}

View File

@ -11,11 +11,11 @@ char swig_int::str_output[32] ;
swig_int::swig_int() {
value = 0 ;
units = "--" ;
units = "1" ;
}
char * swig_int::__str__() {
if ( ! units.empty() && units.compare("--") ) {
if ( ! units.empty() && units.compare("1") ) {
sprintf(str_output , "%lld %s", value , units.c_str()) ;
} else {
sprintf(str_output , "%lld", value ) ;